{"version":3,"file":"planetscale.cjs","names":["BaseListChatMessageHistory","PlanetScaleClient"],"sources":["../../../src/stores/message/planetscale.ts"],"sourcesContent":["import {\n  Client as PlanetScaleClient,\n  Config as PlanetScaleConfig,\n  Connection as PlanetScaleConnection,\n} from \"@planetscale/database\";\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 * Type definition for the input parameters required when instantiating a\n * PlanetScaleChatMessageHistory object.\n */\nexport type PlanetScaleChatMessageHistoryInput = {\n  tableName?: string;\n  sessionId: string;\n  config?: PlanetScaleConfig;\n  client?: PlanetScaleClient;\n};\n\n/**\n * Interface for the data transfer object used when selecting stored\n * messages from the PlanetScale database.\n */\ninterface selectStoredMessagesDTO {\n  id: string;\n  session_id: string;\n  type: string;\n  content: string;\n  role: string | null;\n  name: string | null;\n  additional_kwargs: string;\n}\n\n/**\n * Class for storing and retrieving chat message history from a\n * PlanetScale database. Extends the BaseListChatMessageHistory class.\n * @example\n * ```typescript\n * const chatHistory = new PlanetScaleChatMessageHistory({\n *   tableName: \"stored_message\",\n *   sessionId: \"lc-example\",\n *   config: {\n *     url: \"ADD_YOURS_HERE\",\n *   },\n * });\n * const chain = new ConversationChain({\n *   llm: new ChatOpenAI({ model: \"gpt-4o-mini\" }),\n *   memory: chatHistory,\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 PlanetScaleChatMessageHistory extends BaseListChatMessageHistory {\n  lc_namespace = [\"langchain\", \"stores\", \"message\", \"planetscale\"];\n\n  get lc_secrets() {\n    return {\n      \"config.host\": \"PLANETSCALE_HOST\",\n      \"config.username\": \"PLANETSCALE_USERNAME\",\n      \"config.password\": \"PLANETSCALE_PASSWORD\",\n      \"config.url\": \"PLANETSCALE_DATABASE_URL\",\n    };\n  }\n\n  public client: PlanetScaleClient;\n\n  private connection: PlanetScaleConnection;\n\n  private tableName: string;\n\n  private sessionId: string;\n\n  private tableInitialized: boolean;\n\n  constructor(fields: PlanetScaleChatMessageHistoryInput) {\n    super(fields);\n\n    const { sessionId, config, client, tableName } = fields;\n\n    if (client) {\n      this.client = client;\n    } else if (config) {\n      this.client = new PlanetScaleClient(config);\n    } else {\n      throw new Error(\n        \"Either a client or config must be provided to PlanetScaleChatMessageHistory\"\n      );\n    }\n\n    this.connection = this.client.connection();\n\n    this.tableName = tableName || \"langchain_chat_histories\";\n    this.tableInitialized = false;\n    this.sessionId = sessionId;\n  }\n\n  /**\n   * Private method to ensure that the necessary table exists in the\n   * PlanetScale database before performing any operations. If the table\n   * does not exist, it is created.\n   * @returns Promise that resolves to void.\n   */\n  private async ensureTable(): Promise<void> {\n    if (this.tableInitialized) {\n      return;\n    }\n\n    const query = `CREATE TABLE IF NOT EXISTS ${this.tableName} (id BINARY(16) PRIMARY KEY, session_id VARCHAR(255), type VARCHAR(255), content VARCHAR(255), role VARCHAR(255), name VARCHAR(255), additional_kwargs VARCHAR(255));`;\n\n    await this.connection.execute(query);\n\n    const indexQuery = `ALTER TABLE ${this.tableName} MODIFY id BINARY(16) DEFAULT (UUID_TO_BIN(UUID()));`;\n\n    await this.connection.execute(indexQuery);\n\n    this.tableInitialized = true;\n  }\n\n  /**\n   * Method to retrieve all messages from the PlanetScale database for the\n   * current session.\n   * @returns Promise that resolves to an array of BaseMessage objects.\n   */\n  async getMessages(): Promise<BaseMessage[]> {\n    await this.ensureTable();\n\n    const query = `SELECT * FROM ${this.tableName} WHERE session_id = :session_id`;\n    const params = {\n      session_id: this.sessionId,\n    };\n\n    const rawStoredMessages = await this.connection.execute(query, params);\n    const storedMessagesObject =\n      rawStoredMessages.rows as unknown as selectStoredMessagesDTO[];\n\n    const orderedMessages: StoredMessage[] = storedMessagesObject.map(\n      (message) => {\n        const data = {\n          content: message.content,\n          additional_kwargs: JSON.parse(message.additional_kwargs),\n        } as StoredMessageData;\n\n        if (message.role) {\n          data.role = message.role;\n        }\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   * Method to add a new message to the PlanetScale database for the current\n   * session.\n   * @param message The BaseMessage object to be added to the database.\n   * @returns Promise that resolves to void.\n   */\n  async addMessage(message: BaseMessage): Promise<void> {\n    await this.ensureTable();\n\n    const messageToAdd = mapChatMessagesToStoredMessages([message]);\n\n    const query = `INSERT INTO ${this.tableName} (session_id, type, content, role, name, additional_kwargs) VALUES (:session_id, :type, :content, :role, :name, :additional_kwargs)`;\n\n    const params = {\n      session_id: 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      additional_kwargs: JSON.stringify(messageToAdd[0].data.additional_kwargs),\n    };\n\n    await this.connection.execute(query, params);\n  }\n\n  /**\n   * Method to delete all messages from the PlanetScale database for the\n   * current session.\n   * @returns Promise that resolves to void.\n   */\n  async clear(): Promise<void> {\n    await this.ensureTable();\n\n    const query = `DELETE FROM ${this.tableName} WHERE session_id = :session_id`;\n    const params = {\n      session_id: this.sessionId,\n    };\n    await this.connection.execute(query, params);\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,IAAa,gCAAb,cAAmDA,6BAAAA,2BAA2B;CAC5E,eAAe;EAAC;EAAa;EAAU;EAAW;EAAc;CAEhE,IAAI,aAAa;AACf,SAAO;GACL,eAAe;GACf,mBAAmB;GACnB,mBAAmB;GACnB,cAAc;GACf;;CAGH;CAEA;CAEA;CAEA;CAEA;CAEA,YAAY,QAA4C;AACtD,QAAM,OAAO;EAEb,MAAM,EAAE,WAAW,QAAQ,QAAQ,cAAc;AAEjD,MAAI,OACF,MAAK,SAAS;WACL,OACT,MAAK,SAAS,IAAIC,sBAAAA,OAAkB,OAAO;MAE3C,OAAM,IAAI,MACR,8EACD;AAGH,OAAK,aAAa,KAAK,OAAO,YAAY;AAE1C,OAAK,YAAY,aAAa;AAC9B,OAAK,mBAAmB;AACxB,OAAK,YAAY;;;;;;;;CASnB,MAAc,cAA6B;AACzC,MAAI,KAAK,iBACP;EAGF,MAAM,QAAQ,8BAA8B,KAAK,UAAU;AAE3D,QAAM,KAAK,WAAW,QAAQ,MAAM;EAEpC,MAAM,aAAa,eAAe,KAAK,UAAU;AAEjD,QAAM,KAAK,WAAW,QAAQ,WAAW;AAEzC,OAAK,mBAAmB;;;;;;;CAQ1B,MAAM,cAAsC;AAC1C,QAAM,KAAK,aAAa;EAExB,MAAM,QAAQ,iBAAiB,KAAK,UAAU;EAC9C,MAAM,SAAS,EACb,YAAY,KAAK,WAClB;AA2BD,UAAA,GAAA,yBAAA,kCAzB0B,MAAM,KAAK,WAAW,QAAQ,OAAO,OAAO,EAElD,KAE0C,KAC3D,YAAY;GACX,MAAM,OAAO;IACX,SAAS,QAAQ;IACjB,mBAAmB,KAAK,MAAM,QAAQ,kBAAkB;IACzD;AAED,OAAI,QAAQ,KACV,MAAK,OAAO,QAAQ;AAGtB,OAAI,QAAQ,KACV,MAAK,OAAO,QAAQ;AAGtB,UAAO;IACL,MAAM,QAAQ;IACd;IACD;IAEJ,CACsD;;;;;;;;CASzD,MAAM,WAAW,SAAqC;AACpD,QAAM,KAAK,aAAa;EAExB,MAAM,gBAAA,GAAA,yBAAA,iCAA+C,CAAC,QAAQ,CAAC;EAE/D,MAAM,QAAQ,eAAe,KAAK,UAAU;EAE5C,MAAM,SAAS;GACb,YAAY,KAAK;GACjB,MAAM,aAAa,GAAG;GACtB,SAAS,aAAa,GAAG,KAAK;GAC9B,MAAM,aAAa,GAAG,KAAK;GAC3B,MAAM,aAAa,GAAG,KAAK;GAC3B,mBAAmB,KAAK,UAAU,aAAa,GAAG,KAAK,kBAAkB;GAC1E;AAED,QAAM,KAAK,WAAW,QAAQ,OAAO,OAAO;;;;;;;CAQ9C,MAAM,QAAuB;AAC3B,QAAM,KAAK,aAAa;EAExB,MAAM,QAAQ,eAAe,KAAK,UAAU;EAC5C,MAAM,SAAS,EACb,YAAY,KAAK,WAClB;AACD,QAAM,KAAK,WAAW,QAAQ,OAAO,OAAO"}