agents 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/chat/index.d.ts +151 -2
  2. package/dist/chat/index.js +210 -11
  3. package/dist/chat/index.js.map +1 -1
  4. package/dist/{client-BwgM3cRz.js → client-QBjFV5de.js} +161 -49
  5. package/dist/client-QBjFV5de.js.map +1 -0
  6. package/dist/client.d.ts +2 -2
  7. package/dist/{compaction-helpers-BFTBIzpK.js → compaction-helpers-BPE1_ziA.js} +1 -1
  8. package/dist/{compaction-helpers-BFTBIzpK.js.map → compaction-helpers-BPE1_ziA.js.map} +1 -1
  9. package/dist/{compaction-helpers-DkJreaDR.d.ts → compaction-helpers-CHNQeyRm.d.ts} +1 -1
  10. package/dist/{do-oauth-client-provider-C2jurFjW.d.ts → do-oauth-client-provider-31gqR33H.d.ts} +1 -1
  11. package/dist/{email-DwPlM0bQ.d.ts → email-Cql45SKP.d.ts} +1 -1
  12. package/dist/email.d.ts +2 -2
  13. package/dist/experimental/memory/session/index.d.ts +153 -82
  14. package/dist/experimental/memory/session/index.js +257 -24
  15. package/dist/experimental/memory/session/index.js.map +1 -1
  16. package/dist/experimental/memory/utils/index.d.ts +1 -1
  17. package/dist/experimental/memory/utils/index.js +1 -1
  18. package/dist/{index-BtHngIIG.d.ts → index-BPkkIqMn.d.ts} +204 -74
  19. package/dist/{index-Ua2Nfvbm.d.ts → index-DDSX-g7W.d.ts} +11 -1
  20. package/dist/index.d.ts +30 -26
  21. package/dist/index.js +2 -3049
  22. package/dist/{internal_context-DT8RxmAN.d.ts → internal_context-DuQZFvWI.d.ts} +1 -1
  23. package/dist/internal_context.d.ts +1 -1
  24. package/dist/mcp/client.d.ts +2 -2
  25. package/dist/mcp/client.js +1 -1
  26. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  27. package/dist/mcp/index.d.ts +1 -1
  28. package/dist/mcp/index.js +2 -2
  29. package/dist/observability/index.d.ts +1 -1
  30. package/dist/react.d.ts +3 -1
  31. package/dist/react.js +3 -0
  32. package/dist/react.js.map +1 -1
  33. package/dist/{retries-DXMQGhG3.d.ts → retries-B_CN5KM9.d.ts} +1 -1
  34. package/dist/retries.d.ts +1 -1
  35. package/dist/{serializable-8Jt1B04R.d.ts → serializable-DGdO8CDh.d.ts} +1 -1
  36. package/dist/serializable.d.ts +1 -1
  37. package/dist/src-B8NZxxsO.js +3217 -0
  38. package/dist/src-B8NZxxsO.js.map +1 -0
  39. package/dist/{types-C-m0II8i.d.ts → types-B9A8AU7B.d.ts} +1 -1
  40. package/dist/types.d.ts +1 -1
  41. package/dist/{workflow-types-CZNXKj_D.d.ts → workflow-types-XmOkuI7A.d.ts} +1 -1
  42. package/dist/workflow-types.d.ts +1 -1
  43. package/dist/workflows.d.ts +2 -2
  44. package/dist/workflows.js +1 -1
  45. package/package.json +12 -16
  46. package/dist/client-BwgM3cRz.js.map +0 -1
  47. package/dist/experimental/forever.d.ts +0 -64
  48. package/dist/experimental/forever.js +0 -338
  49. package/dist/experimental/forever.js.map +0 -1
  50. package/dist/index.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/experimental/memory/session/skills.ts","../../../../src/experimental/memory/session/context.ts","../../../../src/experimental/memory/session/providers/agent.ts","../../../../src/experimental/memory/session/providers/agent-context.ts","../../../../src/experimental/memory/session/session.ts","../../../../src/experimental/memory/session/manager.ts"],"sourcesContent":["/**\n * Skill Provider — on-demand keyed document collections.\n *\n * Extends ContextProvider with `load()` for on-demand content fetching\n * and a keyed `set()` for writing individual entries.\n *\n * Duck-typed: if a provider has a `load` method, it's a SkillProvider.\n */\n\nimport type { ContextProvider } from \"./context\";\n\n/**\n * Storage interface for skill collections.\n *\n * - `get()` returns metadata listing (rendered into system prompt)\n * - `load(key)` fetches full content (via load_context tool)\n * - `set(key, content, description?)` writes an entry (via set_context tool)\n */\nexport interface SkillProvider extends ContextProvider {\n load(key: string): Promise<string | null>;\n set?(key: string, content: string, description?: string): Promise<void>;\n}\n\n/**\n * Check if a provider is a SkillProvider (has a `load` method).\n */\nexport function isSkillProvider(provider: unknown): provider is SkillProvider {\n return (\n typeof provider === \"object\" &&\n provider !== null &&\n \"load\" in provider &&\n typeof (provider as SkillProvider).load === \"function\"\n );\n}\n\n// ── R2 Skill Provider ──────────────────────────────────────────────\n\n/**\n * SkillProvider backed by an R2 bucket.\n *\n * - `get()` returns a metadata listing of all skills (key + description)\n * - `load(key)` fetches a skill's full content\n * - `set(key, content, description?)` writes a skill\n *\n * Descriptions are pulled from R2 custom metadata (`description` key).\n * If a prefix is provided, it is prepended on storage operations and\n * stripped from keys in metadata.\n *\n * @example\n * ```ts\n * const skills = new R2SkillProvider(env.SKILLS_BUCKET, { prefix: \"skills/\" });\n * ```\n */\nexport class R2SkillProvider implements SkillProvider {\n private bucket: R2Bucket;\n private prefix: string;\n\n constructor(bucket: R2Bucket, options?: { prefix?: string }) {\n this.bucket = bucket;\n this.prefix = options?.prefix ?? \"\";\n }\n\n async get(): Promise<string | null> {\n const entries: string[] = [];\n let cursor: string | undefined;\n let truncated = true;\n while (truncated) {\n const listed = await this.bucket.list({\n prefix: this.prefix,\n cursor,\n include: [\"customMetadata\"]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n for (const obj of listed.objects) {\n const key = obj.key.slice(this.prefix.length);\n const desc = obj.customMetadata?.description;\n entries.push(`- ${key}${desc ? `: ${desc}` : \"\"}`);\n }\n truncated = listed.truncated;\n cursor = listed.truncated ? listed.cursor : undefined;\n }\n return entries.length > 0 ? entries.join(\"\\n\") : null;\n }\n\n async load(key: string): Promise<string | null> {\n const obj = await this.bucket.get(this.prefix + key);\n if (!obj) return null;\n return obj.text();\n }\n\n async set(key: string, content: string, description?: string): Promise<void> {\n await this.bucket.put(this.prefix + key, content, {\n customMetadata: description ? { description } : undefined\n });\n }\n}\n","/**\n * Context Block Management\n *\n * Persistent key-value blocks (MEMORY, USER, SOUL, etc.) that are:\n * - Loaded from their providers at init\n * - Frozen into a snapshot when toSystemPrompt() is called\n * - Updated via setBlock() which writes to the provider immediately\n * but does NOT update the frozen snapshot (preserves LLM prefix cache)\n * - Re-snapshotted on next toSystemPrompt() call\n *\n * Provider type determines behavior:\n * - ContextProvider (get only) → readonly block in system prompt\n * - WritableContextProvider (get+set) → writable via set_context tool\n * - SkillProvider (get+load+set?) → metadata in prompt, load_context tool\n */\n\nimport { jsonSchema, type ToolSet } from \"ai\";\nimport { estimateStringTokens } from \"../utils/tokens\";\nimport { isSkillProvider, type SkillProvider } from \"./skills\";\n\n/**\n * Base storage interface for a context block.\n * A provider with only `get()` is readonly.\n */\nexport interface ContextProvider {\n get(): Promise<string | null>;\n}\n\n/**\n * Writable context provider — extends ContextProvider with `set()`.\n * Blocks backed by this provider are writable via the `set_context` tool.\n */\nexport interface WritableContextProvider extends ContextProvider {\n set(content: string): Promise<void>;\n}\n\n/**\n * Check if a provider is writable (has a `set` method).\n */\nexport function isWritableProvider(\n provider: unknown\n): provider is WritableContextProvider {\n return (\n typeof provider === \"object\" &&\n provider !== null &&\n \"set\" in provider &&\n typeof (provider as WritableContextProvider).set === \"function\"\n );\n}\n\n/**\n * Configuration for a context block.\n */\nexport interface ContextConfig {\n /** Block label — used as key and in tool descriptions */\n label: string;\n /** Human-readable description (shown to AI in tool) */\n description?: string;\n /** Maximum tokens allowed. Enforced on set. */\n maxTokens?: number;\n /** Storage provider. Determines block behavior:\n * - ContextProvider (get only) → readonly\n * - WritableContextProvider (get+set) → writable via set_context\n * - SkillProvider (get+load+set?) → on-demand via load_context\n * If omitted, auto-wired to writable SQLite when using builder. */\n provider?: ContextProvider | WritableContextProvider | SkillProvider;\n}\n\n/**\n * A loaded context block with computed token count.\n */\nexport interface ContextBlock {\n label: string;\n description?: string;\n content: string;\n tokens: number;\n maxTokens?: number;\n /** True if provider is writable (has set) */\n writable: boolean;\n /** True if backed by a SkillProvider */\n isSkill: boolean;\n}\n\n/**\n * Manages context blocks with frozen snapshot support.\n */\nexport class ContextBlocks {\n private configs: ContextConfig[];\n private blocks = new Map<string, ContextBlock>();\n private snapshot: string | null = null;\n private loaded = false;\n private promptStore: WritableContextProvider | null;\n\n constructor(configs: ContextConfig[], promptStore?: WritableContextProvider) {\n this.configs = configs;\n this.promptStore = promptStore ?? null;\n }\n\n isLoaded(): boolean {\n return this.loaded;\n }\n\n /**\n * Load all blocks from their providers.\n * Called once at session init.\n */\n async load(): Promise<void> {\n for (const config of this.configs) {\n const content = config.provider\n ? ((await config.provider.get()) ?? \"\")\n : \"\";\n\n const skill = config.provider ? isSkillProvider(config.provider) : false;\n const writable = config.provider\n ? isWritableProvider(config.provider) ||\n (skill && !!(config.provider as SkillProvider).set)\n : false;\n\n this.blocks.set(config.label, {\n label: config.label,\n description: config.description,\n content,\n tokens: estimateStringTokens(content),\n maxTokens: config.maxTokens,\n writable,\n isSkill: skill\n });\n }\n this.loaded = true;\n }\n\n /**\n * Get a block by label.\n */\n getBlock(label: string): ContextBlock | null {\n return this.blocks.get(label) ?? null;\n }\n\n /**\n * Get all blocks.\n */\n getBlocks(): ContextBlock[] {\n return Array.from(this.blocks.values());\n }\n\n /**\n * Set block content. Writes to provider immediately.\n * Does NOT update the frozen snapshot.\n */\n async setBlock(label: string, content: string): Promise<ContextBlock> {\n if (!this.loaded) await this.load();\n const config = this.configs.find((c) => c.label === label);\n const existing = this.blocks.get(label);\n\n if (!existing?.writable) {\n throw new Error(`Block \"${label}\" is readonly`);\n }\n\n if (existing.isSkill) {\n throw new Error(\n `Block \"${label}\" is a skill provider. Use setSkill() instead.`\n );\n }\n\n const tokens = estimateStringTokens(content);\n const maxTokens = config?.maxTokens ?? existing?.maxTokens;\n\n if (maxTokens !== undefined && tokens > maxTokens) {\n throw new Error(\n `Block \"${label}\" exceeds maxTokens: ${tokens} > ${maxTokens}`\n );\n }\n\n const block: ContextBlock = {\n label,\n description: config?.description ?? existing?.description,\n content,\n tokens,\n maxTokens,\n writable: true,\n isSkill: false\n };\n\n this.blocks.set(label, block);\n\n // Write to provider immediately (durable)\n if (config?.provider && isWritableProvider(config.provider)) {\n await config.provider.set(content);\n }\n\n return block;\n }\n\n /**\n * Set a skill entry within a skill block.\n */\n async setSkill(\n label: string,\n key: string,\n content: string,\n description?: string\n ): Promise<void> {\n if (!this.loaded) await this.load();\n const config = this.configs.find((c) => c.label === label);\n const existing = this.blocks.get(label);\n\n if (!existing?.isSkill) {\n throw new Error(`Block \"${label}\" is not a skill provider`);\n }\n\n const provider = config?.provider;\n if (!provider || !isSkillProvider(provider) || !provider.set) {\n throw new Error(`Block \"${label}\" does not support writes`);\n }\n\n await provider.set(key, content, description);\n\n // Refresh metadata\n const metadata = await provider.get();\n if (metadata) {\n existing.content = metadata;\n existing.tokens = estimateStringTokens(metadata);\n }\n }\n\n /**\n * Load a skill's full content from a skill block.\n */\n async loadSkill(label: string, key: string): Promise<string | null> {\n if (!this.loaded) await this.load();\n const config = this.configs.find((c) => c.label === label);\n\n if (!config?.provider || !isSkillProvider(config.provider)) {\n throw new Error(`Block \"${label}\" is not a skill provider`);\n }\n\n return config.provider.load(key);\n }\n\n /**\n * Append content to a block.\n */\n async appendToBlock(label: string, content: string): Promise<ContextBlock> {\n if (!this.loaded) await this.load();\n const existing = this.blocks.get(label);\n if (!existing) {\n throw new Error(`Block \"${label}\" not found`);\n }\n return this.setBlock(label, existing.content + content);\n }\n\n /**\n * Get the system prompt string with context blocks.\n *\n * Returns a frozen snapshot: first call renders and caches,\n * subsequent calls return the same string (preserves LLM prefix cache).\n * Call refreshSnapshot() to re-render after block changes take effect.\n */\n toSystemPrompt(): string {\n if (!this.loaded) {\n throw new Error(\"Context blocks not loaded. Call load() first.\");\n }\n\n if (this.snapshot !== null) {\n return this.snapshot;\n }\n\n return this.captureSnapshot();\n }\n\n /**\n * Force re-render the snapshot from current block state.\n */\n refreshSnapshot(): string {\n return this.captureSnapshot();\n }\n\n private captureSnapshot(): string {\n const parts: string[] = [];\n const sep = \"═\".repeat(46);\n\n for (const block of this.blocks.values()) {\n if (!block.content) continue;\n\n let header = block.label.toUpperCase();\n if (block.description && block.isSkill) {\n header += ` (${block.description} — use load_context to load)`;\n } else if (block.description) {\n header += ` (${block.description})`;\n } else if (block.isSkill) {\n header += \" (use load_context to load)\";\n }\n if (block.maxTokens) {\n const pct = Math.round((block.tokens / block.maxTokens) * 100);\n header += ` [${pct}% — ${block.tokens}/${block.maxTokens} tokens]`;\n }\n if (!block.writable) header += \" [readonly]\";\n\n parts.push(`${sep}\\n${header}\\n${sep}\\n${block.content}`);\n }\n\n this.snapshot = parts.join(\"\\n\\n\");\n return this.snapshot;\n }\n\n /**\n * Get writable blocks (for tool description).\n */\n getWritableBlocks(): ContextBlock[] {\n return Array.from(this.blocks.values()).filter((b) => b.writable);\n }\n\n /**\n * Check if any skill providers are registered.\n */\n hasSkillBlocks(): boolean {\n return Array.from(this.blocks.values()).some((b) => b.isSkill);\n }\n\n /**\n * Get skill block labels.\n */\n getSkillLabels(): string[] {\n return Array.from(this.blocks.values())\n .filter((b) => b.isSkill)\n .map((b) => b.label);\n }\n\n // ── Public API ──────────────────────────────────────────────────\n\n /**\n * Frozen system prompt. On first call:\n * 1. Checks store for a persisted prompt (survives DO eviction)\n * 2. If none, loads blocks from providers, renders, and persists\n */\n async freezeSystemPrompt(): Promise<string> {\n if (this.promptStore) {\n const stored = await this.promptStore.get();\n if (stored !== null) return stored;\n }\n\n if (!this.loaded) await this.load();\n const prompt = this.toSystemPrompt();\n\n if (this.promptStore) {\n await this.promptStore.set(prompt);\n }\n\n return prompt;\n }\n\n /**\n * Re-render the system prompt from current block state and persist.\n */\n async refreshSystemPrompt(): Promise<string> {\n if (!this.loaded) await this.load();\n const prompt = this.refreshSnapshot();\n\n if (this.promptStore) {\n await this.promptStore.set(prompt);\n }\n\n return prompt;\n }\n\n /**\n * AI tools for context blocks.\n *\n * Auto-wired based on provider capabilities:\n * - `set_context` — when any block is writable\n * - `load_context` — when any block is a skill provider\n */\n async tools(): Promise<ToolSet> {\n if (!this.loaded) await this.load();\n\n const writable = this.getWritableBlocks();\n const hasSkills = this.hasSkillBlocks();\n const toolSet: ToolSet = {};\n\n // ── set_context ──────────────────────────────────────────────\n\n if (writable.length > 0) {\n const regularBlocks = writable.filter((b) => !b.isSkill);\n const skillBlocks = writable.filter((b) => b.isSkill);\n\n const blockDescriptions: string[] = [];\n for (const b of regularBlocks) {\n blockDescriptions.push(\n `- \"${b.label}\": ${b.description ?? \"no description\"}`\n );\n }\n for (const b of skillBlocks) {\n blockDescriptions.push(\n `- \"${b.label}\": skill collection (requires key and optional description)`\n );\n }\n\n const properties: Record<string, unknown> = {\n label: {\n type: \"string\" as const,\n enum: writable.map((b) => b.label),\n description: \"Block label to write to\"\n },\n content: {\n type: \"string\" as const,\n description: \"Content to write\"\n },\n action: {\n type: \"string\" as const,\n enum: [\"replace\", \"append\"],\n description: \"replace (default) or append\"\n }\n };\n\n const required = [\"label\", \"content\"];\n\n if (skillBlocks.length > 0) {\n properties.key = {\n type: \"string\" as const,\n description:\n \"Skill key (required for skill blocks: \" +\n skillBlocks.map((b) => `\"${b.label}\"`).join(\", \") +\n \")\"\n };\n properties.description = {\n type: \"string\" as const,\n description: \"Short description for the skill entry\"\n };\n }\n\n toolSet.set_context = {\n description: `Write to a context block. Available blocks:\\n${blockDescriptions.join(\"\\n\")}\\n\\nWrites are durable and persist across sessions.`,\n inputSchema: jsonSchema({\n type: \"object\" as const,\n properties: properties as Record<string, object>,\n required\n }),\n execute: async ({\n label,\n content,\n key,\n description,\n action\n }: {\n label: string;\n content: string;\n key?: string;\n description?: string;\n action?: string;\n }) => {\n try {\n const block = this.blocks.get(label);\n if (!block) return `Error: block \"${label}\" not found`;\n\n if (block.isSkill) {\n if (!key)\n return `Error: key is required for skill block \"${label}\"`;\n await this.setSkill(label, key, content, description);\n return `Written skill \"${key}\" to ${label}.`;\n }\n\n const updated =\n action === \"append\"\n ? await this.appendToBlock(label, content)\n : await this.setBlock(label, content);\n const usage = updated.maxTokens\n ? `${Math.round((updated.tokens / updated.maxTokens) * 100)}% (${updated.tokens}/${updated.maxTokens} tokens)`\n : `${updated.tokens} tokens`;\n return `Written to ${label}. Usage: ${usage}`;\n } catch (err) {\n return `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n };\n }\n\n // ── load_context ─────────────────────────────────────────────\n\n if (hasSkills) {\n const skillLabels = this.getSkillLabels();\n\n toolSet.load_context = {\n description:\n \"Load a document from a skill block by key. \" +\n \"Available skill blocks: \" +\n skillLabels.map((l) => `\"${l}\"`).join(\", \") +\n \". Check the system prompt for available keys.\",\n inputSchema: jsonSchema({\n type: \"object\" as const,\n properties: {\n label: {\n type: \"string\" as const,\n enum: skillLabels,\n description: \"Skill block label\"\n },\n key: {\n type: \"string\" as const,\n description: \"Skill key to load\"\n }\n },\n required: [\"label\", \"key\"]\n }),\n execute: async ({ label, key }: { label: string; key: string }) => {\n try {\n const content = await this.loadSkill(label, key);\n return content ?? `Not found: ${key}`;\n } catch (err) {\n return `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n };\n }\n\n return toolSet;\n }\n}\n","/**\n * Agent Session Provider\n *\n * SQLite-backed provider with tree-structured messages (branching),\n * compaction overlays, and FTS5 search.\n */\n\nimport type { UIMessage } from \"ai\";\nimport type {\n SessionProvider,\n SearchResult,\n StoredCompaction\n} from \"../provider\";\nimport { COMPACTION_PREFIX } from \"../../utils/compaction-helpers\";\n\nexport interface SqlProvider {\n sql<T = Record<string, string | number | boolean | null>>(\n strings: TemplateStringsArray,\n ...values: (string | number | boolean | null)[]\n ): T[];\n}\n\nexport class AgentSessionProvider implements SessionProvider {\n private agent: SqlProvider;\n private initialized = false;\n private sessionId: string;\n\n /**\n * @param agent - Agent or any object with a `sql` tagged template method\n * @param sessionId - Optional session ID to isolate multiple sessions in the same DO.\n * Messages are filtered by session_id within shared tables.\n */\n constructor(agent: SqlProvider, sessionId?: string) {\n this.agent = agent;\n this.sessionId = sessionId ?? \"\";\n }\n\n private ensureTable(): void {\n if (this.initialized) return;\n\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS assistant_messages (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL DEFAULT '',\n parent_id TEXT,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n this.agent.sql`\n CREATE INDEX IF NOT EXISTS idx_assistant_msg_parent\n ON assistant_messages(parent_id)\n `;\n\n this.agent.sql`\n CREATE INDEX IF NOT EXISTS idx_assistant_msg_session\n ON assistant_messages(session_id)\n `;\n\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS assistant_compactions (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL DEFAULT '',\n summary TEXT NOT NULL,\n from_message_id TEXT NOT NULL,\n to_message_id TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n this.agent.sql`\n CREATE VIRTUAL TABLE IF NOT EXISTS assistant_fts\n USING fts5(id UNINDEXED, session_id UNINDEXED, role UNINDEXED, content, tokenize='porter unicode61')\n `;\n\n // Reserved for SessionManager metadata (PR #1167) and Think integration (PR #1169)\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS assistant_config (\n session_id TEXT NOT NULL,\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n PRIMARY KEY (session_id, key)\n )\n `;\n\n this.initialized = true;\n }\n\n // ── Read ───────────────────────────────────────────────────────\n\n getMessage(id: string): UIMessage | null {\n this.ensureTable();\n const rows = this.agent.sql<{ content: string }>`\n SELECT content FROM assistant_messages WHERE id = ${id} AND session_id = ${this.sessionId}\n `;\n return rows.length > 0 ? this.parse(rows[0].content) : null;\n }\n\n getHistory(leafId?: string | null): UIMessage[] {\n this.ensureTable();\n\n const leaf = leafId\n ? this.agent.sql<{ id: string }>`\n SELECT id FROM assistant_messages WHERE id = ${leafId} AND session_id = ${this.sessionId}\n `[0]\n : this.latestLeafRow();\n\n if (!leaf) return [];\n\n const path = this.agent.sql<{ content: string }>`\n WITH RECURSIVE path AS (\n SELECT *, 0 as depth FROM assistant_messages WHERE id = ${leaf.id}\n UNION ALL\n SELECT m.*, p.depth + 1 FROM assistant_messages m\n JOIN path p ON m.id = p.parent_id\n WHERE m.session_id = ${this.sessionId} AND p.depth < 10000\n )\n SELECT content FROM path ORDER BY depth DESC\n `;\n\n const messages = this.parseRows(path);\n const compactions = this.getCompactions();\n if (compactions.length === 0) return messages;\n return this.applyCompactions(messages, compactions);\n }\n\n getLatestLeaf(): UIMessage | null {\n this.ensureTable();\n const row = this.latestLeafRow();\n return row ? this.parse(row.content) : null;\n }\n\n getBranches(messageId: string): UIMessage[] {\n this.ensureTable();\n const rows = this.agent.sql<{ content: string }>`\n SELECT content FROM assistant_messages\n WHERE parent_id = ${messageId} AND session_id = ${this.sessionId} ORDER BY created_at ASC\n `;\n return this.parseRows(rows);\n }\n\n getPathLength(leafId?: string | null): number {\n this.ensureTable();\n const leaf = leafId\n ? this.agent.sql<{ id: string }>`\n SELECT id FROM assistant_messages WHERE id = ${leafId} AND session_id = ${this.sessionId}\n `[0]\n : this.latestLeafRow();\n if (!leaf) return 0;\n\n const rows = this.agent.sql<{ count: number }>`\n WITH RECURSIVE path AS (\n SELECT id, parent_id, 0 as depth FROM assistant_messages WHERE id = ${leaf.id}\n UNION ALL\n SELECT m.id, m.parent_id, p.depth + 1 FROM assistant_messages m\n JOIN path p ON m.id = p.parent_id\n WHERE m.session_id = ${this.sessionId} AND p.depth < 10000\n )\n SELECT COUNT(*) as count FROM path\n `;\n return rows[0]?.count ?? 0;\n }\n\n // ── Write ──────────────────────────────────────────────────────\n\n appendMessage(message: UIMessage, parentId?: string | null): void {\n this.ensureTable();\n // Skip if message already exists (INSERT OR IGNORE idempotency)\n const existing = this.agent.sql<{ id: string }>`\n SELECT id FROM assistant_messages WHERE id = ${message.id} AND session_id = ${this.sessionId}\n `;\n if (existing.length > 0) return;\n\n let parent = parentId ?? this.latestLeafRow()?.id ?? null;\n\n // Validate parentId belongs to this session\n if (parent) {\n const valid = this.agent.sql<{ id: string }>`\n SELECT id FROM assistant_messages WHERE id = ${parent} AND session_id = ${this.sessionId}\n `;\n if (valid.length === 0) parent = null;\n }\n\n const json = JSON.stringify(message);\n\n this.agent.sql`\n INSERT INTO assistant_messages (id, session_id, parent_id, role, content)\n VALUES (${message.id}, ${this.sessionId}, ${parent}, ${message.role}, ${json})\n `;\n this.indexFTS(message);\n }\n\n updateMessage(message: UIMessage): void {\n this.ensureTable();\n this.agent.sql`\n UPDATE assistant_messages SET content = ${JSON.stringify(message)}\n WHERE id = ${message.id} AND session_id = ${this.sessionId}\n `;\n this.indexFTS(message);\n }\n\n deleteMessages(messageIds: string[]): void {\n this.ensureTable();\n for (const id of messageIds) {\n this.agent\n .sql`DELETE FROM assistant_messages WHERE id = ${id} AND session_id = ${this.sessionId}`;\n this.deleteFTS(id);\n }\n }\n\n clearMessages(): void {\n this.ensureTable();\n this.agent\n .sql`DELETE FROM assistant_messages WHERE session_id = ${this.sessionId}`;\n this.agent\n .sql`DELETE FROM assistant_compactions WHERE session_id = ${this.sessionId}`;\n // FTS5 requires delete by rowid\n const ftsRows = this.agent.sql<{ rowid: number }>`\n SELECT rowid FROM assistant_fts WHERE session_id = ${this.sessionId}\n `;\n for (const row of ftsRows) {\n this.agent.sql`DELETE FROM assistant_fts WHERE rowid = ${row.rowid}`;\n }\n }\n\n // ── Compaction ─────────────────────────────────────────────────\n\n addCompaction(\n summary: string,\n fromMessageId: string,\n toMessageId: string\n ): StoredCompaction {\n this.ensureTable();\n const id = crypto.randomUUID();\n this.agent.sql`\n INSERT INTO assistant_compactions (id, session_id, summary, from_message_id, to_message_id)\n VALUES (${id}, ${this.sessionId}, ${summary}, ${fromMessageId}, ${toMessageId})\n `;\n return {\n id,\n summary,\n fromMessageId,\n toMessageId,\n createdAt: new Date().toISOString()\n };\n }\n\n getCompactions(): StoredCompaction[] {\n this.ensureTable();\n type Row = {\n id: string;\n summary: string;\n from_message_id: string;\n to_message_id: string;\n created_at: string;\n };\n return this.agent.sql<Row>`\n SELECT * FROM assistant_compactions WHERE session_id = ${this.sessionId} ORDER BY created_at ASC\n `.map((r) => ({\n id: r.id,\n summary: r.summary,\n fromMessageId: r.from_message_id,\n toMessageId: r.to_message_id,\n createdAt: r.created_at\n }));\n }\n\n // ── Search ─────────────────────────────────────────────────────\n\n searchMessages(query: string, limit = 20): SearchResult[] {\n this.ensureTable();\n // Sanitize query: wrap in double quotes to treat as literal phrase,\n // escaping any existing double quotes to prevent FTS5 syntax injection\n const sanitized = `\"${query.replace(/\"/g, '\"\"')}\"`;\n try {\n return this.agent.sql<{ id: string; role: string; content: string }>`\n SELECT f.id, f.role, f.content FROM assistant_fts f\n INNER JOIN assistant_messages m ON m.id = f.id AND m.session_id = f.session_id\n WHERE assistant_fts MATCH ${sanitized} AND f.session_id = ${this.sessionId}\n ORDER BY rank LIMIT ${limit}\n `.map((r) => ({\n id: r.id,\n role: r.role,\n content: r.content\n }));\n } catch {\n // Malformed FTS query — return empty results\n return [];\n }\n }\n\n // ── Internal ───────────────────────────────────────────────────\n\n private latestLeafRow(): { id: string; content: string } | null {\n const rows = this.agent.sql<{ id: string; content: string }>`\n SELECT m.id, m.content FROM assistant_messages m\n LEFT JOIN assistant_messages c ON c.parent_id = m.id AND c.session_id = ${this.sessionId}\n WHERE c.id IS NULL AND m.session_id = ${this.sessionId}\n ORDER BY m.created_at DESC, m.rowid DESC LIMIT 1\n `;\n return rows[0] ?? null;\n }\n\n private indexFTS(message: UIMessage): void {\n const text = message.parts\n .filter((p) => p.type === \"text\")\n .map((p) => (p as { text: string }).text)\n .join(\" \");\n // Always delete old entry first — handles text→no-text transitions\n this.deleteFTS(message.id);\n if (text) {\n this.agent.sql`\n INSERT INTO assistant_fts (id, session_id, role, content)\n VALUES (${message.id}, ${this.sessionId}, ${message.role}, ${text})\n `;\n }\n }\n\n private deleteFTS(id: string): void {\n const rows = this.agent.sql<{ rowid: number }>`\n SELECT rowid FROM assistant_fts WHERE id = ${id} AND session_id = ${this.sessionId}\n `;\n for (const row of rows) {\n this.agent.sql`DELETE FROM assistant_fts WHERE rowid = ${row.rowid}`;\n }\n }\n\n private applyCompactions(\n messages: UIMessage[],\n compactions: StoredCompaction[]\n ): UIMessage[] {\n const ids = messages.map((m) => m.id);\n const result: UIMessage[] = [];\n let i = 0;\n while (i < messages.length) {\n // Find all compactions starting at this message, pick the latest\n // (widest range) so newer compactions supersede older ones\n const matching = compactions.filter((c) => c.fromMessageId === ids[i]);\n const comp =\n matching.length > 1 ? matching[matching.length - 1] : matching[0];\n if (comp) {\n const endIdx = ids.indexOf(comp.toMessageId);\n if (endIdx >= i) {\n result.push({\n id: `${COMPACTION_PREFIX}${comp.id}`,\n role: \"assistant\",\n parts: [\n {\n type: \"text\",\n text: comp.summary\n }\n ],\n createdAt: new Date()\n } as UIMessage);\n i = endIdx + 1;\n continue;\n }\n }\n result.push(messages[i]);\n i++;\n }\n return result;\n }\n\n private parse(json: string): UIMessage | null {\n try {\n const msg = JSON.parse(json);\n if (\n typeof msg?.id === \"string\" &&\n typeof msg?.role === \"string\" &&\n Array.isArray(msg?.parts)\n ) {\n return msg;\n }\n } catch {\n /* skip */\n }\n return null;\n }\n\n private parseRows(rows: { content: string }[]): UIMessage[] {\n const result: UIMessage[] = [];\n for (const row of rows) {\n const msg = this.parse(row.content);\n if (msg) result.push(msg);\n }\n return result;\n }\n}\n","/**\n * SQLite Context Block Provider\n *\n * Default durable storage for context blocks using DO SQLite.\n * Each block is a row in cf_agents_context_blocks.\n */\n\nimport type { ContextProvider } from \"../context\";\nimport type { SqlProvider } from \"./agent\";\n\nexport class AgentContextProvider implements ContextProvider {\n private agent: SqlProvider;\n private label: string;\n private initialized = false;\n\n constructor(agent: SqlProvider, label: string) {\n this.agent = agent;\n this.label = label;\n }\n\n private ensureTable(): void {\n if (this.initialized) return;\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_context_blocks (\n label TEXT PRIMARY KEY,\n content TEXT NOT NULL,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `;\n this.initialized = true;\n }\n\n async get(): Promise<string | null> {\n this.ensureTable();\n const rows = this.agent.sql<{ content: string }>`\n SELECT content FROM cf_agents_context_blocks WHERE label = ${this.label}\n `;\n return rows[0]?.content ?? null;\n }\n\n async set(content: string): Promise<void> {\n this.ensureTable();\n this.agent.sql`\n INSERT INTO cf_agents_context_blocks (label, content)\n VALUES (${this.label}, ${content})\n ON CONFLICT(label) DO UPDATE SET content = ${content}, updated_at = CURRENT_TIMESTAMP\n `;\n }\n}\n","/**\n * Session — conversation history, context blocks, compaction, search, and tools.\n */\n\nimport type { ToolSet } from \"ai\";\nimport type { UIMessage } from \"ai\";\nimport type { SessionProvider, StoredCompaction } from \"./provider\";\nimport type { SessionOptions } from \"./types\";\nimport {\n ContextBlocks,\n type ContextBlock,\n type ContextConfig,\n type WritableContextProvider\n} from \"./context\";\nimport { AgentSessionProvider, type SqlProvider } from \"./providers/agent\";\nimport { AgentContextProvider } from \"./providers/agent-context\";\nimport type { CompactResult } from \"../utils/compaction-helpers\";\nimport { estimateMessageTokens } from \"../utils/tokens\";\nimport { MessageType } from \"../../../types\";\n\nexport type SessionContextOptions = Omit<ContextConfig, \"label\">;\n\n// Raw builder entry — provider resolved at init time so chain order doesn't matter\ninterface PendingContext {\n label: string;\n options: SessionContextOptions;\n}\n\n/** Agent-like object that can broadcast to connected clients */\ninterface Broadcaster {\n broadcast(message: string | ArrayBufferLike): void;\n}\n\nfunction isBroadcaster(obj: unknown): obj is Broadcaster {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"broadcast\" in obj &&\n typeof (obj as Broadcaster).broadcast === \"function\"\n );\n}\n\nexport class Session {\n private storage!: SessionProvider;\n private context!: ContextBlocks;\n\n // Builder state — only used with Session.create()\n private _agent?: SqlProvider;\n private _broadcaster?: Broadcaster;\n private _sessionId?: string;\n private _pending?: PendingContext[];\n private _cachedPrompt?: WritableContextProvider | true;\n private _compactionFn?:\n | ((messages: UIMessage[]) => Promise<CompactResult | null>)\n | null;\n private _tokenThreshold?: number;\n private _ready = false;\n\n constructor(storage: SessionProvider, options?: SessionOptions) {\n this.storage = storage;\n this.context = new ContextBlocks(\n options?.context ?? [],\n options?.promptStore\n );\n this._ready = true;\n }\n\n /**\n * Chainable session creation with auto-wired SQLite providers.\n * Chain methods in any order — providers are resolved lazily on first use.\n *\n * @example\n * ```ts\n * const session = Session.create(this)\n * .withContext(\"soul\", { provider: { get: async () => \"You are helpful.\" } })\n * .withContext(\"memory\", { description: \"Learned facts\", maxTokens: 1100 })\n * .withCachedPrompt();\n *\n * // Skills from R2 (on-demand loading via load_context tool)\n * const session = Session.create(this)\n * .withContext(\"skills\", {\n * provider: new R2SkillProvider(env.SKILLS_BUCKET, { prefix: \"skills/\" })\n * })\n * .withCachedPrompt();\n * ```\n */\n static create(agent: SqlProvider): Session {\n const session: Session = Object.create(Session.prototype);\n session._agent = agent;\n if (isBroadcaster(agent)) {\n session._broadcaster = agent;\n }\n session._pending = [];\n session._ready = false;\n return session;\n }\n\n // ── Builder methods ─────────────────────────────────────────────\n\n forSession(sessionId: string): this {\n this._sessionId = sessionId;\n return this;\n }\n\n withContext(label: string, options?: SessionContextOptions): this {\n this._pending!.push({ label, options: options ?? {} });\n return this;\n }\n\n withCachedPrompt(provider?: WritableContextProvider): this {\n this._cachedPrompt = provider ?? true;\n return this;\n }\n\n /**\n * Register a compaction function. Called by `compact()` to compress\n * message history into a summary overlay.\n */\n onCompaction(\n fn: (messages: UIMessage[]) => Promise<CompactResult | null>\n ): this {\n this._compactionFn = fn;\n return this;\n }\n\n /**\n * Auto-compact when estimated token count exceeds the threshold.\n * Checked after each `appendMessage`. Requires `onCompaction()`.\n */\n compactAfter(tokenThreshold: number): this {\n this._tokenThreshold = tokenThreshold;\n return this;\n }\n\n // ── Lazy init ───────────────────────────────────────────────────\n\n private _ensureReady(): void {\n if (this._ready) return;\n\n // Resolve context configs — sessionId is final by now\n const configs: ContextConfig[] = (this._pending ?? []).map(\n ({ label, options: opts }) => {\n let provider = opts.provider;\n if (!provider) {\n // No provider → auto-wire to writable SQLite\n const key = this._sessionId ? `${label}_${this._sessionId}` : label;\n provider = new AgentContextProvider(this._agent!, key);\n }\n return {\n label,\n description: opts.description,\n maxTokens: opts.maxTokens,\n provider\n };\n }\n );\n\n // Resolve prompt store\n let promptStore: WritableContextProvider | undefined;\n if (this._cachedPrompt === true) {\n const key = this._sessionId\n ? `_system_prompt_${this._sessionId}`\n : \"_system_prompt\";\n promptStore = new AgentContextProvider(this._agent!, key);\n } else if (this._cachedPrompt) {\n promptStore = this._cachedPrompt;\n }\n\n this.storage = new AgentSessionProvider(this._agent!, this._sessionId);\n this.context = new ContextBlocks(configs, promptStore);\n this._ready = true;\n }\n\n // ── History (tree-structured) ─────────────────────────────────\n\n getHistory(leafId?: string | null): UIMessage[] {\n this._ensureReady();\n return this.storage.getHistory(leafId);\n }\n\n getMessage(id: string): UIMessage | null {\n this._ensureReady();\n return this.storage.getMessage(id);\n }\n\n getLatestLeaf(): UIMessage | null {\n this._ensureReady();\n return this.storage.getLatestLeaf();\n }\n\n getBranches(messageId: string): UIMessage[] {\n this._ensureReady();\n return this.storage.getBranches(messageId);\n }\n\n getPathLength(leafId?: string | null): number {\n this._ensureReady();\n return this.storage.getPathLength(leafId);\n }\n\n // ── Broadcast ──────────────────────────────────────────────────\n\n private _broadcast(type: MessageType, data: Record<string, unknown>): void {\n if (!this._broadcaster) return;\n this._broadcaster.broadcast(JSON.stringify({ type, ...data }));\n }\n\n private _emitStatus(\n phase: \"idle\" | \"compacting\",\n extra?: Record<string, unknown>\n ): number {\n const tokenEstimate = estimateMessageTokens(this.getHistory());\n this._broadcast(MessageType.CF_AGENT_SESSION, {\n phase,\n tokenEstimate,\n tokenThreshold: this._tokenThreshold ?? null,\n ...extra\n });\n return tokenEstimate;\n }\n\n private _emitError(error: string): void {\n this._broadcast(MessageType.CF_AGENT_SESSION_ERROR, { error });\n }\n\n // ── Write ─────────────────────────────────────────────────────\n\n async appendMessage(\n message: UIMessage,\n parentId?: string | null\n ): Promise<void> {\n this._ensureReady();\n this.storage.appendMessage(message, parentId);\n\n const tokenEstimate = this._emitStatus(\"idle\");\n\n if (\n this._tokenThreshold != null &&\n this._compactionFn &&\n tokenEstimate > this._tokenThreshold\n ) {\n try {\n await this.compact();\n } catch {\n // Auto-compact failure is non-fatal — message is already appended\n }\n }\n }\n\n updateMessage(message: UIMessage): void {\n this._ensureReady();\n this.storage.updateMessage(message);\n this._emitStatus(\"idle\");\n }\n\n deleteMessages(messageIds: string[]): void {\n this._ensureReady();\n this.storage.deleteMessages(messageIds);\n this._emitStatus(\"idle\");\n }\n\n clearMessages(): void {\n this._ensureReady();\n this.storage.clearMessages();\n this._emitStatus(\"idle\");\n }\n\n // ── Compaction ────────────────────────────────────────────────\n\n addCompaction(\n summary: string,\n fromMessageId: string,\n toMessageId: string\n ): StoredCompaction {\n this._ensureReady();\n return this.storage.addCompaction(summary, fromMessageId, toMessageId);\n }\n\n getCompactions(): StoredCompaction[] {\n this._ensureReady();\n return this.storage.getCompactions();\n }\n\n /**\n * Run the registered compaction function and store the result as an overlay.\n * Requires `onCompaction()` to be called first.\n */\n async compact(): Promise<CompactResult | null> {\n this._ensureReady();\n if (!this._compactionFn) {\n throw new Error(\n \"No compaction function registered. Call onCompaction() first.\"\n );\n }\n\n const tokensBefore = this._emitStatus(\"compacting\");\n\n let result: CompactResult | null;\n try {\n result = await this._compactionFn(this.getHistory());\n } catch (err) {\n this._emitError(err instanceof Error ? err.message : String(err));\n return null;\n }\n\n if (!result) {\n this._emitStatus(\"idle\");\n return null;\n }\n\n // Validate toMessageId exists in the history\n const historyIds = new Set(this.getHistory().map((m) => m.id));\n if (!historyIds.has(result.toMessageId)) {\n this._emitStatus(\"idle\");\n return null;\n }\n\n // Iterative compaction — extend from earliest existing compaction's start\n const existing = this.getCompactions();\n const fromId =\n existing.length > 0 ? existing[0].fromMessageId : result.fromMessageId;\n\n this.addCompaction(result.summary, fromId, result.toMessageId);\n await this.refreshSystemPrompt();\n\n this._emitStatus(\"idle\", {\n compacted: { tokensBefore }\n });\n\n return { ...result, fromMessageId: fromId };\n }\n\n // ── Context Blocks ────────────────────────────────────────────\n\n getContextBlock(label: string): ContextBlock | null {\n this._ensureReady();\n return this.context.getBlock(label);\n }\n\n getContextBlocks(): ContextBlock[] {\n this._ensureReady();\n return this.context.getBlocks();\n }\n\n async replaceContextBlock(\n label: string,\n content: string\n ): Promise<ContextBlock> {\n this._ensureReady();\n return this.context.setBlock(label, content);\n }\n\n async appendContextBlock(\n label: string,\n content: string\n ): Promise<ContextBlock> {\n this._ensureReady();\n return this.context.appendToBlock(label, content);\n }\n\n // ── System Prompt ─────────────────────────────────────────────\n\n async freezeSystemPrompt(): Promise<string> {\n this._ensureReady();\n return this.context.freezeSystemPrompt();\n }\n\n async refreshSystemPrompt(): Promise<string> {\n this._ensureReady();\n return this.context.refreshSystemPrompt();\n }\n\n // ── Search ────────────────────────────────────────────────────\n\n search(\n query: string,\n options?: { limit?: number }\n ): Array<{\n id: string;\n role: string;\n content: string;\n createdAt?: string;\n }> {\n this._ensureReady();\n if (!this.storage.searchMessages) {\n throw new Error(\"Session provider does not support search\");\n }\n return this.storage.searchMessages(query, options?.limit ?? 20);\n }\n\n // ── Tools ─────────────────────────────────────────────────────\n\n /** Returns set_context and load_context tools. */\n async tools(): Promise<ToolSet> {\n this._ensureReady();\n return this.context.tools();\n }\n}\n","/**\n * SessionManager — registry of named sessions.\n *\n * Lifecycle: create, get, list, delete, rename.\n * Convenience methods for message ops by session ID.\n * Cross-session search and tools.\n */\n\nimport type { UIMessage } from \"ai\";\nimport { jsonSchema, type ToolSet } from \"ai\";\nimport type { CompactResult } from \"../utils/compaction-helpers\";\nimport type { WritableContextProvider } from \"./context\";\nimport type { StoredCompaction } from \"./provider\";\nimport type { SqlProvider } from \"./providers/agent\";\nimport { Session, type SessionContextOptions } from \"./session\";\n\nexport interface SessionInfo {\n id: string;\n name: string;\n parent_session_id: string | null;\n model: string | null;\n source: string | null;\n input_tokens: number;\n output_tokens: number;\n estimated_cost: number;\n end_reason: string | null;\n created_at: string;\n updated_at: string;\n}\n\n// Pending context entry — resolved per-session with namespaced providers\ninterface PendingManagerContext {\n label: string;\n options: SessionContextOptions;\n}\n\nexport interface SessionManagerOptions {\n maxContextMessages?: number;\n}\n\nexport class SessionManager {\n private agent!: SqlProvider;\n private _maxContextMessages = 100;\n private _pending: PendingManagerContext[] = [];\n private _cachedPrompt?: WritableContextProvider | true;\n private _compactionFn?:\n | ((messages: UIMessage[]) => Promise<CompactResult | null>)\n | null;\n private _tokenThreshold?: number;\n private _sessions = new Map<string, Session>();\n private _tableReady = false;\n private _ready = false;\n\n constructor(agent: SqlProvider, options: SessionManagerOptions = {}) {\n this.agent = agent;\n this._maxContextMessages = options.maxContextMessages ?? 100;\n this._ready = true;\n this._ensureTable();\n }\n\n /**\n * Chainable SessionManager creation with auto-wired context for all sessions.\n *\n * @example\n * ```ts\n * const manager = SessionManager.create(this)\n * .withContext(\"soul\", { provider: { get: async () => \"You are helpful.\" } })\n * .withContext(\"memory\", { description: \"Learned facts\", maxTokens: 1100 })\n * .withCachedPrompt()\n * .maxContextMessages(50);\n *\n * // Each getSession(id) auto-creates namespaced providers:\n * // memory key: \"memory_<sessionId>\"\n * // prompt key: \"_system_prompt_<sessionId>\"\n * const session = manager.getSession(\"chat-123\");\n * ```\n */\n static create(agent: SqlProvider): SessionManager {\n const mgr: SessionManager = Object.create(SessionManager.prototype);\n mgr.agent = agent;\n mgr._maxContextMessages = 100;\n mgr._pending = [];\n mgr._compactionFn = null;\n mgr._tokenThreshold = undefined;\n mgr._sessions = new Map();\n mgr._tableReady = false;\n mgr._ready = false;\n return mgr;\n }\n\n // ── Builder methods ─────────────────────────────────────────────\n\n withContext(label: string, options?: SessionContextOptions): this {\n this._pending.push({ label, options: options ?? {} });\n return this;\n }\n\n withCachedPrompt(provider?: WritableContextProvider): this {\n this._cachedPrompt = provider ?? true;\n return this;\n }\n\n maxContextMessages(count: number): this {\n this._maxContextMessages = count;\n return this;\n }\n\n /**\n * Register a compaction function propagated to all sessions.\n * Called by `Session.compact()` to compress message history.\n */\n onCompaction(\n fn: (messages: UIMessage[]) => Promise<CompactResult | null>\n ): this {\n this._compactionFn = fn;\n return this;\n }\n\n /**\n * Auto-compact when estimated token count exceeds the threshold.\n * Propagated to all sessions. Requires `onCompaction()`.\n */\n compactAfter(tokenThreshold: number): this {\n this._tokenThreshold = tokenThreshold;\n return this;\n }\n\n // ── Lazy init ───────────────────────────────────────────────────\n\n private _ensureReady(): void {\n if (this._ready) return;\n this._ready = true;\n this._ensureTable();\n }\n\n private _ensureTable(): void {\n if (this._tableReady) return;\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS assistant_sessions (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n parent_session_id TEXT,\n model TEXT,\n source TEXT,\n input_tokens INTEGER DEFAULT 0,\n output_tokens INTEGER DEFAULT 0,\n estimated_cost REAL DEFAULT 0,\n end_reason TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `;\n this.agent.sql`\n CREATE VIRTUAL TABLE IF NOT EXISTS assistant_fts\n USING fts5(id UNINDEXED, session_id UNINDEXED, role UNINDEXED, content, tokenize='porter unicode61')\n `;\n this._tableReady = true;\n }\n\n // ── Session access ────────────────────────────────────────────\n\n /** Get or create the Session instance for a session ID. */\n getSession(sessionId: string): Session {\n this._ensureReady();\n let session = this._sessions.get(sessionId);\n if (!session) {\n const s = Session.create(this.agent).forSession(sessionId);\n for (const { label, options } of this._pending) {\n s.withContext(label, options);\n }\n if (this._cachedPrompt === true) {\n s.withCachedPrompt();\n } else if (this._cachedPrompt) {\n s.withCachedPrompt(this._cachedPrompt);\n }\n if (this._compactionFn) {\n s.onCompaction(this._compactionFn);\n }\n if (this._tokenThreshold != null) {\n s.compactAfter(this._tokenThreshold);\n }\n session = s;\n this._sessions.set(sessionId, session);\n }\n return session;\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────\n\n create(\n name: string,\n opts?: { parentSessionId?: string; model?: string; source?: string }\n ): SessionInfo {\n this._ensureReady();\n const id = crypto.randomUUID();\n this.agent.sql`\n INSERT INTO assistant_sessions (id, name, parent_session_id, model, source)\n VALUES (${id}, ${name}, ${opts?.parentSessionId ?? null}, ${opts?.model ?? null}, ${opts?.source ?? null})\n `;\n return this.get(id)!;\n }\n\n get(sessionId: string): SessionInfo | null {\n this._ensureReady();\n const rows = this.agent.sql`\n SELECT * FROM assistant_sessions WHERE id = ${sessionId}\n ` as unknown as SessionInfo[];\n return rows[0] ?? null;\n }\n\n list(): SessionInfo[] {\n this._ensureReady();\n return this.agent.sql`\n SELECT * FROM assistant_sessions ORDER BY updated_at DESC\n ` as unknown as SessionInfo[];\n }\n\n delete(sessionId: string): void {\n this.getSession(sessionId).clearMessages();\n this.agent.sql`DELETE FROM assistant_sessions WHERE id = ${sessionId}`;\n this._sessions.delete(sessionId);\n }\n\n rename(sessionId: string, name: string): void {\n this._ensureReady();\n this.agent.sql`\n UPDATE assistant_sessions SET name = ${name}, updated_at = CURRENT_TIMESTAMP\n WHERE id = ${sessionId}\n `;\n }\n\n // ── Message convenience methods ───────────────────────────────\n\n async append(\n sessionId: string,\n message: UIMessage,\n parentId?: string\n ): Promise<string> {\n await this.getSession(sessionId).appendMessage(message, parentId);\n this._touch(sessionId);\n return message.id;\n }\n\n async upsert(\n sessionId: string,\n message: UIMessage,\n parentId?: string\n ): Promise<string> {\n const session = this.getSession(sessionId);\n const existing = session.getMessage(message.id);\n if (existing) {\n session.updateMessage(message);\n } else {\n await session.appendMessage(message, parentId);\n }\n this._touch(sessionId);\n return message.id;\n }\n\n async appendAll(\n sessionId: string,\n messages: UIMessage[],\n parentId?: string\n ): Promise<string | null> {\n const session = this.getSession(sessionId);\n let lastParent = parentId ?? null;\n for (const msg of messages) {\n await session.appendMessage(msg, lastParent);\n lastParent = msg.id;\n }\n this._touch(sessionId);\n return lastParent;\n }\n\n getHistory(sessionId: string, leafId?: string): UIMessage[] {\n return this.getSession(sessionId).getHistory(leafId);\n }\n\n getMessageCount(sessionId: string): number {\n return this.getSession(sessionId).getPathLength();\n }\n\n clearMessages(sessionId: string): void {\n this.getSession(sessionId).clearMessages();\n this._touch(sessionId);\n }\n\n deleteMessages(sessionId: string, messageIds: string[]): void {\n this.getSession(sessionId).deleteMessages(messageIds);\n this._touch(sessionId);\n }\n\n // ── Branching ──────────────────────────────────────────────────\n\n getBranches(sessionId: string, messageId: string): UIMessage[] {\n return this.getSession(sessionId).getBranches(messageId);\n }\n\n /**\n * Fork a session at a specific message, creating a new session\n * with the history up to that point copied over.\n */\n async fork(\n sessionId: string,\n atMessageId: string,\n newName: string\n ): Promise<SessionInfo> {\n const info = this.create(newName, { parentSessionId: sessionId });\n const history = this.getSession(sessionId).getHistory(atMessageId);\n const newSession = this.getSession(info.id);\n\n let parentId: string | null = null;\n for (const msg of history) {\n const newId = crypto.randomUUID();\n const copy: UIMessage = { ...msg, id: newId };\n await newSession.appendMessage(copy, parentId);\n parentId = newId;\n }\n\n this._touch(info.id);\n return info;\n }\n\n // ── Compaction ────────────────────────────────────────────────\n\n needsCompaction(sessionId: string): boolean {\n return (\n this.getSession(sessionId).getPathLength() > this._maxContextMessages\n );\n }\n\n addCompaction(\n sessionId: string,\n summary: string,\n fromId: string,\n toId: string\n ): StoredCompaction {\n return this.getSession(sessionId).addCompaction(summary, fromId, toId);\n }\n\n getCompactions(sessionId: string): StoredCompaction[] {\n return this.getSession(sessionId).getCompactions();\n }\n\n async compactAndSplit(\n sessionId: string,\n summary: string,\n newName?: string\n ): Promise<SessionInfo> {\n const old = this.get(sessionId);\n this.agent.sql`\n UPDATE assistant_sessions SET end_reason = 'compaction', updated_at = CURRENT_TIMESTAMP\n WHERE id = ${sessionId}\n `;\n\n const info = this.create(newName ?? old?.name ?? \"Compacted\", {\n parentSessionId: sessionId,\n model: old?.model ?? undefined,\n source: old?.source ?? undefined\n });\n\n await this.append(info.id, {\n id: crypto.randomUUID(),\n role: \"assistant\",\n parts: [\n { type: \"text\", text: `[Context from previous session]\\n\\n${summary}` }\n ]\n });\n\n return info;\n }\n\n // ── Usage tracking ────────────────────────────────────────────\n\n addUsage(\n sessionId: string,\n inputTokens: number,\n outputTokens: number,\n cost: number\n ): void {\n this._ensureReady();\n this.agent.sql`\n UPDATE assistant_sessions SET\n input_tokens = input_tokens + ${inputTokens},\n output_tokens = output_tokens + ${outputTokens},\n estimated_cost = estimated_cost + ${cost},\n updated_at = CURRENT_TIMESTAMP\n WHERE id = ${sessionId}\n `;\n }\n\n // ── Search ────────────────────────────────────────────────────\n\n search(query: string, options?: { limit?: number }) {\n this._ensureReady();\n const limit = options?.limit ?? 20;\n // Quote each word individually to prevent FTS5 syntax injection\n // while preserving implicit AND between terms\n const sanitized = query\n .split(/\\s+/)\n .filter(Boolean)\n .map((w) => `\"${w.replace(/\"/g, '\"\"')}\"`)\n .join(\" \");\n if (!sanitized) return [];\n try {\n return this.agent.sql<{ id: string; role: string; content: string }>`\n SELECT id, role, content FROM assistant_fts\n WHERE assistant_fts MATCH ${sanitized}\n ORDER BY rank LIMIT ${limit}\n `.map((r) => ({\n id: r.id,\n role: r.role,\n content: r.content,\n createdAt: \"\"\n }));\n } catch {\n return [];\n }\n }\n\n // ── Tools ─────────────────────────────────────────────────────\n\n tools(): ToolSet {\n return {\n session_search: {\n description:\n \"Search past conversations for relevant context. Searches across all sessions.\",\n inputSchema: jsonSchema({\n type: \"object\" as const,\n properties: {\n query: { type: \"string\" as const, description: \"Search query\" }\n },\n required: [\"query\"]\n }),\n execute: async ({ query }: { query: string }) => {\n try {\n const results = this.search(query, { limit: 10 });\n if (results.length === 0) return \"No results found.\";\n return results\n .map((r) => `[${r.role}] ${r.content}`)\n .join(\"\\n---\\n\");\n } catch (err) {\n return `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n }\n };\n }\n\n // ── Internal ──────────────────────────────────────────────────\n\n private _touch(sessionId: string): void {\n this.agent.sql`\n UPDATE assistant_sessions SET updated_at = CURRENT_TIMESTAMP\n WHERE id = ${sessionId}\n `;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/experimental/memory/session/search.ts","../../../../src/experimental/memory/session/skills.ts","../../../../src/experimental/memory/session/context.ts","../../../../src/experimental/memory/session/providers/agent.ts","../../../../src/experimental/memory/session/providers/agent-context.ts","../../../../src/experimental/memory/session/session.ts","../../../../src/experimental/memory/session/manager.ts"],"sourcesContent":["/**\n * Search Provider — full-text searchable context blocks.\n *\n * Extends ContextProvider with `search()` for querying indexed content\n * and a keyed `set()` for indexing individual entries.\n *\n * Duck-typed: if a provider has a `search` method, it's a SearchProvider.\n */\n\nimport type { ContextProvider } from \"./context\";\nimport type { SqlProvider } from \"./providers/agent\";\n\n/**\n * Storage interface for searchable context.\n *\n * - `get()` returns a summary of indexed content (rendered into system prompt)\n * - `search(query)` full-text search (via search_context tool)\n * - `set(key, content)` indexes content under a key (via set_context tool)\n */\nexport interface SearchProvider extends ContextProvider {\n search(query: string): Promise<string | null>;\n set?(key: string, content: string): Promise<void>;\n}\n\n/**\n * Check if a provider is a SearchProvider (has a `search` method).\n */\nexport function isSearchProvider(\n provider: unknown\n): provider is SearchProvider {\n return (\n typeof provider === \"object\" &&\n provider !== null &&\n \"search\" in provider &&\n typeof (provider as SearchProvider).search === \"function\"\n );\n}\n\n// ── Agent Search Provider (DO SQLite FTS5) ─────────────────────────\n\n/**\n * SearchProvider backed by Durable Object SQLite with FTS5.\n *\n * - `get()` returns a count of indexed entries\n * - `search(query)` full-text search using FTS5\n * - `set(key, content)` indexes or replaces content under a key\n *\n * Each instance uses a namespaced FTS5 table to avoid collisions\n * with the session message search.\n *\n * @example\n * ```ts\n * Session.create(this)\n * .withContext(\"knowledge\", {\n * provider: new AgentSearchProvider(this)\n * })\n * ```\n */\nexport class AgentSearchProvider implements SearchProvider {\n private agent: SqlProvider;\n private label = \"\";\n private initialized = false;\n\n constructor(agent: SqlProvider) {\n this.agent = agent;\n }\n\n init(label: string): void {\n this.label = label;\n }\n\n private ensureTable(): void {\n if (this.initialized) return;\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_search_entries (\n label TEXT NOT NULL,\n key TEXT NOT NULL,\n content TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (label, key)\n )\n `;\n this.agent.sql`\n CREATE VIRTUAL TABLE IF NOT EXISTS cf_agents_search_fts\n USING fts5(\n label UNINDEXED,\n key UNINDEXED,\n content,\n tokenize='porter unicode61'\n )\n `;\n this.initialized = true;\n }\n\n async get(): Promise<string | null> {\n this.ensureTable();\n const rows = this.agent.sql<{ count: number }>`\n SELECT COUNT(*) as count FROM cf_agents_search_entries\n WHERE label = ${this.label}\n `;\n const count = rows[0]?.count ?? 0;\n if (count === 0) return null;\n\n const keys = this.agent.sql<{ key: string }>`\n SELECT key FROM cf_agents_search_entries\n WHERE label = ${this.label}\n ORDER BY updated_at DESC\n LIMIT 20\n `;\n const listing = keys.map((r) => `- ${r.key}`).join(\"\\n\");\n return `${count} entries indexed. Recent:\\n${listing}`;\n }\n\n async search(query: string): Promise<string | null> {\n this.ensureTable();\n // Quote each word individually to prevent FTS5 syntax injection\n // while preserving implicit AND between terms\n const sanitized = query\n .split(/\\s+/)\n .filter(Boolean)\n .map((w) => `\"${w.replace(/\"/g, '\"\"')}\"`)\n .join(\" \");\n if (!sanitized) return null;\n try {\n const rows = this.agent.sql<{\n key: string;\n content: string;\n }>`\n SELECT f.key, f.content\n FROM cf_agents_search_fts f\n WHERE cf_agents_search_fts MATCH ${sanitized}\n AND f.label = ${this.label}\n ORDER BY rank\n LIMIT 10\n `;\n if (rows.length === 0) return null;\n return rows.map((r) => `[${r.key}]\\n${r.content}`).join(\"\\n\\n\");\n } catch {\n // Malformed FTS query\n return null;\n }\n }\n\n async set(key: string, content: string): Promise<void> {\n this.ensureTable();\n\n // Delete old FTS entry if exists\n this.deleteFTS(key);\n\n // Upsert the entry\n this.agent.sql`\n INSERT INTO cf_agents_search_entries (label, key, content)\n VALUES (${this.label}, ${key}, ${content})\n ON CONFLICT(label, key) DO UPDATE SET\n content = ${content},\n updated_at = CURRENT_TIMESTAMP\n `;\n\n // Index in FTS\n this.agent.sql`\n INSERT INTO cf_agents_search_fts (label, key, content)\n VALUES (${this.label}, ${key}, ${content})\n `;\n }\n\n private deleteFTS(key: string): void {\n const rows = this.agent.sql<{ rowid: number }>`\n SELECT rowid FROM cf_agents_search_fts\n WHERE key = ${key} AND label = ${this.label}\n `;\n for (const row of rows) {\n this.agent\n .sql`DELETE FROM cf_agents_search_fts WHERE rowid = ${row.rowid}`;\n }\n }\n}\n","/**\n * Skill Provider — on-demand keyed document collections.\n *\n * Extends ContextProvider with `load()` for on-demand content fetching\n * and a keyed `set()` for writing individual entries.\n *\n * Duck-typed: if a provider has a `load` method, it's a SkillProvider.\n */\n\nimport type { ContextProvider } from \"./context\";\n\n/**\n * Storage interface for skill collections.\n *\n * - `get()` returns metadata listing (rendered into system prompt)\n * - `load(key)` fetches full content (via load_context tool)\n * - `set(key, content, description?)` writes an entry (via set_context tool)\n */\nexport interface SkillProvider extends ContextProvider {\n load(key: string): Promise<string | null>;\n set?(key: string, content: string, description?: string): Promise<void>;\n}\n\n/**\n * Check if a provider is a SkillProvider (has a `load` method).\n */\nexport function isSkillProvider(provider: unknown): provider is SkillProvider {\n return (\n typeof provider === \"object\" &&\n provider !== null &&\n \"load\" in provider &&\n typeof (provider as SkillProvider).load === \"function\"\n );\n}\n\n// ── R2 Skill Provider ──────────────────────────────────────────────\n\n/**\n * SkillProvider backed by an R2 bucket.\n *\n * - `get()` returns a metadata listing of all skills (key + description)\n * - `load(key)` fetches a skill's full content\n * - `set(key, content, description?)` writes a skill\n *\n * Descriptions are pulled from R2 custom metadata (`description` key).\n * If a prefix is provided, it is prepended on storage operations and\n * stripped from keys in metadata.\n *\n * @example\n * ```ts\n * const skills = new R2SkillProvider(env.SKILLS_BUCKET, { prefix: \"skills/\" });\n * ```\n */\nexport class R2SkillProvider implements SkillProvider {\n private bucket: R2Bucket;\n private prefix: string;\n\n constructor(bucket: R2Bucket, options?: { prefix?: string }) {\n this.bucket = bucket;\n this.prefix = options?.prefix ?? \"\";\n }\n\n async get(): Promise<string | null> {\n const entries: string[] = [];\n let cursor: string | undefined;\n let truncated = true;\n while (truncated) {\n const listed = await this.bucket.list({\n prefix: this.prefix,\n cursor,\n include: [\"customMetadata\"]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n for (const obj of listed.objects) {\n const key = obj.key.slice(this.prefix.length);\n const desc = obj.customMetadata?.description;\n entries.push(`- ${key}${desc ? `: ${desc}` : \"\"}`);\n }\n truncated = listed.truncated;\n cursor = listed.truncated ? listed.cursor : undefined;\n }\n return entries.length > 0 ? entries.join(\"\\n\") : null;\n }\n\n async load(key: string): Promise<string | null> {\n const obj = await this.bucket.get(this.prefix + key);\n if (!obj) return null;\n return obj.text();\n }\n\n async set(key: string, content: string, description?: string): Promise<void> {\n await this.bucket.put(this.prefix + key, content, {\n customMetadata: description ? { description } : undefined\n });\n }\n}\n","/**\n * Context Block Management\n *\n * Persistent key-value blocks (MEMORY, USER, SOUL, etc.) that are:\n * - Loaded from their providers at init\n * - Frozen into a snapshot when toSystemPrompt() is called\n * - Updated via setBlock() which writes to the provider immediately\n * but does NOT update the frozen snapshot (preserves LLM prefix cache)\n * - Re-snapshotted on next toSystemPrompt() call\n *\n * Provider type determines behavior:\n * - ContextProvider (get only) → readonly block in system prompt\n * - WritableContextProvider (get+set) → writable via set_context tool\n * - SkillProvider (get+load+set?) → metadata in prompt, load_context tool\n * - SearchProvider (get+search+set?) → searchable via search_context tool\n */\n\nimport { jsonSchema, type ToolSet } from \"ai\";\nimport { estimateStringTokens } from \"../utils/tokens\";\nimport { isSearchProvider, type SearchProvider } from \"./search\";\nimport { isSkillProvider, type SkillProvider } from \"./skills\";\n\n/**\n * Base storage interface for a context block.\n * A provider with only `get()` is readonly.\n */\nexport interface ContextProvider {\n get(): Promise<string | null>;\n /** Called by the context system to provide the block label before first use. */\n init?(label: string): void;\n}\n\n/**\n * Writable context provider — extends ContextProvider with `set()`.\n * Blocks backed by this provider are writable via the `set_context` tool.\n */\nexport interface WritableContextProvider extends ContextProvider {\n set(content: string): Promise<void>;\n}\n\n/**\n * Check if a provider is writable (has a `set` method).\n */\nexport function isWritableProvider(\n provider: unknown\n): provider is WritableContextProvider {\n return (\n typeof provider === \"object\" &&\n provider !== null &&\n \"set\" in provider &&\n typeof (provider as WritableContextProvider).set === \"function\"\n );\n}\n\n/**\n * Configuration for a context block.\n */\nexport interface ContextConfig {\n /** Block label — used as key and in tool descriptions */\n label: string;\n /** Human-readable description (shown to AI in tool) */\n description?: string;\n /** Maximum tokens allowed. Enforced on set. */\n maxTokens?: number;\n /** Storage provider. Determines block behavior:\n * - ContextProvider (get only) → readonly\n * - WritableContextProvider (get+set) → writable via set_context\n * - SkillProvider (get+load+set?) → on-demand via load_context\n * - SearchProvider (get+search+set?) → searchable via search_context\n * If omitted, auto-wired to writable SQLite when using builder. */\n provider?:\n | ContextProvider\n | WritableContextProvider\n | SkillProvider\n | SearchProvider;\n}\n\n/**\n * A loaded context block with computed token count.\n */\nexport interface ContextBlock {\n label: string;\n description?: string;\n content: string;\n tokens: number;\n maxTokens?: number;\n /** True if provider is writable (has set) */\n writable: boolean;\n /** True if backed by a SkillProvider */\n isSkill: boolean;\n /** True if backed by a SearchProvider */\n isSearchable: boolean;\n}\n\n/**\n * Manages context blocks with frozen snapshot support.\n */\nexport class ContextBlocks {\n private configs: ContextConfig[];\n private blocks = new Map<string, ContextBlock>();\n private snapshot: string | null = null;\n private loaded = false;\n private promptStore: WritableContextProvider | null;\n\n constructor(configs: ContextConfig[], promptStore?: WritableContextProvider) {\n this.configs = configs;\n this.promptStore = promptStore ?? null;\n }\n\n isLoaded(): boolean {\n return this.loaded;\n }\n\n /**\n * Load all blocks from their providers.\n * Called once at session init.\n */\n async load(): Promise<void> {\n for (const config of this.configs) {\n // Pass the label to the provider before first use\n if (config.provider?.init) {\n config.provider.init(config.label);\n }\n\n const content = config.provider\n ? ((await config.provider.get()) ?? \"\")\n : \"\";\n\n const skill = config.provider ? isSkillProvider(config.provider) : false;\n const searchable = config.provider\n ? isSearchProvider(config.provider)\n : false;\n const writable = config.provider\n ? isWritableProvider(config.provider) ||\n (skill && !!(config.provider as SkillProvider).set) ||\n (searchable && !!(config.provider as SearchProvider).set)\n : false;\n\n this.blocks.set(config.label, {\n label: config.label,\n description: config.description,\n content,\n tokens: estimateStringTokens(content),\n maxTokens: config.maxTokens,\n writable,\n isSkill: skill,\n isSearchable: searchable\n });\n }\n this.loaded = true;\n }\n\n /**\n * Get a block by label.\n */\n getBlock(label: string): ContextBlock | null {\n return this.blocks.get(label) ?? null;\n }\n\n /**\n * Get all blocks.\n */\n getBlocks(): ContextBlock[] {\n return Array.from(this.blocks.values());\n }\n\n /**\n * Set block content. Writes to provider immediately.\n * Does NOT update the frozen snapshot.\n */\n async setBlock(label: string, content: string): Promise<ContextBlock> {\n if (!this.loaded) await this.load();\n const config = this.configs.find((c) => c.label === label);\n const existing = this.blocks.get(label);\n\n if (!existing?.writable) {\n throw new Error(`Block \"${label}\" is readonly`);\n }\n\n if (existing.isSkill || existing.isSearchable) {\n throw new Error(\n `Block \"${label}\" is a keyed provider. Use setSkill() or setSearchEntry() instead.`\n );\n }\n\n const tokens = estimateStringTokens(content);\n const maxTokens = config?.maxTokens ?? existing?.maxTokens;\n\n if (maxTokens !== undefined && tokens > maxTokens) {\n throw new Error(\n `Block \"${label}\" exceeds maxTokens: ${tokens} > ${maxTokens}`\n );\n }\n\n const block: ContextBlock = {\n label,\n description: config?.description ?? existing?.description,\n content,\n tokens,\n maxTokens,\n writable: true,\n isSkill: false,\n isSearchable: false\n };\n\n this.blocks.set(label, block);\n\n // Write to provider immediately (durable)\n if (config?.provider && isWritableProvider(config.provider)) {\n await config.provider.set(content);\n }\n\n return block;\n }\n\n /**\n * Set a skill entry within a skill block.\n */\n async setSkill(\n label: string,\n key: string,\n content: string,\n description?: string\n ): Promise<void> {\n if (!this.loaded) await this.load();\n const config = this.configs.find((c) => c.label === label);\n const existing = this.blocks.get(label);\n\n if (!existing?.isSkill) {\n throw new Error(`Block \"${label}\" is not a skill provider`);\n }\n\n const provider = config?.provider;\n if (!provider || !isSkillProvider(provider) || !provider.set) {\n throw new Error(`Block \"${label}\" does not support writes`);\n }\n\n await provider.set(key, content, description);\n\n // Refresh metadata\n const metadata = await provider.get();\n if (metadata) {\n existing.content = metadata;\n existing.tokens = estimateStringTokens(metadata);\n }\n }\n\n /**\n * Load a skill's full content from a skill block.\n */\n async loadSkill(label: string, key: string): Promise<string | null> {\n if (!this.loaded) await this.load();\n const config = this.configs.find((c) => c.label === label);\n\n if (!config?.provider || !isSkillProvider(config.provider)) {\n throw new Error(`Block \"${label}\" is not a skill provider`);\n }\n\n return config.provider.load(key);\n }\n\n /**\n * Index a search entry within a searchable block.\n */\n async setSearchEntry(\n label: string,\n key: string,\n content: string\n ): Promise<void> {\n if (!this.loaded) await this.load();\n const config = this.configs.find((c) => c.label === label);\n const existing = this.blocks.get(label);\n\n if (!existing?.isSearchable) {\n throw new Error(`Block \"${label}\" is not a search provider`);\n }\n\n const provider = config?.provider;\n if (!provider || !isSearchProvider(provider) || !provider.set) {\n throw new Error(`Block \"${label}\" does not support writes`);\n }\n\n await provider.set(key, content);\n\n // Refresh summary\n const summary = await provider.get();\n existing.content = summary ?? \"\";\n existing.tokens = estimateStringTokens(existing.content);\n }\n\n /**\n * Search a searchable block.\n */\n async searchContext(label: string, query: string): Promise<string | null> {\n if (!this.loaded) await this.load();\n const config = this.configs.find((c) => c.label === label);\n\n if (!config?.provider || !isSearchProvider(config.provider)) {\n throw new Error(`Block \"${label}\" is not a search provider`);\n }\n\n return config.provider.search(query);\n }\n\n /**\n * Append content to a block.\n */\n async appendToBlock(label: string, content: string): Promise<ContextBlock> {\n if (!this.loaded) await this.load();\n const existing = this.blocks.get(label);\n if (!existing) {\n throw new Error(`Block \"${label}\" not found`);\n }\n return this.setBlock(label, existing.content + content);\n }\n\n /**\n * Get the system prompt string with context blocks.\n *\n * Returns a frozen snapshot: first call renders and caches,\n * subsequent calls return the same string (preserves LLM prefix cache).\n * Call refreshSnapshot() to re-render after block changes take effect.\n */\n toSystemPrompt(): string {\n if (!this.loaded) {\n throw new Error(\"Context blocks not loaded. Call load() first.\");\n }\n\n if (this.snapshot !== null) {\n return this.snapshot;\n }\n\n return this.captureSnapshot();\n }\n\n /**\n * Force re-render the snapshot from current block state.\n */\n refreshSnapshot(): string {\n return this.captureSnapshot();\n }\n\n private captureSnapshot(): string {\n const parts: string[] = [];\n const sep = \"═\".repeat(46);\n\n for (const block of this.blocks.values()) {\n // Searchable blocks render even when empty so the model knows they exist\n if (!block.content && !block.isSearchable) continue;\n\n let header = block.label.toUpperCase();\n const hints: string[] = [];\n if (block.description) hints.push(block.description);\n if (block.isSkill) hints.push(\"use load_context to load\");\n if (block.isSearchable) hints.push(\"use search_context to search\");\n if (hints.length > 0) header += ` (${hints.join(\" — \")})`;\n if (block.maxTokens) {\n const pct = Math.round((block.tokens / block.maxTokens) * 100);\n header += ` [${pct}% — ${block.tokens}/${block.maxTokens} tokens]`;\n }\n if (!block.writable) header += \" [readonly]\";\n\n parts.push(`${sep}\\n${header}\\n${sep}\\n${block.content}`);\n }\n\n this.snapshot = parts.join(\"\\n\\n\");\n return this.snapshot;\n }\n\n /**\n * Get writable blocks (for tool description).\n */\n getWritableBlocks(): ContextBlock[] {\n return Array.from(this.blocks.values()).filter((b) => b.writable);\n }\n\n /**\n * Check if any skill providers are registered.\n */\n hasSkillBlocks(): boolean {\n return Array.from(this.blocks.values()).some((b) => b.isSkill);\n }\n\n /**\n * Get skill block labels.\n */\n getSkillLabels(): string[] {\n return Array.from(this.blocks.values())\n .filter((b) => b.isSkill)\n .map((b) => b.label);\n }\n\n /**\n * Check if any search providers are registered.\n */\n hasSearchBlocks(): boolean {\n return Array.from(this.blocks.values()).some((b) => b.isSearchable);\n }\n\n /**\n * Get searchable block labels.\n */\n getSearchLabels(): string[] {\n return Array.from(this.blocks.values())\n .filter((b) => b.isSearchable)\n .map((b) => b.label);\n }\n\n // ── Public API ──────────────────────────────────────────────────\n\n /**\n * Frozen system prompt. On first call:\n * 1. Checks store for a persisted prompt (survives DO eviction)\n * 2. If none, loads blocks from providers, renders, and persists\n */\n async freezeSystemPrompt(): Promise<string> {\n if (this.promptStore) {\n const stored = await this.promptStore.get();\n if (stored !== null) return stored;\n }\n\n if (!this.loaded) await this.load();\n const prompt = this.toSystemPrompt();\n\n if (this.promptStore) {\n await this.promptStore.set(prompt);\n }\n\n return prompt;\n }\n\n /**\n * Re-render the system prompt from current block state and persist.\n */\n async refreshSystemPrompt(): Promise<string> {\n if (!this.loaded) await this.load();\n const prompt = this.refreshSnapshot();\n\n if (this.promptStore) {\n await this.promptStore.set(prompt);\n }\n\n return prompt;\n }\n\n /**\n * AI tools for context blocks.\n *\n * Auto-wired based on provider capabilities:\n * - `set_context` — when any block is writable\n * - `load_context` — when any block is a skill provider\n * - `search_context` — when any block is a search provider\n */\n async tools(): Promise<ToolSet> {\n if (!this.loaded) await this.load();\n\n const writable = this.getWritableBlocks();\n const hasSkills = this.hasSkillBlocks();\n const hasSearch = this.hasSearchBlocks();\n const toolSet: ToolSet = {};\n\n // ── set_context ──────────────────────────────────────────────\n\n if (writable.length > 0) {\n const regularBlocks = writable.filter(\n (b) => !b.isSkill && !b.isSearchable\n );\n const keyedBlocks = writable.filter((b) => b.isSkill || b.isSearchable);\n\n const blockDescriptions: string[] = [];\n for (const b of regularBlocks) {\n blockDescriptions.push(\n `- \"${b.label}\": ${b.description ?? \"no description\"}`\n );\n }\n for (const b of keyedBlocks) {\n const kind = b.isSkill\n ? \"skill collection (requires key and optional description)\"\n : \"searchable (requires key)\";\n blockDescriptions.push(`- \"${b.label}\": ${kind}`);\n }\n\n const properties: Record<string, unknown> = {\n label: {\n type: \"string\" as const,\n enum: writable.map((b) => b.label),\n description: \"Block label to write to\"\n },\n content: {\n type: \"string\" as const,\n description: \"Content to write\"\n },\n action: {\n type: \"string\" as const,\n enum: [\"replace\", \"append\"],\n description: \"replace (default) or append\"\n }\n };\n\n const required = [\"label\", \"content\"];\n\n if (keyedBlocks.length > 0) {\n properties.key = {\n type: \"string\" as const,\n description:\n \"Entry key (required for keyed blocks: \" +\n keyedBlocks.map((b) => `\"${b.label}\"`).join(\", \") +\n \")\"\n };\n }\n\n if (keyedBlocks.some((b) => b.isSkill)) {\n properties.description = {\n type: \"string\" as const,\n description: \"Short description for the skill entry\"\n };\n }\n\n toolSet.set_context = {\n description: `Write to a context block. Available blocks:\\n${blockDescriptions.join(\"\\n\")}\\n\\nWrites are durable and persist across sessions.`,\n inputSchema: jsonSchema({\n type: \"object\" as const,\n properties: properties as Record<string, object>,\n required\n }),\n execute: async ({\n label,\n content,\n key,\n description,\n action\n }: {\n label: string;\n content: string;\n key?: string;\n description?: string;\n action?: string;\n }) => {\n try {\n const block = this.blocks.get(label);\n if (!block) return `Error: block \"${label}\" not found`;\n\n if (block.isSkill) {\n if (!key)\n return `Error: key is required for skill block \"${label}\"`;\n await this.setSkill(label, key, content, description);\n return `Written skill \"${key}\" to ${label}.`;\n }\n\n if (block.isSearchable) {\n if (!key)\n return `Error: key is required for searchable block \"${label}\"`;\n await this.setSearchEntry(label, key, content);\n return `Indexed \"${key}\" in ${label}.`;\n }\n\n const updated =\n action === \"append\"\n ? await this.appendToBlock(label, content)\n : await this.setBlock(label, content);\n const usage = updated.maxTokens\n ? `${Math.round((updated.tokens / updated.maxTokens) * 100)}% (${updated.tokens}/${updated.maxTokens} tokens)`\n : `${updated.tokens} tokens`;\n return `Written to ${label}. Usage: ${usage}`;\n } catch (err) {\n return `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n };\n }\n\n // ── load_context ─────────────────────────────────────────────\n\n if (hasSkills) {\n const skillLabels = this.getSkillLabels();\n\n toolSet.load_context = {\n description:\n \"Load a document from a skill block by key. \" +\n \"Available skill blocks: \" +\n skillLabels.map((l) => `\"${l}\"`).join(\", \") +\n \". Check the system prompt for available keys.\",\n inputSchema: jsonSchema({\n type: \"object\" as const,\n properties: {\n label: {\n type: \"string\" as const,\n enum: skillLabels,\n description: \"Skill block label\"\n },\n key: {\n type: \"string\" as const,\n description: \"Skill key to load\"\n }\n },\n required: [\"label\", \"key\"]\n }),\n execute: async ({ label, key }: { label: string; key: string }) => {\n try {\n const content = await this.loadSkill(label, key);\n return content ?? `Not found: ${key}`;\n } catch (err) {\n return `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n };\n }\n\n // ── search_context ────────────────────────────────────────────\n\n if (hasSearch) {\n const searchLabels = this.getSearchLabels();\n\n toolSet.search_context = {\n description:\n \"Search for information in a searchable context block. \" +\n \"Available searchable blocks: \" +\n searchLabels.map((l) => `\"${l}\"`).join(\", \") +\n \".\",\n inputSchema: jsonSchema({\n type: \"object\" as const,\n properties: {\n label: {\n type: \"string\" as const,\n enum: searchLabels,\n description: \"Searchable block label\"\n },\n query: {\n type: \"string\" as const,\n description: \"Search query\"\n }\n },\n required: [\"label\", \"query\"]\n }),\n execute: async ({ label, query }: { label: string; query: string }) => {\n try {\n const results = await this.searchContext(label, query);\n return results ?? \"No results found.\";\n } catch (err) {\n return `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n };\n }\n\n return toolSet;\n }\n}\n","/**\n * Agent Session Provider\n *\n * SQLite-backed provider with tree-structured messages (branching),\n * compaction overlays, and FTS5 search.\n */\n\nimport type { UIMessage } from \"ai\";\nimport type {\n SessionProvider,\n SearchResult,\n StoredCompaction\n} from \"../provider\";\nimport { COMPACTION_PREFIX } from \"../../utils/compaction-helpers\";\n\nexport interface SqlProvider {\n sql<T = Record<string, string | number | boolean | null>>(\n strings: TemplateStringsArray,\n ...values: (string | number | boolean | null)[]\n ): T[];\n}\n\nexport class AgentSessionProvider implements SessionProvider {\n private agent: SqlProvider;\n private initialized = false;\n private sessionId: string;\n\n /**\n * @param agent - Agent or any object with a `sql` tagged template method\n * @param sessionId - Optional session ID to isolate multiple sessions in the same DO.\n * Messages are filtered by session_id within shared tables.\n */\n constructor(agent: SqlProvider, sessionId?: string) {\n this.agent = agent;\n this.sessionId = sessionId ?? \"\";\n }\n\n private ensureTable(): void {\n if (this.initialized) return;\n\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS assistant_messages (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL DEFAULT '',\n parent_id TEXT,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n this.agent.sql`\n CREATE INDEX IF NOT EXISTS idx_assistant_msg_parent\n ON assistant_messages(parent_id)\n `;\n\n this.agent.sql`\n CREATE INDEX IF NOT EXISTS idx_assistant_msg_session\n ON assistant_messages(session_id)\n `;\n\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS assistant_compactions (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL DEFAULT '',\n summary TEXT NOT NULL,\n from_message_id TEXT NOT NULL,\n to_message_id TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n this.agent.sql`\n CREATE VIRTUAL TABLE IF NOT EXISTS assistant_fts\n USING fts5(id UNINDEXED, session_id UNINDEXED, role UNINDEXED, content, tokenize='porter unicode61')\n `;\n\n // Reserved for SessionManager metadata (PR #1167) and Think integration (PR #1169)\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS assistant_config (\n session_id TEXT NOT NULL,\n key TEXT NOT NULL,\n value TEXT NOT NULL,\n PRIMARY KEY (session_id, key)\n )\n `;\n\n this.initialized = true;\n }\n\n // ── Read ───────────────────────────────────────────────────────\n\n getMessage(id: string): UIMessage | null {\n this.ensureTable();\n const rows = this.agent.sql<{ content: string }>`\n SELECT content FROM assistant_messages WHERE id = ${id} AND session_id = ${this.sessionId}\n `;\n return rows.length > 0 ? this.parse(rows[0].content) : null;\n }\n\n getHistory(leafId?: string | null): UIMessage[] {\n this.ensureTable();\n\n const leaf = leafId\n ? this.agent.sql<{ id: string }>`\n SELECT id FROM assistant_messages WHERE id = ${leafId} AND session_id = ${this.sessionId}\n `[0]\n : this.latestLeafRow();\n\n if (!leaf) return [];\n\n const path = this.agent.sql<{ content: string }>`\n WITH RECURSIVE path AS (\n SELECT *, 0 as depth FROM assistant_messages WHERE id = ${leaf.id}\n UNION ALL\n SELECT m.*, p.depth + 1 FROM assistant_messages m\n JOIN path p ON m.id = p.parent_id\n WHERE m.session_id = ${this.sessionId} AND p.depth < 10000\n )\n SELECT content FROM path ORDER BY depth DESC\n `;\n\n const messages = this.parseRows(path);\n const compactions = this.getCompactions();\n if (compactions.length === 0) return messages;\n return this.applyCompactions(messages, compactions);\n }\n\n getLatestLeaf(): UIMessage | null {\n this.ensureTable();\n const row = this.latestLeafRow();\n return row ? this.parse(row.content) : null;\n }\n\n getBranches(messageId: string): UIMessage[] {\n this.ensureTable();\n const rows = this.agent.sql<{ content: string }>`\n SELECT content FROM assistant_messages\n WHERE parent_id = ${messageId} AND session_id = ${this.sessionId} ORDER BY created_at ASC\n `;\n return this.parseRows(rows);\n }\n\n getPathLength(leafId?: string | null): number {\n this.ensureTable();\n const leaf = leafId\n ? this.agent.sql<{ id: string }>`\n SELECT id FROM assistant_messages WHERE id = ${leafId} AND session_id = ${this.sessionId}\n `[0]\n : this.latestLeafRow();\n if (!leaf) return 0;\n\n const rows = this.agent.sql<{ count: number }>`\n WITH RECURSIVE path AS (\n SELECT id, parent_id, 0 as depth FROM assistant_messages WHERE id = ${leaf.id}\n UNION ALL\n SELECT m.id, m.parent_id, p.depth + 1 FROM assistant_messages m\n JOIN path p ON m.id = p.parent_id\n WHERE m.session_id = ${this.sessionId} AND p.depth < 10000\n )\n SELECT COUNT(*) as count FROM path\n `;\n return rows[0]?.count ?? 0;\n }\n\n // ── Write ──────────────────────────────────────────────────────\n\n appendMessage(message: UIMessage, parentId?: string | null): void {\n this.ensureTable();\n // Skip if message already exists (INSERT OR IGNORE idempotency)\n const existing = this.agent.sql<{ id: string }>`\n SELECT id FROM assistant_messages WHERE id = ${message.id} AND session_id = ${this.sessionId}\n `;\n if (existing.length > 0) return;\n\n let parent = parentId ?? this.latestLeafRow()?.id ?? null;\n\n // Validate parentId belongs to this session\n if (parent) {\n const valid = this.agent.sql<{ id: string }>`\n SELECT id FROM assistant_messages WHERE id = ${parent} AND session_id = ${this.sessionId}\n `;\n if (valid.length === 0) parent = null;\n }\n\n const json = JSON.stringify(message);\n\n this.agent.sql`\n INSERT INTO assistant_messages (id, session_id, parent_id, role, content)\n VALUES (${message.id}, ${this.sessionId}, ${parent}, ${message.role}, ${json})\n `;\n this.indexFTS(message);\n }\n\n updateMessage(message: UIMessage): void {\n this.ensureTable();\n this.agent.sql`\n UPDATE assistant_messages SET content = ${JSON.stringify(message)}\n WHERE id = ${message.id} AND session_id = ${this.sessionId}\n `;\n this.indexFTS(message);\n }\n\n deleteMessages(messageIds: string[]): void {\n this.ensureTable();\n for (const id of messageIds) {\n this.agent\n .sql`DELETE FROM assistant_messages WHERE id = ${id} AND session_id = ${this.sessionId}`;\n this.deleteFTS(id);\n }\n }\n\n clearMessages(): void {\n this.ensureTable();\n this.agent\n .sql`DELETE FROM assistant_messages WHERE session_id = ${this.sessionId}`;\n this.agent\n .sql`DELETE FROM assistant_compactions WHERE session_id = ${this.sessionId}`;\n // FTS5 requires delete by rowid\n const ftsRows = this.agent.sql<{ rowid: number }>`\n SELECT rowid FROM assistant_fts WHERE session_id = ${this.sessionId}\n `;\n for (const row of ftsRows) {\n this.agent.sql`DELETE FROM assistant_fts WHERE rowid = ${row.rowid}`;\n }\n }\n\n // ── Compaction ─────────────────────────────────────────────────\n\n addCompaction(\n summary: string,\n fromMessageId: string,\n toMessageId: string\n ): StoredCompaction {\n this.ensureTable();\n const id = crypto.randomUUID();\n this.agent.sql`\n INSERT INTO assistant_compactions (id, session_id, summary, from_message_id, to_message_id)\n VALUES (${id}, ${this.sessionId}, ${summary}, ${fromMessageId}, ${toMessageId})\n `;\n return {\n id,\n summary,\n fromMessageId,\n toMessageId,\n createdAt: new Date().toISOString()\n };\n }\n\n getCompactions(): StoredCompaction[] {\n this.ensureTable();\n type Row = {\n id: string;\n summary: string;\n from_message_id: string;\n to_message_id: string;\n created_at: string;\n };\n return this.agent.sql<Row>`\n SELECT * FROM assistant_compactions WHERE session_id = ${this.sessionId} ORDER BY created_at ASC\n `.map((r) => ({\n id: r.id,\n summary: r.summary,\n fromMessageId: r.from_message_id,\n toMessageId: r.to_message_id,\n createdAt: r.created_at\n }));\n }\n\n // ── Search ─────────────────────────────────────────────────────\n\n searchMessages(query: string, limit = 20): SearchResult[] {\n this.ensureTable();\n // Sanitize query: wrap in double quotes to treat as literal phrase,\n // escaping any existing double quotes to prevent FTS5 syntax injection\n const sanitized = `\"${query.replace(/\"/g, '\"\"')}\"`;\n try {\n return this.agent.sql<{ id: string; role: string; content: string }>`\n SELECT f.id, f.role, f.content FROM assistant_fts f\n INNER JOIN assistant_messages m ON m.id = f.id AND m.session_id = f.session_id\n WHERE assistant_fts MATCH ${sanitized} AND f.session_id = ${this.sessionId}\n ORDER BY rank LIMIT ${limit}\n `.map((r) => ({\n id: r.id,\n role: r.role,\n content: r.content\n }));\n } catch {\n // Malformed FTS query — return empty results\n return [];\n }\n }\n\n // ── Internal ───────────────────────────────────────────────────\n\n private latestLeafRow(): { id: string; content: string } | null {\n const rows = this.agent.sql<{ id: string; content: string }>`\n SELECT m.id, m.content FROM assistant_messages m\n LEFT JOIN assistant_messages c ON c.parent_id = m.id AND c.session_id = ${this.sessionId}\n WHERE c.id IS NULL AND m.session_id = ${this.sessionId}\n ORDER BY m.created_at DESC, m.rowid DESC LIMIT 1\n `;\n return rows[0] ?? null;\n }\n\n private indexFTS(message: UIMessage): void {\n const text = message.parts\n .filter((p) => p.type === \"text\")\n .map((p) => (p as { text: string }).text)\n .join(\" \");\n // Always delete old entry first — handles text→no-text transitions\n this.deleteFTS(message.id);\n if (text) {\n this.agent.sql`\n INSERT INTO assistant_fts (id, session_id, role, content)\n VALUES (${message.id}, ${this.sessionId}, ${message.role}, ${text})\n `;\n }\n }\n\n private deleteFTS(id: string): void {\n const rows = this.agent.sql<{ rowid: number }>`\n SELECT rowid FROM assistant_fts WHERE id = ${id} AND session_id = ${this.sessionId}\n `;\n for (const row of rows) {\n this.agent.sql`DELETE FROM assistant_fts WHERE rowid = ${row.rowid}`;\n }\n }\n\n private applyCompactions(\n messages: UIMessage[],\n compactions: StoredCompaction[]\n ): UIMessage[] {\n const ids = messages.map((m) => m.id);\n const result: UIMessage[] = [];\n let i = 0;\n while (i < messages.length) {\n // Find all compactions starting at this message, pick the latest\n // (widest range) so newer compactions supersede older ones\n const matching = compactions.filter((c) => c.fromMessageId === ids[i]);\n const comp =\n matching.length > 1 ? matching[matching.length - 1] : matching[0];\n if (comp) {\n const endIdx = ids.indexOf(comp.toMessageId);\n if (endIdx >= i) {\n result.push({\n id: `${COMPACTION_PREFIX}${comp.id}`,\n role: \"assistant\",\n parts: [\n {\n type: \"text\",\n text: comp.summary\n }\n ],\n createdAt: new Date()\n } as UIMessage);\n i = endIdx + 1;\n continue;\n }\n }\n result.push(messages[i]);\n i++;\n }\n return result;\n }\n\n private parse(json: string): UIMessage | null {\n try {\n const msg = JSON.parse(json);\n if (\n typeof msg?.id === \"string\" &&\n typeof msg?.role === \"string\" &&\n Array.isArray(msg?.parts)\n ) {\n return msg;\n }\n } catch {\n /* skip */\n }\n return null;\n }\n\n private parseRows(rows: { content: string }[]): UIMessage[] {\n const result: UIMessage[] = [];\n for (const row of rows) {\n const msg = this.parse(row.content);\n if (msg) result.push(msg);\n }\n return result;\n }\n}\n","/**\n * SQLite Context Block Provider\n *\n * Default durable storage for context blocks using DO SQLite.\n * Each block is a row in cf_agents_context_blocks.\n */\n\nimport type { WritableContextProvider } from \"../context\";\nimport type { SqlProvider } from \"./agent\";\n\nexport class AgentContextProvider implements WritableContextProvider {\n private agent: SqlProvider;\n private label: string;\n private initialized = false;\n\n constructor(agent: SqlProvider, label?: string) {\n this.agent = agent;\n this.label = label ?? \"\";\n }\n\n init(label: string): void {\n if (!this.label) {\n this.label = label;\n }\n }\n\n private ensureTable(): void {\n if (this.initialized) return;\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_context_blocks (\n label TEXT PRIMARY KEY,\n content TEXT NOT NULL,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `;\n this.initialized = true;\n }\n\n async get(): Promise<string | null> {\n this.ensureTable();\n const rows = this.agent.sql<{ content: string }>`\n SELECT content FROM cf_agents_context_blocks WHERE label = ${this.label}\n `;\n return rows[0]?.content ?? null;\n }\n\n async set(content: string): Promise<void> {\n this.ensureTable();\n this.agent.sql`\n INSERT INTO cf_agents_context_blocks (label, content)\n VALUES (${this.label}, ${content})\n ON CONFLICT(label) DO UPDATE SET content = ${content}, updated_at = CURRENT_TIMESTAMP\n `;\n }\n}\n","/**\n * Session — conversation history, context blocks, compaction, search, and tools.\n */\n\nimport type { ToolSet } from \"ai\";\nimport type { UIMessage } from \"ai\";\nimport type { SessionProvider, StoredCompaction } from \"./provider\";\nimport type { SessionOptions } from \"./types\";\nimport {\n ContextBlocks,\n type ContextBlock,\n type ContextConfig,\n type WritableContextProvider\n} from \"./context\";\nimport { AgentSessionProvider, type SqlProvider } from \"./providers/agent\";\nimport { AgentContextProvider } from \"./providers/agent-context\";\nimport type { CompactResult } from \"../utils/compaction-helpers\";\nimport { estimateMessageTokens } from \"../utils/tokens\";\nimport { MessageType } from \"../../../types\";\n\nexport type SessionContextOptions = Omit<ContextConfig, \"label\">;\n\n// Raw builder entry — provider resolved at init time so chain order doesn't matter\ninterface PendingContext {\n label: string;\n options: SessionContextOptions;\n}\n\n/** Agent-like object that can broadcast to connected clients */\ninterface Broadcaster {\n broadcast(message: string | ArrayBufferLike): void;\n}\n\nfunction isBroadcaster(obj: unknown): obj is Broadcaster {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"broadcast\" in obj &&\n typeof (obj as Broadcaster).broadcast === \"function\"\n );\n}\n\nexport class Session {\n private storage!: SessionProvider;\n private context!: ContextBlocks;\n\n // Builder state — only used with Session.create()\n private _agent?: SqlProvider;\n private _broadcaster?: Broadcaster;\n private _sessionId?: string;\n private _pending?: PendingContext[];\n private _cachedPrompt?: WritableContextProvider | true;\n private _compactionFn?:\n | ((messages: UIMessage[]) => Promise<CompactResult | null>)\n | null;\n private _tokenThreshold?: number;\n private _ready = false;\n\n constructor(storage: SessionProvider, options?: SessionOptions) {\n this.storage = storage;\n this.context = new ContextBlocks(\n options?.context ?? [],\n options?.promptStore\n );\n this._ready = true;\n }\n\n /**\n * Chainable session creation with auto-wired SQLite providers.\n * Chain methods in any order — providers are resolved lazily on first use.\n *\n * @example\n * ```ts\n * const session = Session.create(this)\n * .withContext(\"soul\", { provider: { get: async () => \"You are helpful.\" } })\n * .withContext(\"memory\", { description: \"Learned facts\", maxTokens: 1100 })\n * .withCachedPrompt();\n *\n * // Skills from R2 (on-demand loading via load_context tool)\n * const session = Session.create(this)\n * .withContext(\"skills\", {\n * provider: new R2SkillProvider(env.SKILLS_BUCKET, { prefix: \"skills/\" })\n * })\n * .withCachedPrompt();\n * ```\n */\n static create(agent: SqlProvider): Session {\n const session: Session = Object.create(Session.prototype);\n session._agent = agent;\n if (isBroadcaster(agent)) {\n session._broadcaster = agent;\n }\n session._pending = [];\n session._ready = false;\n return session;\n }\n\n // ── Builder methods ─────────────────────────────────────────────\n\n forSession(sessionId: string): this {\n this._sessionId = sessionId;\n return this;\n }\n\n withContext(label: string, options?: SessionContextOptions): this {\n this._pending!.push({ label, options: options ?? {} });\n return this;\n }\n\n withCachedPrompt(provider?: WritableContextProvider): this {\n this._cachedPrompt = provider ?? true;\n return this;\n }\n\n /**\n * Register a compaction function. Called by `compact()` to compress\n * message history into a summary overlay.\n */\n onCompaction(\n fn: (messages: UIMessage[]) => Promise<CompactResult | null>\n ): this {\n this._compactionFn = fn;\n return this;\n }\n\n /**\n * Auto-compact when estimated token count exceeds the threshold.\n * Checked after each `appendMessage`. Requires `onCompaction()`.\n */\n compactAfter(tokenThreshold: number): this {\n this._tokenThreshold = tokenThreshold;\n return this;\n }\n\n // ── Lazy init ───────────────────────────────────────────────────\n\n private _ensureReady(): void {\n if (this._ready) return;\n\n // Resolve context configs — sessionId is final by now\n const configs: ContextConfig[] = (this._pending ?? []).map(\n ({ label, options: opts }) => {\n let provider = opts.provider;\n if (!provider) {\n // No provider → auto-wire to writable SQLite\n const key = this._sessionId ? `${label}_${this._sessionId}` : label;\n provider = new AgentContextProvider(this._agent!, key);\n }\n return {\n label,\n description: opts.description,\n maxTokens: opts.maxTokens,\n provider\n };\n }\n );\n\n // Resolve prompt store\n let promptStore: WritableContextProvider | undefined;\n if (this._cachedPrompt === true) {\n const key = this._sessionId\n ? `_system_prompt_${this._sessionId}`\n : \"_system_prompt\";\n promptStore = new AgentContextProvider(this._agent!, key);\n } else if (this._cachedPrompt) {\n promptStore = this._cachedPrompt;\n }\n\n this.storage = new AgentSessionProvider(this._agent!, this._sessionId);\n this.context = new ContextBlocks(configs, promptStore);\n this._ready = true;\n }\n\n // ── History (tree-structured) ─────────────────────────────────\n\n getHistory(leafId?: string | null): UIMessage[] {\n this._ensureReady();\n return this.storage.getHistory(leafId);\n }\n\n getMessage(id: string): UIMessage | null {\n this._ensureReady();\n return this.storage.getMessage(id);\n }\n\n getLatestLeaf(): UIMessage | null {\n this._ensureReady();\n return this.storage.getLatestLeaf();\n }\n\n getBranches(messageId: string): UIMessage[] {\n this._ensureReady();\n return this.storage.getBranches(messageId);\n }\n\n getPathLength(leafId?: string | null): number {\n this._ensureReady();\n return this.storage.getPathLength(leafId);\n }\n\n // ── Broadcast ──────────────────────────────────────────────────\n\n private _broadcast(type: MessageType, data: Record<string, unknown>): void {\n if (!this._broadcaster) return;\n this._broadcaster.broadcast(JSON.stringify({ type, ...data }));\n }\n\n private _emitStatus(\n phase: \"idle\" | \"compacting\",\n extra?: Record<string, unknown>\n ): number {\n const tokenEstimate = estimateMessageTokens(this.getHistory());\n this._broadcast(MessageType.CF_AGENT_SESSION, {\n phase,\n tokenEstimate,\n tokenThreshold: this._tokenThreshold ?? null,\n ...extra\n });\n return tokenEstimate;\n }\n\n private _emitError(error: string): void {\n this._broadcast(MessageType.CF_AGENT_SESSION_ERROR, { error });\n }\n\n // ── Write ─────────────────────────────────────────────────────\n\n async appendMessage(\n message: UIMessage,\n parentId?: string | null\n ): Promise<void> {\n this._ensureReady();\n this.storage.appendMessage(message, parentId);\n\n const tokenEstimate = this._emitStatus(\"idle\");\n\n if (\n this._tokenThreshold != null &&\n this._compactionFn &&\n tokenEstimate > this._tokenThreshold\n ) {\n try {\n await this.compact();\n } catch {\n // Auto-compact failure is non-fatal — message is already appended\n }\n }\n }\n\n updateMessage(message: UIMessage): void {\n this._ensureReady();\n this.storage.updateMessage(message);\n this._emitStatus(\"idle\");\n }\n\n deleteMessages(messageIds: string[]): void {\n this._ensureReady();\n this.storage.deleteMessages(messageIds);\n this._emitStatus(\"idle\");\n }\n\n clearMessages(): void {\n this._ensureReady();\n this.storage.clearMessages();\n this._emitStatus(\"idle\");\n }\n\n // ── Compaction ────────────────────────────────────────────────\n\n addCompaction(\n summary: string,\n fromMessageId: string,\n toMessageId: string\n ): StoredCompaction {\n this._ensureReady();\n return this.storage.addCompaction(summary, fromMessageId, toMessageId);\n }\n\n getCompactions(): StoredCompaction[] {\n this._ensureReady();\n return this.storage.getCompactions();\n }\n\n /**\n * Run the registered compaction function and store the result as an overlay.\n * Requires `onCompaction()` to be called first.\n */\n async compact(): Promise<CompactResult | null> {\n this._ensureReady();\n if (!this._compactionFn) {\n throw new Error(\n \"No compaction function registered. Call onCompaction() first.\"\n );\n }\n\n const tokensBefore = this._emitStatus(\"compacting\");\n\n let result: CompactResult | null;\n try {\n result = await this._compactionFn(this.getHistory());\n } catch (err) {\n this._emitError(err instanceof Error ? err.message : String(err));\n return null;\n }\n\n if (!result) {\n this._emitStatus(\"idle\");\n return null;\n }\n\n // Validate toMessageId exists in the history\n const historyIds = new Set(this.getHistory().map((m) => m.id));\n if (!historyIds.has(result.toMessageId)) {\n this._emitStatus(\"idle\");\n return null;\n }\n\n // Iterative compaction — extend from earliest existing compaction's start\n const existing = this.getCompactions();\n const fromId =\n existing.length > 0 ? existing[0].fromMessageId : result.fromMessageId;\n\n this.addCompaction(result.summary, fromId, result.toMessageId);\n await this.refreshSystemPrompt();\n\n this._emitStatus(\"idle\", {\n compacted: { tokensBefore }\n });\n\n return { ...result, fromMessageId: fromId };\n }\n\n // ── Context Blocks ────────────────────────────────────────────\n\n getContextBlock(label: string): ContextBlock | null {\n this._ensureReady();\n return this.context.getBlock(label);\n }\n\n getContextBlocks(): ContextBlock[] {\n this._ensureReady();\n return this.context.getBlocks();\n }\n\n async replaceContextBlock(\n label: string,\n content: string\n ): Promise<ContextBlock> {\n this._ensureReady();\n return this.context.setBlock(label, content);\n }\n\n async appendContextBlock(\n label: string,\n content: string\n ): Promise<ContextBlock> {\n this._ensureReady();\n return this.context.appendToBlock(label, content);\n }\n\n // ── System Prompt ─────────────────────────────────────────────\n\n async freezeSystemPrompt(): Promise<string> {\n this._ensureReady();\n return this.context.freezeSystemPrompt();\n }\n\n async refreshSystemPrompt(): Promise<string> {\n this._ensureReady();\n return this.context.refreshSystemPrompt();\n }\n\n // ── Search ────────────────────────────────────────────────────\n\n search(\n query: string,\n options?: { limit?: number }\n ): Array<{\n id: string;\n role: string;\n content: string;\n createdAt?: string;\n }> {\n this._ensureReady();\n if (!this.storage.searchMessages) {\n throw new Error(\"Session provider does not support search\");\n }\n return this.storage.searchMessages(query, options?.limit ?? 20);\n }\n\n // ── Tools ─────────────────────────────────────────────────────\n\n /** Returns set_context and load_context tools. */\n async tools(): Promise<ToolSet> {\n this._ensureReady();\n return this.context.tools();\n }\n}\n","/**\n * SessionManager — registry of named sessions.\n *\n * Lifecycle: create, get, list, delete, rename.\n * Convenience methods for message ops by session ID.\n * Cross-session search and tools.\n */\n\nimport type { UIMessage } from \"ai\";\nimport { jsonSchema, type ToolSet } from \"ai\";\nimport type { CompactResult } from \"../utils/compaction-helpers\";\nimport type { WritableContextProvider } from \"./context\";\nimport type { StoredCompaction } from \"./provider\";\nimport type { SqlProvider } from \"./providers/agent\";\nimport type { SearchProvider } from \"./search\";\nimport { Session, type SessionContextOptions } from \"./session\";\n\nexport interface SessionInfo {\n id: string;\n name: string;\n parent_session_id: string | null;\n model: string | null;\n source: string | null;\n input_tokens: number;\n output_tokens: number;\n estimated_cost: number;\n end_reason: string | null;\n created_at: string;\n updated_at: string;\n}\n\n// Pending context entry — resolved per-session with namespaced providers\ninterface PendingManagerContext {\n label: string;\n options: SessionContextOptions;\n}\n\nexport interface SessionManagerOptions {\n maxContextMessages?: number;\n}\n\nexport class SessionManager {\n private agent!: SqlProvider;\n private _maxContextMessages = 100;\n private _pending: PendingManagerContext[] = [];\n private _cachedPrompt?: WritableContextProvider | true;\n private _compactionFn?:\n | ((messages: UIMessage[]) => Promise<CompactResult | null>)\n | null;\n private _tokenThreshold?: number;\n private _sessions = new Map<string, Session>();\n private _historyLabel?: string;\n private _tableReady = false;\n private _ready = false;\n\n constructor(agent: SqlProvider, options: SessionManagerOptions = {}) {\n this.agent = agent;\n this._maxContextMessages = options.maxContextMessages ?? 100;\n this._ready = true;\n this._ensureTable();\n }\n\n /**\n * Chainable SessionManager creation with auto-wired context for all sessions.\n *\n * @example\n * ```ts\n * const manager = SessionManager.create(this)\n * .withContext(\"soul\", { provider: { get: async () => \"You are helpful.\" } })\n * .withContext(\"memory\", { description: \"Learned facts\", maxTokens: 1100 })\n * .withCachedPrompt()\n * .maxContextMessages(50);\n *\n * // Each getSession(id) auto-creates namespaced providers:\n * // memory key: \"memory_<sessionId>\"\n * // prompt key: \"_system_prompt_<sessionId>\"\n * const session = manager.getSession(\"chat-123\");\n * ```\n */\n static create(agent: SqlProvider): SessionManager {\n const mgr: SessionManager = Object.create(SessionManager.prototype);\n mgr.agent = agent;\n mgr._maxContextMessages = 100;\n mgr._pending = [];\n mgr._compactionFn = null;\n mgr._tokenThreshold = undefined;\n mgr._sessions = new Map();\n mgr._tableReady = false;\n mgr._ready = false;\n return mgr;\n }\n\n // ── Builder methods ─────────────────────────────────────────────\n\n withContext(label: string, options?: SessionContextOptions): this {\n this._pending.push({ label, options: options ?? {} });\n return this;\n }\n\n withCachedPrompt(provider?: WritableContextProvider): this {\n this._cachedPrompt = provider ?? true;\n return this;\n }\n\n maxContextMessages(count: number): this {\n this._maxContextMessages = count;\n return this;\n }\n\n /**\n * Register a compaction function propagated to all sessions.\n * Called by `Session.compact()` to compress message history.\n */\n onCompaction(\n fn: (messages: UIMessage[]) => Promise<CompactResult | null>\n ): this {\n this._compactionFn = fn;\n return this;\n }\n\n /**\n * Auto-compact when estimated token count exceeds the threshold.\n * Propagated to all sessions. Requires `onCompaction()`.\n */\n compactAfter(tokenThreshold: number): this {\n this._tokenThreshold = tokenThreshold;\n return this;\n }\n\n /**\n * Add a searchable context block that searches conversation history\n * across all sessions managed by this manager.\n *\n * The model can use `search_context` to find relevant messages from\n * any session. The block is readonly (no `set`).\n *\n * @example\n * ```ts\n * SessionManager.create(this)\n * .withContext(\"memory\", { maxTokens: 1100 })\n * .withSearchableHistory(\"history\")\n * .withCachedPrompt();\n * ```\n */\n withSearchableHistory(label: string): this {\n this._historyLabel = label;\n return this;\n }\n\n // ── Lazy init ───────────────────────────────────────────────────\n\n private _ensureReady(): void {\n if (this._ready) return;\n this._ready = true;\n this._ensureTable();\n }\n\n private _ensureTable(): void {\n if (this._tableReady) return;\n this.agent.sql`\n CREATE TABLE IF NOT EXISTS assistant_sessions (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n parent_session_id TEXT,\n model TEXT,\n source TEXT,\n input_tokens INTEGER DEFAULT 0,\n output_tokens INTEGER DEFAULT 0,\n estimated_cost REAL DEFAULT 0,\n end_reason TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `;\n this.agent.sql`\n CREATE VIRTUAL TABLE IF NOT EXISTS assistant_fts\n USING fts5(id UNINDEXED, session_id UNINDEXED, role UNINDEXED, content, tokenize='porter unicode61')\n `;\n this._tableReady = true;\n }\n\n private _createHistoryProvider(): SearchProvider {\n const mgr = this;\n return {\n async get() {\n const sessions = mgr.list();\n if (sessions.length === 0) return null;\n return `${sessions.length} session${sessions.length === 1 ? \"\" : \"s\"} available for search.`;\n },\n async search(query: string) {\n const results = mgr.search(query, { limit: 10 });\n if (results.length === 0) return null;\n return results.map((r) => `[${r.role}] ${r.content}`).join(\"\\n---\\n\");\n }\n // No set — conversation history is readonly\n };\n }\n\n // ── Session access ────────────────────────────────────────────\n\n /** Get or create the Session instance for a session ID. */\n getSession(sessionId: string): Session {\n this._ensureReady();\n let session = this._sessions.get(sessionId);\n if (!session) {\n const s = Session.create(this.agent).forSession(sessionId);\n for (const { label, options } of this._pending) {\n s.withContext(label, options);\n }\n if (this._cachedPrompt === true) {\n s.withCachedPrompt();\n } else if (this._cachedPrompt) {\n s.withCachedPrompt(this._cachedPrompt);\n }\n if (this._historyLabel) {\n s.withContext(this._historyLabel, {\n description: \"Cross-session conversation history\",\n provider: this._createHistoryProvider()\n });\n }\n if (this._compactionFn) {\n s.onCompaction(this._compactionFn);\n }\n if (this._tokenThreshold != null) {\n s.compactAfter(this._tokenThreshold);\n }\n session = s;\n this._sessions.set(sessionId, session);\n }\n return session;\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────\n\n create(\n name: string,\n opts?: { parentSessionId?: string; model?: string; source?: string }\n ): SessionInfo {\n this._ensureReady();\n const id = crypto.randomUUID();\n this.agent.sql`\n INSERT INTO assistant_sessions (id, name, parent_session_id, model, source)\n VALUES (${id}, ${name}, ${opts?.parentSessionId ?? null}, ${opts?.model ?? null}, ${opts?.source ?? null})\n `;\n return this.get(id)!;\n }\n\n get(sessionId: string): SessionInfo | null {\n this._ensureReady();\n const rows = this.agent.sql`\n SELECT * FROM assistant_sessions WHERE id = ${sessionId}\n ` as unknown as SessionInfo[];\n return rows[0] ?? null;\n }\n\n list(): SessionInfo[] {\n this._ensureReady();\n return this.agent.sql`\n SELECT * FROM assistant_sessions ORDER BY updated_at DESC\n ` as unknown as SessionInfo[];\n }\n\n delete(sessionId: string): void {\n this.getSession(sessionId).clearMessages();\n this.agent.sql`DELETE FROM assistant_sessions WHERE id = ${sessionId}`;\n this._sessions.delete(sessionId);\n }\n\n rename(sessionId: string, name: string): void {\n this._ensureReady();\n this.agent.sql`\n UPDATE assistant_sessions SET name = ${name}, updated_at = CURRENT_TIMESTAMP\n WHERE id = ${sessionId}\n `;\n }\n\n // ── Message convenience methods ───────────────────────────────\n\n async append(\n sessionId: string,\n message: UIMessage,\n parentId?: string\n ): Promise<string> {\n await this.getSession(sessionId).appendMessage(message, parentId);\n this._touch(sessionId);\n return message.id;\n }\n\n async upsert(\n sessionId: string,\n message: UIMessage,\n parentId?: string\n ): Promise<string> {\n const session = this.getSession(sessionId);\n const existing = session.getMessage(message.id);\n if (existing) {\n session.updateMessage(message);\n } else {\n await session.appendMessage(message, parentId);\n }\n this._touch(sessionId);\n return message.id;\n }\n\n async appendAll(\n sessionId: string,\n messages: UIMessage[],\n parentId?: string\n ): Promise<string | null> {\n const session = this.getSession(sessionId);\n let lastParent = parentId ?? null;\n for (const msg of messages) {\n await session.appendMessage(msg, lastParent);\n lastParent = msg.id;\n }\n this._touch(sessionId);\n return lastParent;\n }\n\n getHistory(sessionId: string, leafId?: string): UIMessage[] {\n return this.getSession(sessionId).getHistory(leafId);\n }\n\n getMessageCount(sessionId: string): number {\n return this.getSession(sessionId).getPathLength();\n }\n\n clearMessages(sessionId: string): void {\n this.getSession(sessionId).clearMessages();\n this._touch(sessionId);\n }\n\n deleteMessages(sessionId: string, messageIds: string[]): void {\n this.getSession(sessionId).deleteMessages(messageIds);\n this._touch(sessionId);\n }\n\n // ── Branching ──────────────────────────────────────────────────\n\n getBranches(sessionId: string, messageId: string): UIMessage[] {\n return this.getSession(sessionId).getBranches(messageId);\n }\n\n /**\n * Fork a session at a specific message, creating a new session\n * with the history up to that point copied over.\n */\n async fork(\n sessionId: string,\n atMessageId: string,\n newName: string\n ): Promise<SessionInfo> {\n const info = this.create(newName, { parentSessionId: sessionId });\n const history = this.getSession(sessionId).getHistory(atMessageId);\n const newSession = this.getSession(info.id);\n\n let parentId: string | null = null;\n for (const msg of history) {\n const newId = crypto.randomUUID();\n const copy: UIMessage = { ...msg, id: newId };\n await newSession.appendMessage(copy, parentId);\n parentId = newId;\n }\n\n this._touch(info.id);\n return info;\n }\n\n // ── Compaction ────────────────────────────────────────────────\n\n needsCompaction(sessionId: string): boolean {\n return (\n this.getSession(sessionId).getPathLength() > this._maxContextMessages\n );\n }\n\n addCompaction(\n sessionId: string,\n summary: string,\n fromId: string,\n toId: string\n ): StoredCompaction {\n return this.getSession(sessionId).addCompaction(summary, fromId, toId);\n }\n\n getCompactions(sessionId: string): StoredCompaction[] {\n return this.getSession(sessionId).getCompactions();\n }\n\n async compactAndSplit(\n sessionId: string,\n summary: string,\n newName?: string\n ): Promise<SessionInfo> {\n const old = this.get(sessionId);\n this.agent.sql`\n UPDATE assistant_sessions SET end_reason = 'compaction', updated_at = CURRENT_TIMESTAMP\n WHERE id = ${sessionId}\n `;\n\n const info = this.create(newName ?? old?.name ?? \"Compacted\", {\n parentSessionId: sessionId,\n model: old?.model ?? undefined,\n source: old?.source ?? undefined\n });\n\n await this.append(info.id, {\n id: crypto.randomUUID(),\n role: \"assistant\",\n parts: [\n { type: \"text\", text: `[Context from previous session]\\n\\n${summary}` }\n ]\n });\n\n return info;\n }\n\n // ── Usage tracking ────────────────────────────────────────────\n\n addUsage(\n sessionId: string,\n inputTokens: number,\n outputTokens: number,\n cost: number\n ): void {\n this._ensureReady();\n this.agent.sql`\n UPDATE assistant_sessions SET\n input_tokens = input_tokens + ${inputTokens},\n output_tokens = output_tokens + ${outputTokens},\n estimated_cost = estimated_cost + ${cost},\n updated_at = CURRENT_TIMESTAMP\n WHERE id = ${sessionId}\n `;\n }\n\n // ── Search ────────────────────────────────────────────────────\n\n search(query: string, options?: { limit?: number }) {\n this._ensureReady();\n const limit = options?.limit ?? 20;\n // Quote each word individually to prevent FTS5 syntax injection\n // while preserving implicit AND between terms\n const sanitized = query\n .split(/\\s+/)\n .filter(Boolean)\n .map((w) => `\"${w.replace(/\"/g, '\"\"')}\"`)\n .join(\" \");\n if (!sanitized) return [];\n try {\n return this.agent.sql<{ id: string; role: string; content: string }>`\n SELECT id, role, content FROM assistant_fts\n WHERE assistant_fts MATCH ${sanitized}\n ORDER BY rank LIMIT ${limit}\n `.map((r) => ({\n id: r.id,\n role: r.role,\n content: r.content,\n createdAt: \"\"\n }));\n } catch {\n return [];\n }\n }\n\n // ── Tools ─────────────────────────────────────────────────────\n\n tools(): ToolSet {\n return {\n session_search: {\n description:\n \"Search past conversations for relevant context. Searches across all sessions.\",\n inputSchema: jsonSchema({\n type: \"object\" as const,\n properties: {\n query: { type: \"string\" as const, description: \"Search query\" }\n },\n required: [\"query\"]\n }),\n execute: async ({ query }: { query: string }) => {\n try {\n const results = this.search(query, { limit: 10 });\n if (results.length === 0) return \"No results found.\";\n return results\n .map((r) => `[${r.role}] ${r.content}`)\n .join(\"\\n---\\n\");\n } catch (err) {\n return `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n }\n };\n }\n\n // ── Internal ──────────────────────────────────────────────────\n\n private _touch(sessionId: string): void {\n this.agent.sql`\n UPDATE assistant_sessions SET updated_at = CURRENT_TIMESTAMP\n WHERE id = ${sessionId}\n `;\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { a as alignBoundaryForward, c as createCompactFunction, d as sanitizeToolPairs, i as alignBoundaryBackward, l as findTailCutByTokens, n as CompactOptions, o as buildSummaryPrompt, r as CompactResult, s as computeSummaryBudget, t as COMPACTION_PREFIX, u as isCompactionMessage } from "../../../compaction-helpers-DkJreaDR.js";
1
+ import { a as alignBoundaryForward, c as createCompactFunction, d as sanitizeToolPairs, i as alignBoundaryBackward, l as findTailCutByTokens, n as CompactOptions, o as buildSummaryPrompt, r as CompactResult, s as computeSummaryBudget, t as COMPACTION_PREFIX, u as isCompactionMessage } from "../../../compaction-helpers-CHNQeyRm.js";
2
2
  import { UIMessage } from "ai";
3
3
 
4
4
  //#region src/experimental/memory/utils/tokens.d.ts
@@ -1,4 +1,4 @@
1
- import { a as computeSummaryBudget, c as isCompactionMessage, d as TOKENS_PER_MESSAGE, f as WORDS_TOKEN_MULTIPLIER, i as buildSummaryPrompt, l as sanitizeToolPairs, m as estimateStringTokens, n as alignBoundaryBackward, o as createCompactFunction, p as estimateMessageTokens, r as alignBoundaryForward, s as findTailCutByTokens, t as COMPACTION_PREFIX, u as CHARS_PER_TOKEN } from "../../../compaction-helpers-BFTBIzpK.js";
1
+ import { a as computeSummaryBudget, c as isCompactionMessage, d as TOKENS_PER_MESSAGE, f as WORDS_TOKEN_MULTIPLIER, i as buildSummaryPrompt, l as sanitizeToolPairs, m as estimateStringTokens, n as alignBoundaryBackward, o as createCompactFunction, p as estimateMessageTokens, r as alignBoundaryForward, s as findTailCutByTokens, t as COMPACTION_PREFIX, u as CHARS_PER_TOKEN } from "../../../compaction-helpers-BPE1_ziA.js";
2
2
  //#region src/experimental/memory/utils/compaction.ts
3
3
  /**
4
4
  * Truncate tool outputs and long text in older messages.