"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PlanetScaleChatMessageHistory = void 0; const database_1 = require("@planetscale/database"); const chat_history_1 = require("@langchain/core/chat_history"); const messages_1 = require("@langchain/core/messages"); /** * Class for storing and retrieving chat message history from a * PlanetScale database. Extends the BaseListChatMessageHistory class. * @example * ```typescript * const chatHistory = new PlanetScaleChatMessageHistory({ * tableName: "stored_message", * sessionId: "lc-example", * config: { * url: "ADD_YOURS_HERE", * }, * }); * const chain = new ConversationChain({ * llm: new ChatOpenAI(), * memory: chatHistory, * }); * const response = await chain.invoke({ * input: "What did I just say my name was?", * }); * console.log({ response }); * ``` */ class PlanetScaleChatMessageHistory extends chat_history_1.BaseListChatMessageHistory { get lc_secrets() { return { "config.host": "PLANETSCALE_HOST", "config.username": "PLANETSCALE_USERNAME", "config.password": "PLANETSCALE_PASSWORD", "config.url": "PLANETSCALE_DATABASE_URL", }; } constructor(fields) { super(fields); Object.defineProperty(this, "lc_namespace", { enumerable: true, configurable: true, writable: true, value: ["langchain", "stores", "message", "planetscale"] }); Object.defineProperty(this, "client", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "connection", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "tableName", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "sessionId", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "tableInitialized", { enumerable: true, configurable: true, writable: true, value: void 0 }); const { sessionId, config, client, tableName } = fields; if (client) { this.client = client; } else if (config) { this.client = new database_1.Client(config); } else { throw new Error("Either a client or config must be provided to PlanetScaleChatMessageHistory"); } this.connection = this.client.connection(); this.tableName = tableName || "langchain_chat_histories"; this.tableInitialized = false; this.sessionId = sessionId; } /** * Private method to ensure that the necessary table exists in the * PlanetScale database before performing any operations. If the table * does not exist, it is created. * @returns Promise that resolves to void. */ async ensureTable() { if (this.tableInitialized) { return; } 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));`; await this.connection.execute(query); const indexQuery = `ALTER TABLE ${this.tableName} MODIFY id BINARY(16) DEFAULT (UUID_TO_BIN(UUID()));`; await this.connection.execute(indexQuery); this.tableInitialized = true; } /** * Method to retrieve all messages from the PlanetScale database for the * current session. * @returns Promise that resolves to an array of BaseMessage objects. */ async getMessages() { await this.ensureTable(); const query = `SELECT * FROM ${this.tableName} WHERE session_id = :session_id`; const params = { session_id: this.sessionId, }; const rawStoredMessages = await this.connection.execute(query, params); const storedMessagesObject = rawStoredMessages.rows; const orderedMessages = storedMessagesObject.map((message) => { const data = { content: message.content, additional_kwargs: JSON.parse(message.additional_kwargs), }; if (message.role) { data.role = message.role; } if (message.name) { data.name = message.name; } return { type: message.type, data, }; }); return (0, messages_1.mapStoredMessagesToChatMessages)(orderedMessages); } /** * Method to add a new message to the PlanetScale database for the current * session. * @param message The BaseMessage object to be added to the database. * @returns Promise that resolves to void. */ async addMessage(message) { await this.ensureTable(); const messageToAdd = (0, messages_1.mapChatMessagesToStoredMessages)([message]); const query = `INSERT INTO ${this.tableName} (session_id, type, content, role, name, additional_kwargs) VALUES (:session_id, :type, :content, :role, :name, :additional_kwargs)`; const params = { session_id: this.sessionId, type: messageToAdd[0].type, content: messageToAdd[0].data.content, role: messageToAdd[0].data.role, name: messageToAdd[0].data.name, additional_kwargs: JSON.stringify(messageToAdd[0].data.additional_kwargs), }; await this.connection.execute(query, params); } /** * Method to delete all messages from the PlanetScale database for the * current session. * @returns Promise that resolves to void. */ async clear() { await this.ensureTable(); const query = `DELETE FROM ${this.tableName} WHERE session_id = :session_id`; const params = { session_id: this.sessionId, }; await this.connection.execute(query, params); } } exports.PlanetScaleChatMessageHistory = PlanetScaleChatMessageHistory;