{"version":3,"file":"xata.cjs","names":["chatMemoryColumns: Schemas.Column[]","BaseListChatMessageHistory","fields: XataChatMessageHistoryInput<XataClient>","BaseClient","XataApiClient","orderedMessages: StoredMessage[]","message: storedMessagesDTO","message: BaseMessage","schema: GetTableSchemaResponse | null"],"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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"}