{"version":3,"file":"xata.cjs","names":["BaseListChatMessageHistory","BaseClient","XataApiClient"],"sources":["../../../src/stores/message/xata.ts"],"sourcesContent":["import {\n  BaseClient,\n  BaseClientOptions,\n  GetTableSchemaResponse,\n  Schemas,\n  XataApiClient,\n  parseWorkspacesUrlParts,\n} from \"@xata.io/client\";\nimport { BaseListChatMessageHistory } from \"@langchain/core/chat_history\";\nimport {\n  BaseMessage,\n  StoredMessage,\n  StoredMessageData,\n  mapChatMessagesToStoredMessages,\n  mapStoredMessagesToChatMessages,\n} from \"@langchain/core/messages\";\n\n/**\n * An object type that represents the input for the XataChatMessageHistory\n * class.\n */\nexport type XataChatMessageHistoryInput<XataClient> = {\n  sessionId: string;\n  config?: BaseClientOptions;\n  client?: XataClient;\n  table?: string;\n  createTable?: boolean;\n  apiKey?: string;\n};\n\n/**\n * An interface that represents the data transfer object for stored\n * messages.\n */\ninterface storedMessagesDTO {\n  id: string;\n  sessionId: string;\n  type: string;\n  content: string;\n  role?: string;\n  name?: string;\n  additionalKwargs: string;\n}\n\nconst chatMemoryColumns: Schemas.Column[] = [\n  { name: \"sessionId\", type: \"string\" },\n  { name: \"type\", type: \"string\" },\n  { name: \"role\", type: \"string\" },\n  { name: \"content\", type: \"text\" },\n  { name: \"name\", type: \"string\" },\n  { name: \"additionalKwargs\", type: \"text\" },\n];\n\n/**\n * A class for managing chat message history using Xata.io client. It\n * extends the BaseListChatMessageHistory class and provides methods to\n * get, add, and clear messages. It also ensures the existence of a table\n * where the chat messages are stored.\n * @example\n * ```typescript\n * const chatHistory = new XataChatMessageHistory({\n *   table: \"messages\",\n *   sessionId: new Date().toISOString(),\n *   client: new BaseClient({\n *     databaseURL: process.env.XATA_DB_URL,\n *     apiKey: process.env.XATA_API_KEY,\n *     branch: \"main\",\n *   }),\n *   apiKey: process.env.XATA_API_KEY,\n * });\n *\n * const chain = new ConversationChain({\n *   llm: new ChatOpenAI({ model: \"gpt-4o-mini\" }),\n *   memory: new BufferMemory({ chatHistory }),\n * });\n *\n * const response = await chain.invoke({\n *   input: \"What did I just say my name was?\",\n * });\n * console.log({ response });\n * ```\n */\nexport class XataChatMessageHistory<\n  XataClient extends BaseClient,\n> extends BaseListChatMessageHistory {\n  lc_namespace = [\"langchain\", \"stores\", \"message\", \"xata\"];\n\n  public client: XataClient;\n\n  private sessionId: string;\n\n  private table: string;\n\n  private tableInitialized: boolean;\n\n  private createTable: boolean;\n\n  private apiClient: XataApiClient;\n\n  constructor(fields: XataChatMessageHistoryInput<XataClient>) {\n    super(fields);\n\n    const { sessionId, config, client, table } = fields;\n    this.sessionId = sessionId;\n    this.table = table || \"memory\";\n    if (client) {\n      this.client = client;\n    } else if (config) {\n      this.client = new BaseClient(config) as XataClient;\n    } else {\n      throw new Error(\n        \"Either a client or a config must be provided to XataChatMessageHistoryInput\"\n      );\n    }\n    if (fields.createTable !== false) {\n      this.createTable = true;\n      const apiKey = fields.apiKey || fields.config?.apiKey;\n      if (!apiKey) {\n        throw new Error(\n          \"If createTable is set, an apiKey must be provided to XataChatMessageHistoryInput, either directly or through the config object\"\n        );\n      }\n      this.apiClient = new XataApiClient({ apiKey });\n    } else {\n      this.createTable = false;\n    }\n    this.tableInitialized = false;\n  }\n\n  /**\n   * Retrieves all messages associated with the session ID, ordered by\n   * creation time.\n   * @returns A promise that resolves to an array of BaseMessage instances.\n   */\n  async getMessages(): Promise<BaseMessage[]> {\n    await this.ensureTable();\n    const records = await this.client.db[this.table]\n      .filter({ sessionId: this.sessionId })\n      .sort(\"xata.createdAt\", \"asc\")\n      .getAll();\n\n    const rawStoredMessages = records as unknown as storedMessagesDTO[];\n    const orderedMessages: StoredMessage[] = rawStoredMessages.map(\n      (message: storedMessagesDTO) => {\n        const data = {\n          content: message.content,\n          additional_kwargs: JSON.parse(message.additionalKwargs),\n        } as StoredMessageData;\n        if (message.role) {\n          data.role = message.role;\n        }\n        if (message.name) {\n          data.name = message.name;\n        }\n\n        return {\n          type: message.type,\n          data,\n        };\n      }\n    );\n    return mapStoredMessagesToChatMessages(orderedMessages);\n  }\n\n  /**\n   * Adds a new message to the database.\n   * @param message The BaseMessage instance to be added.\n   * @returns A promise that resolves when the message has been added.\n   */\n  async addMessage(message: BaseMessage): Promise<void> {\n    await this.ensureTable();\n    const messageToAdd = mapChatMessagesToStoredMessages([message]);\n    await this.client.db[this.table].create({\n      sessionId: this.sessionId,\n      type: messageToAdd[0].type,\n      content: messageToAdd[0].data.content,\n      role: messageToAdd[0].data.role,\n      name: messageToAdd[0].data.name,\n      additionalKwargs: JSON.stringify(messageToAdd[0].data.additional_kwargs),\n    });\n  }\n\n  /**\n   * Deletes all messages associated with the session ID.\n   * @returns A promise that resolves when the messages have been deleted.\n   */\n  async clear(): Promise<void> {\n    await this.ensureTable();\n    const records = await this.client.db[this.table]\n      .select([\"id\"])\n      .filter({ sessionId: this.sessionId })\n      .getAll();\n    const ids = records.map((m) => m.id);\n    await this.client.db[this.table].delete(ids);\n  }\n\n  /**\n   * Checks if the table exists and creates it if it doesn't. This method is\n   * called before any operation on the table.\n   * @returns A promise that resolves when the table has been ensured.\n   */\n  private async ensureTable(): Promise<void> {\n    if (!this.createTable) {\n      return;\n    }\n    if (this.tableInitialized) {\n      return;\n    }\n\n    const { databaseURL, branch } = await this.client.getConfig();\n    const [, , host, , database] = databaseURL.split(\"/\");\n    const urlParts = parseWorkspacesUrlParts(host);\n    if (urlParts == null) {\n      throw new Error(\"Invalid databaseURL\");\n    }\n    const { workspace, region } = urlParts;\n    const tableParams = {\n      workspace,\n      region,\n      database,\n      branch,\n      table: this.table,\n    };\n\n    let schema: GetTableSchemaResponse | null = null;\n    try {\n      schema = await this.apiClient.tables.getTableSchema(tableParams);\n    } catch {\n      // pass\n    }\n    if (schema == null) {\n      await this.apiClient.tables.createTable(tableParams);\n      await this.apiClient.tables.setTableSchema({\n        ...tableParams,\n        schema: {\n          columns: chatMemoryColumns,\n        },\n      });\n    }\n  }\n}\n"],"mappings":"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"}