Accept/expose conversation thread ID to AI actions API

Background

As part of Iteration 1: Multi-threaded conversations in the chat, this issue aims to make chat API endpoints work with multi-threads.

Key Concepts

  • duo_chat thread: A thread with conversation_type == 'duo_chat'
  • quick chat thread: A thread with another conversation_type (yet to be determined)

Implementation Details

  • Add thread_id and conversation_type to both Resolvers::Ai::ChatMessagesResolver and Mutations::Ai::Action as optional arguments.
    • (for backward compatibility, refer to conversation_type absent routes below)
  • For read operation (Resolvers::Ai::ChatMessagesResolver)
    • If conversation_type is absent, read from latest duo_chat thread.
      • If no thread is found, return empty result.
    • If conversation_type is present, fetch thread from thread_id (and return empty result if thread_id is nil).
  • For write operation (Mutations::Ai::Action)
    • If conversation_type is absent, add message to user's latest duo_chat thread.
      • If no thread is available, create a new duo_chat thread first
    • If conversation_type is present and thread_id=value, add message to the existing thread.
    • If conversation_type is present and thread_id=nil, create a new thread with specified conversation_type, and add message to it.
  • For both read and write, the thread must be scoped to the user and conversation_type to keep things secure.
  • When creating thread, it should be done in Llm::ChatService, and the thread_id should be returned as part of Mutations::Ai::Action's response.
  • thread ID is added to websocket messages
  • thread ID is also exposed for each message when listing AI messages
Edited by Mark Chao