{"version":3,"sources":["../../src/memory/index.ts","../../src/memory/store.ts","../../src/memory/sqlite.ts"],"sourcesContent":["export { InMemoryStore } from \"./store.js\";\nexport { SQLiteStore } from \"./sqlite.js\";\nexport type { MemoryStore } from \"./store.js\";\n","import type { Message } from \"../types.js\";\n\nexport interface MemoryStore {\n  getThread(threadId: string): Promise<Message[]>;\n  saveThread(threadId: string, messages: Message[]): Promise<void>;\n  appendMessage(threadId: string, message: Message): Promise<void>;\n  listThreads(opts?: { limit?: number; before?: string }): Promise<Array<{ id: string; updatedAt: number; messageCount: number }>>;\n  deleteThread(threadId: string): Promise<void>;\n}\n\nexport class InMemoryStore implements MemoryStore {\n  private threads: Map<string, { messages: Message[]; updatedAt: number }> = new Map();\n\n  async getThread(threadId: string): Promise<Message[]> {\n    return this.threads.get(threadId)?.messages ?? [];\n  }\n\n  async saveThread(threadId: string, messages: Message[]): Promise<void> {\n    this.threads.set(threadId, { messages, updatedAt: Date.now() });\n  }\n\n  async appendMessage(threadId: string, message: Message): Promise<void> {\n    const thread = this.threads.get(threadId);\n    if (thread) {\n      thread.messages.push(message);\n      thread.updatedAt = Date.now();\n    } else {\n      this.threads.set(threadId, { messages: [message], updatedAt: Date.now() });\n    }\n  }\n\n  async listThreads(opts?: { limit?: number; before?: string }): Promise<Array<{ id: string; updatedAt: number; messageCount: number }>> {\n    let entries = Array.from(this.threads.entries())\n      .map(([id, data]) => ({ id, updatedAt: data.updatedAt, messageCount: data.messages.length }))\n      .sort((a, b) => b.updatedAt - a.updatedAt);\n    if (opts?.before) entries = entries.filter(e => e.updatedAt < parseInt(opts.before as string, 10));\n    return entries.slice(0, opts?.limit ?? 100);\n  }\n\n  async deleteThread(threadId: string): Promise<void> {\n    this.threads.delete(threadId);\n  }\n}\n","import type { MemoryStore } from \"./store.js\";\nimport type { Message } from \"../types.js\";\nimport { InMemoryStore } from \"./store.js\";\n\nfunction jsonSerialize(messages: Message[]): string {\n  return JSON.stringify(messages, (_, value) => {\n    if (value === undefined) return \"__UNDEFINED__\";\n    return value;\n  });\n}\n\nfunction jsonDeserialize(str: string): Message[] {\n  return JSON.parse(str, (_, value) => {\n    if (value === \"__UNDEFINED__\") return undefined;\n    return value;\n  });\n}\n\nexport class SQLiteStore implements MemoryStore {\n  private store: MemoryStore;\n\n  constructor(dbPath?: string) {\n    try {\n      const Database = require(\"better-sqlite3\");\n      const db = new Database(dbPath ?? \"./synth-memory.db\");\n      db.pragma(\"journal_mode = WAL\");\n      db.exec(`\n        CREATE TABLE IF NOT EXISTS threads (\n          id TEXT PRIMARY KEY,\n          messages TEXT NOT NULL,\n          updated_at INTEGER NOT NULL,\n          message_count INTEGER NOT NULL DEFAULT 0\n        )\n      `);\n      try {\n        db.exec(\"ALTER TABLE threads ADD COLUMN message_count INTEGER NOT NULL DEFAULT 0\");\n      } catch {\n        // column already exists\n      }\n      this.store = {\n        async getThread(threadId: string): Promise<Message[]> {\n          const row = db.prepare(\"SELECT messages FROM threads WHERE id = ?\").get(threadId);\n          if (!row) return [];\n          return jsonDeserialize(row.messages);\n        },\n        async saveThread(threadId: string, messages: Message[]): Promise<void> {\n          const now = Date.now();\n          const json = jsonSerialize(messages);\n          const msgCount = messages.length;\n          const exists = db.prepare(\"SELECT 1 FROM threads WHERE id = ?\").get(threadId);\n          const stmt = exists\n            ? db.prepare(\"UPDATE threads SET messages = ?, updated_at = ?, message_count = ? WHERE id = ?\")\n            : db.prepare(\"INSERT INTO threads (id, messages, updated_at, message_count) VALUES (?, ?, ?, ?)\");\n          stmt.run(json, now, msgCount, threadId);\n        },\n        async appendMessage(threadId: string, message: Message): Promise<void> {\n          const row = db.prepare(\"SELECT messages FROM threads WHERE id = ?\").get(threadId);\n          const messages: Message[] = row ? jsonDeserialize(row.messages) : [];\n          messages.push(message);\n          const json = jsonSerialize(messages);\n          const now = Date.now();\n          db.prepare(\"INSERT INTO threads (id, messages, updated_at, message_count) VALUES (?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET messages = excluded.messages, updated_at = excluded.updated_at, message_count = excluded.message_count\")\n            .run(threadId, json, now, messages.length);\n        },\n        async listThreads(opts?: { limit?: number; before?: string }): Promise<Array<{ id: string; updatedAt: number; messageCount: number }>> {\n          const rows = db.prepare(\"SELECT id, updated_at, message_count FROM threads ORDER BY updated_at DESC\").all();\n          let results = rows.map((r: any) => ({ id: r.id, updatedAt: r.updated_at, messageCount: r.message_count }));\n          if (opts?.before) results = results.filter((e: { updatedAt: number }) => e.updatedAt < parseInt(opts.before!, 10));\n          return results.slice(0, opts?.limit ?? 100);\n        },\n        async deleteThread(threadId: string): Promise<void> {\n          db.prepare(\"DELETE FROM threads WHERE id = ?\").run(threadId);\n        },\n      };\n    } catch {\n      console.warn(\"[synth] better-sqlite3 not available, falling back to in-memory store. Install it with: npm install better-sqlite3\");\n      this.store = new InMemoryStore();\n    }\n  }\n\n  async getThread(threadId: string): Promise<Message[]> { return this.store.getThread(threadId); }\n  async saveThread(threadId: string, messages: Message[]): Promise<void> { return this.store.saveThread(threadId, messages); }\n  async appendMessage(threadId: string, message: Message): Promise<void> { return this.store.appendMessage(threadId, message); }\n  async listThreads(opts?: { limit?: number; before?: string }): Promise<Array<{ id: string; updatedAt: number; messageCount: number }>> { return this.store.listThreads(opts); }\n  async deleteThread(threadId: string): Promise<void> { return this.store.deleteThread(threadId); }\n}\n"],"mappings":"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","names":[]}