{"version":3,"file":"file_system.cjs","names":["BaseListChatMessageHistory","fs"],"sources":["../../../src/stores/message/file_system.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport { BaseListChatMessageHistory } from \"@langchain/core/chat_history\";\nimport {\n  BaseMessage,\n  StoredMessage,\n  mapChatMessagesToStoredMessages,\n  mapStoredMessagesToChatMessages,\n} from \"@langchain/core/messages\";\n\nexport const FILE_HISTORY_DEFAULT_FILE_PATH = \".history/history.json\";\n\n/**\n * Represents a lightweight file chat session.\n */\nexport type FileChatSession = {\n  id: string;\n  context: Record<string, unknown>;\n};\n\n/**\n * Represents a stored chat session.\n */\nexport type StoredFileChatSession = FileChatSession & {\n  messages: StoredMessage[];\n};\n\n/**\n * Type for the store of chat sessions.\n */\nexport type FileChatStore = {\n  [userId: string]: Record<string, StoredFileChatSession>;\n};\n\n/**\n * Type for the input to the `FileSystemChatMessageHistory` constructor.\n */\nexport interface FileSystemChatMessageHistoryInput {\n  sessionId: string;\n  userId?: string;\n  filePath?: string;\n}\n\nlet store: FileChatStore;\n\n/**\n * Store chat message history using a local JSON file.\n * For demo and development purposes only.\n *\n * @example\n * ```typescript\n *  const model = new ChatOpenAI({\n *   model: \"gpt-3.5-turbo\",\n *   temperature: 0,\n * });\n * const prompt = ChatPromptTemplate.fromMessages([\n *   [\n *     \"system\",\n *     \"You are a helpful assistant. Answer all questions to the best of your ability.\",\n *   ],\n *   [\"placeholder\", \"chat_history\"],\n *   [\"human\", \"{input}\"],\n * ]);\n *\n * const chain = prompt.pipe(model).pipe(new StringOutputParser());\n * const chainWithHistory = new RunnableWithMessageHistory({\n *   runnable: chain,\n *  inputMessagesKey: \"input\",\n *  historyMessagesKey: \"chat_history\",\n *   getMessageHistory: async (sessionId) => {\n *     const chatHistory = new FileSystemChatMessageHistory({\n *       sessionId: sessionId,\n *       userId: \"userId\",  // Optional\n *     })\n *     return chatHistory;\n *   },\n * });\n * await chainWithHistory.invoke(\n *   { input: \"What did I just say my name was?\" },\n *   { configurable: { sessionId: \"session-id\" } }\n * );\n * ```\n */\nexport class FileSystemChatMessageHistory extends BaseListChatMessageHistory {\n  lc_namespace = [\"langchain\", \"stores\", \"message\", \"file\"];\n\n  private sessionId: string;\n\n  private userId: string;\n\n  private filePath: string;\n\n  constructor(chatHistoryInput: FileSystemChatMessageHistoryInput) {\n    super();\n\n    this.sessionId = chatHistoryInput.sessionId;\n    this.userId = chatHistoryInput.userId ?? \"\";\n    this.filePath = chatHistoryInput.filePath ?? FILE_HISTORY_DEFAULT_FILE_PATH;\n  }\n\n  private async init(): Promise<void> {\n    if (store) {\n      return;\n    }\n    try {\n      store = await this.loadStore();\n    } catch (error) {\n      console.error(\"Error initializing FileSystemChatMessageHistory:\", error);\n      throw error;\n    }\n  }\n\n  protected async loadStore(): Promise<FileChatStore> {\n    try {\n      const store = await fs.readFile(this.filePath, \"utf-8\");\n      return JSON.parse(store) as FileChatStore;\n    } catch (_error) {\n      const error = _error as NodeJS.ErrnoException;\n      if (error.code === \"ENOENT\") {\n        return {};\n      }\n      throw new Error(\n        `Error loading FileSystemChatMessageHistory store: ${error}`\n      );\n    }\n  }\n\n  protected async saveStore(): Promise<void> {\n    try {\n      await fs.mkdir(dirname(this.filePath), { recursive: true });\n      await fs.writeFile(this.filePath, JSON.stringify(store));\n    } catch (error) {\n      throw new Error(\n        `Error saving FileSystemChatMessageHistory store: ${error}`\n      );\n    }\n  }\n\n  async getMessages(): Promise<BaseMessage[]> {\n    await this.init();\n    const messages = store[this.userId]?.[this.sessionId]?.messages ?? [];\n    return mapStoredMessagesToChatMessages(messages);\n  }\n\n  async addMessage(message: BaseMessage): Promise<void> {\n    await this.init();\n    const messages = await this.getMessages();\n    messages.push(message);\n    const storedMessages = mapChatMessagesToStoredMessages(messages);\n    store[this.userId] ??= {};\n    store[this.userId][this.sessionId] = {\n      ...store[this.userId][this.sessionId],\n      messages: storedMessages,\n    };\n    await this.saveStore();\n  }\n\n  async clear(): Promise<void> {\n    await this.init();\n    if (store[this.userId]) {\n      delete store[this.userId][this.sessionId];\n    }\n    await this.saveStore();\n  }\n\n  async getContext(): Promise<Record<string, unknown>> {\n    await this.init();\n    return store[this.userId]?.[this.sessionId]?.context ?? {};\n  }\n\n  async setContext(context: Record<string, unknown>): Promise<void> {\n    await this.init();\n    store[this.userId] ??= {};\n    store[this.userId][this.sessionId] = {\n      ...store[this.userId][this.sessionId],\n      context,\n    };\n    await this.saveStore();\n  }\n\n  async clearAllSessions() {\n    await this.init();\n    delete store[this.userId];\n    await this.saveStore();\n  }\n\n  async getAllSessions(): Promise<FileChatSession[]> {\n    await this.init();\n    const userSessions = store[this.userId]\n      ? Object.entries(store[this.userId]).map(([id, session]) => ({\n          id,\n          context: session.context,\n        }))\n      : [];\n    return userSessions;\n  }\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,iCAAiC;AAiC9C,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCJ,IAAa,+BAAb,cAAkDA,6BAAAA,2BAA2B;CAC3E,eAAe;EAAC;EAAa;EAAU;EAAW;EAAO;CAEzD;CAEA;CAEA;CAEA,YAAY,kBAAqD;AAC/D,SAAO;AAEP,OAAK,YAAY,iBAAiB;AAClC,OAAK,SAAS,iBAAiB,UAAU;AACzC,OAAK,WAAW,iBAAiB,YAAA;;CAGnC,MAAc,OAAsB;AAClC,MAAI,MACF;AAEF,MAAI;AACF,WAAQ,MAAM,KAAK,WAAW;WACvB,OAAO;AACd,WAAQ,MAAM,oDAAoD,MAAM;AACxE,SAAM;;;CAIV,MAAgB,YAAoC;AAClD,MAAI;GACF,MAAM,QAAQ,MAAMC,QAAAA,SAAG,SAAS,KAAK,UAAU,QAAQ;AACvD,UAAO,KAAK,MAAM,MAAM;WACjB,QAAQ;GACf,MAAM,QAAQ;AACd,OAAI,MAAM,SAAS,SACjB,QAAO,EAAE;AAEX,SAAM,IAAI,MACR,qDAAqD,QACtD;;;CAIL,MAAgB,YAA2B;AACzC,MAAI;AACF,SAAMA,QAAAA,SAAG,OAAA,GAAA,UAAA,SAAc,KAAK,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;AAC3D,SAAMA,QAAAA,SAAG,UAAU,KAAK,UAAU,KAAK,UAAU,MAAM,CAAC;WACjD,OAAO;AACd,SAAM,IAAI,MACR,oDAAoD,QACrD;;;CAIL,MAAM,cAAsC;AAC1C,QAAM,KAAK,MAAM;AAEjB,UAAA,GAAA,yBAAA,iCADiB,MAAM,KAAK,UAAU,KAAK,YAAY,YAAY,EAAE,CACrB;;CAGlD,MAAM,WAAW,SAAqC;AACpD,QAAM,KAAK,MAAM;EACjB,MAAM,WAAW,MAAM,KAAK,aAAa;AACzC,WAAS,KAAK,QAAQ;EACtB,MAAM,kBAAA,GAAA,yBAAA,iCAAiD,SAAS;AAChE,QAAM,KAAK,YAAY,EAAE;AACzB,QAAM,KAAK,QAAQ,KAAK,aAAa;GACnC,GAAG,MAAM,KAAK,QAAQ,KAAK;GAC3B,UAAU;GACX;AACD,QAAM,KAAK,WAAW;;CAGxB,MAAM,QAAuB;AAC3B,QAAM,KAAK,MAAM;AACjB,MAAI,MAAM,KAAK,QACb,QAAO,MAAM,KAAK,QAAQ,KAAK;AAEjC,QAAM,KAAK,WAAW;;CAGxB,MAAM,aAA+C;AACnD,QAAM,KAAK,MAAM;AACjB,SAAO,MAAM,KAAK,UAAU,KAAK,YAAY,WAAW,EAAE;;CAG5D,MAAM,WAAW,SAAiD;AAChE,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,YAAY,EAAE;AACzB,QAAM,KAAK,QAAQ,KAAK,aAAa;GACnC,GAAG,MAAM,KAAK,QAAQ,KAAK;GAC3B;GACD;AACD,QAAM,KAAK,WAAW;;CAGxB,MAAM,mBAAmB;AACvB,QAAM,KAAK,MAAM;AACjB,SAAO,MAAM,KAAK;AAClB,QAAM,KAAK,WAAW;;CAGxB,MAAM,iBAA6C;AACjD,QAAM,KAAK,MAAM;AAOjB,SANqB,MAAM,KAAK,UAC5B,OAAO,QAAQ,MAAM,KAAK,QAAQ,CAAC,KAAK,CAAC,IAAI,cAAc;GACzD;GACA,SAAS,QAAQ;GAClB,EAAE,GACH,EAAE"}