@deepagents/context 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.
package/dist/index.d.ts CHANGED
@@ -261,6 +261,38 @@ export declare class ContextEngine {
261
261
  * ```
262
262
  */
263
263
  switchBranch(name: string): Promise<void>;
264
+ /**
265
+ * Create a parallel branch from the current position ("by the way").
266
+ *
267
+ * Use this when you want to fork the conversation without leaving
268
+ * the current branch. Common use case: user wants to ask another
269
+ * question while waiting for the model to respond.
270
+ *
271
+ * Unlike rewind(), this method:
272
+ * - Uses the current HEAD (no messageId needed)
273
+ * - Does NOT switch to the new branch
274
+ * - Keeps pending messages intact
275
+ *
276
+ * @returns The new branch info (does not switch to it)
277
+ * @throws Error if no messages exist in the conversation
278
+ *
279
+ * @example
280
+ * ```ts
281
+ * // User asked a question, model is generating...
282
+ * context.set(user('What is the weather?'));
283
+ * await context.save();
284
+ *
285
+ * // User wants to ask something else without waiting
286
+ * const newBranch = await context.btw();
287
+ * // newBranch = { name: 'main-v2', ... }
288
+ *
289
+ * // Later, switch to the new branch and add the question
290
+ * await context.switchBranch(newBranch.name);
291
+ * context.set(user('Also, what time is it?'));
292
+ * await context.save();
293
+ * ```
294
+ */
295
+ btw(): Promise<BranchInfo>;
264
296
  /**
265
297
  * Update metadata for the current chat.
266
298
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,IAAI,CAAC;AAEhD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EACL,KAAK,cAAc,EAGpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAEL,KAAK,UAAU,EAGf,KAAK,cAAc,EACnB,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,WAAW,EAEjB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EACL,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,KAAK,EAAE,YAAY,CAAC;IACpB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,QAAQ,EAAE,cAAc,CAAC;IACzB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,SAAS,EAAE;QACT,gDAAgD;QAChD,OAAO,EAAE,eAAe,EAAE,CAAC;QAC3B,8CAA8C;QAC9C,OAAO,EAAE,eAAe,EAAE,CAAC;QAC3B,wCAAwC;QACxC,SAAS,EAAE,WAAW,EAAE,CAAC;KAC1B,CAAC;IACF,uDAAuD;IACvD,KAAK,EAAE,SAAS,CAAC;IACjB,0BAA0B;IAC1B,IAAI,EAAE;QACJ,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,GACf,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,sCAAsC,CAAC;AAE9C;;;;;;;;GAQG;AACH,qBAAa,aAAa;;gBAYZ,OAAO,EAAE,oBAAoB;IA0FzC;;OAEG;IACH,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;OAEG;IACH,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;;OAGG;IACH,IAAW,IAAI,IAAI,QAAQ,GAAG,IAAI,CAWjC;IAED;;;;;OAKG;IACI,GAAG,CAAC,GAAG,SAAS,EAAE,eAAe,EAAE;IAW1C;;;OAGG;IACI,MAAM,CAAC,QAAQ,EAAE,eAAe;IAIvC;;;;;;;;;;;;;;;;OAgBG;IACU,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IA0BrE;;;;;;;;;;;;;OAaG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkClC;;;;;;;;;;;OAWG;IACU,QAAQ,CACnB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QACP,QAAQ,CAAC,EAAE,eAAe,CAAC;KACvB,GACL,OAAO,CAAC,cAAc,CAAC;IA+E1B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACU,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAe3D;;;;;;;;;;;;;;;;;;OAkBG;IACU,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAyB9D;;;;;;;;;;;;;;;OAeG;IACU,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAcvD;;;;;;;;;;;;;;OAcG;IACU,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACU,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;IAUvC;;;;;;;;;;;;OAYG;IACU,UAAU,CACrB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,UAAU,CAAC,CAAC,GACrD,OAAO,CAAC,IAAI,CAAC;IAmBhB;;;;;;;OAOG;IACI,WAAW,IAAI,IAAI;IAI1B;;;;;;;;;;;;;;;;;;OAkBG;IACU,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAuCtE;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAKlD;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,GAAG,QAAQ,EAAE,eAAe,EAAE,GAC7B,eAAe,CAKjB;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAKrD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,eAAe,CAwBjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,GAAG,eAAe,CAgB7D;AACD,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,eAAe,CAwBpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,cAAc,GACvB,eAAe,CAOjB"}
package/dist/index.js CHANGED
@@ -1410,6 +1410,41 @@ var ContextEngine = class {
1410
1410
  }
1411
1411
  this.#initialized = true;
1412
1412
  }
1413
+ /**
1414
+ * Create a new branch from a specific message.
1415
+ * Shared logic between rewind() and btw().
1416
+ */
1417
+ async #createBranchFrom(messageId, switchTo) {
1418
+ const branches = await this.#store.listBranches(this.#chatId);
1419
+ const samePrefix = branches.filter(
1420
+ (b) => b.name === this.#branchName || b.name.startsWith(`${this.#branchName}-v`)
1421
+ );
1422
+ const newBranchName = `${this.#branchName}-v${samePrefix.length + 1}`;
1423
+ const newBranch = {
1424
+ id: crypto.randomUUID(),
1425
+ chatId: this.#chatId,
1426
+ name: newBranchName,
1427
+ headMessageId: messageId,
1428
+ isActive: false,
1429
+ createdAt: Date.now()
1430
+ };
1431
+ await this.#store.createBranch(newBranch);
1432
+ if (switchTo) {
1433
+ await this.#store.setActiveBranch(this.#chatId, newBranch.id);
1434
+ this.#branch = { ...newBranch, isActive: true };
1435
+ this.#branchName = newBranchName;
1436
+ this.#pendingMessages = [];
1437
+ }
1438
+ const chain = await this.#store.getMessageChain(messageId);
1439
+ return {
1440
+ id: newBranch.id,
1441
+ name: newBranch.name,
1442
+ headMessageId: newBranch.headMessageId,
1443
+ isActive: switchTo,
1444
+ messageCount: chain.length,
1445
+ createdAt: newBranch.createdAt
1446
+ };
1447
+ }
1413
1448
  /**
1414
1449
  * Get the current chat ID.
1415
1450
  */
@@ -1644,30 +1679,7 @@ var ContextEngine = class {
1644
1679
  if (message2.chatId !== this.#chatId) {
1645
1680
  throw new Error(`Message "${messageId}" belongs to a different chat`);
1646
1681
  }
1647
- const branches = await this.#store.listBranches(this.#chatId);
1648
- const newBranchName = `${this.#branchName}-v${branches.length + 1}`;
1649
- const newBranch = {
1650
- id: crypto.randomUUID(),
1651
- chatId: this.#chatId,
1652
- name: newBranchName,
1653
- headMessageId: messageId,
1654
- isActive: false,
1655
- createdAt: Date.now()
1656
- };
1657
- await this.#store.createBranch(newBranch);
1658
- await this.#store.setActiveBranch(this.#chatId, newBranch.id);
1659
- this.#branch = { ...newBranch, isActive: true };
1660
- this.#branchName = newBranchName;
1661
- this.#pendingMessages = [];
1662
- const chain = await this.#store.getMessageChain(messageId);
1663
- return {
1664
- id: newBranch.id,
1665
- name: newBranch.name,
1666
- headMessageId: newBranch.headMessageId,
1667
- isActive: true,
1668
- messageCount: chain.length,
1669
- createdAt: newBranch.createdAt
1670
- };
1682
+ return this.#createBranchFrom(messageId, true);
1671
1683
  }
1672
1684
  /**
1673
1685
  * Create a checkpoint at the current position.
@@ -1760,6 +1772,44 @@ var ContextEngine = class {
1760
1772
  this.#branchName = name;
1761
1773
  this.#pendingMessages = [];
1762
1774
  }
1775
+ /**
1776
+ * Create a parallel branch from the current position ("by the way").
1777
+ *
1778
+ * Use this when you want to fork the conversation without leaving
1779
+ * the current branch. Common use case: user wants to ask another
1780
+ * question while waiting for the model to respond.
1781
+ *
1782
+ * Unlike rewind(), this method:
1783
+ * - Uses the current HEAD (no messageId needed)
1784
+ * - Does NOT switch to the new branch
1785
+ * - Keeps pending messages intact
1786
+ *
1787
+ * @returns The new branch info (does not switch to it)
1788
+ * @throws Error if no messages exist in the conversation
1789
+ *
1790
+ * @example
1791
+ * ```ts
1792
+ * // User asked a question, model is generating...
1793
+ * context.set(user('What is the weather?'));
1794
+ * await context.save();
1795
+ *
1796
+ * // User wants to ask something else without waiting
1797
+ * const newBranch = await context.btw();
1798
+ * // newBranch = { name: 'main-v2', ... }
1799
+ *
1800
+ * // Later, switch to the new branch and add the question
1801
+ * await context.switchBranch(newBranch.name);
1802
+ * context.set(user('Also, what time is it?'));
1803
+ * await context.save();
1804
+ * ```
1805
+ */
1806
+ async btw() {
1807
+ await this.#ensureInitialized();
1808
+ if (!this.#branch?.headMessageId) {
1809
+ throw new Error("Cannot create btw branch: no messages in conversation");
1810
+ }
1811
+ return this.#createBranchFrom(this.#branch.headMessageId, false);
1812
+ }
1763
1813
  /**
1764
1814
  * Update metadata for the current chat.
1765
1815
  *
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/lib/context.ts", "../src/lib/estimate.ts", "../src/lib/renderers/abstract.renderer.ts", "../src/lib/store/store.ts", "../src/lib/store/sqlite.store.ts", "../src/lib/store/memory.store.ts", "../src/lib/visualize.ts"],
4
- "sourcesContent": ["import { type UIMessage, generateId } from 'ai';\n\nimport type { ContextFragment } from './lib/context.ts';\nimport { isMessageFragment } from './lib/context.ts';\nimport {\n type EstimateResult,\n type FragmentEstimate,\n getModelsRegistry,\n} from './lib/estimate.ts';\nimport type { Models } from './lib/models.generated.ts';\nimport {\n type ContextRenderer,\n XmlRenderer,\n} from './lib/renderers/abstract.renderer.ts';\nimport {\n type BranchData,\n type BranchInfo,\n type ChatData,\n type CheckpointData,\n type CheckpointInfo,\n ContextStore,\n type GraphData,\n type MessageData,\n type StoredChatData,\n} from './lib/store/store.ts';\n\nexport type { FragmentCodec } from './lib/codec.ts';\nexport { isMessageFragment } from './lib/context.ts';\nexport type { ContextFragment, FragmentType } from './lib/context.ts';\nexport { InMemoryContextStore } from './lib/store/memory.store.ts';\nexport { SqliteContextStore } from './lib/store/sqlite.store.ts';\nexport {\n ContextStore,\n type BranchData,\n type BranchInfo,\n type ChatData,\n type ChatInfo,\n type CheckpointData,\n type CheckpointInfo,\n type GraphBranch,\n type GraphCheckpoint,\n type GraphData,\n type GraphNode,\n type MessageData,\n type MessageInfo,\n type SearchOptions,\n type SearchResult,\n type StoredChatData,\n} from './lib/store/store.ts';\nexport { visualizeGraph } from './lib/visualize.ts';\n\n/**\n * Result of resolving context - ready for AI SDK consumption.\n */\nexport interface ResolveResult {\n /** Rendered non-message fragments for system prompt */\n systemPrompt: string;\n /** Message fragments decoded to AI SDK format */\n messages: unknown[];\n}\n\n/**\n * Options for resolve().\n */\nexport interface ResolveOptions {\n /** Renderer to use for system prompt (defaults to XmlRenderer) */\n renderer: ContextRenderer;\n}\n\n/**\n * Options for creating a ContextEngine.\n */\nexport interface ContextEngineOptions {\n /** Store for persisting fragments (required) */\n store: ContextStore;\n /** Unique identifier for this chat (required) */\n chatId: string;\n /** Branch name (defaults to 'main') */\n branch?: string;\n}\n\n/**\n * Options for creating message fragments.\n */\nexport interface MessageOptions {\n /** Custom ID for the fragment. If not provided, auto-generates UUID. */\n id?: string;\n}\n\n/**\n * Metadata about a chat.\n */\nexport interface ChatMeta {\n /** Unique chat identifier */\n id: string;\n /** When the chat was created */\n createdAt: number;\n /** When the chat was last updated */\n updatedAt: number;\n /** Optional user-provided title */\n title?: string;\n /** Optional custom metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Options for context inspection.\n */\nexport interface InspectOptions {\n /** Model ID for cost estimation (required) */\n modelId: Models;\n /** Renderer for estimation (required) */\n renderer: ContextRenderer;\n}\n\n/**\n * Result of inspecting context state.\n * Provides a comprehensive JSON-serializable snapshot for debugging.\n */\nexport interface InspectResult {\n /** Token usage and cost estimation */\n estimate: EstimateResult;\n /** Rendered output using the provided renderer */\n rendered: string;\n /** Fragment structure breakdown */\n fragments: {\n /** Non-message fragments (role, hints, etc.) */\n context: ContextFragment[];\n /** Pending messages not yet saved to store */\n pending: ContextFragment[];\n /** Persisted messages from the store */\n persisted: MessageData[];\n };\n /** Conversation graph with branches and checkpoints */\n graph: GraphData;\n /** Inspection metadata */\n meta: {\n chatId: string;\n branch: string;\n timestamp: number;\n };\n}\n\nexport {\n ModelsRegistry,\n defaultTokenizer,\n estimate,\n getModelsRegistry,\n type EstimateResult,\n type FragmentEstimate,\n type ModelCost,\n type ModelInfo,\n type Tokenizer,\n} from './lib/estimate.ts';\nexport type { KnownModels, Models } from './lib/models.generated.ts';\nexport {\n MarkdownRenderer,\n TomlRenderer,\n ToonRenderer,\n XmlRenderer,\n type ContextRenderer,\n type RendererOptions,\n} from './lib/renderers/abstract.renderer.ts';\n\n/**\n * Context engine for managing AI conversation context with graph-based storage.\n *\n * The engine uses a DAG (Directed Acyclic Graph) model for messages:\n * - Messages are immutable nodes with parentId forming the graph\n * - Branches are pointers to head (tip) messages\n * - Checkpoints are pointers to specific messages\n * - History is preserved through branching (rewind creates new branch)\n */\nexport class ContextEngine {\n /** Non-message fragments (role, hints, etc.) - not persisted in graph */\n #fragments: ContextFragment[] = [];\n /** Pending message fragments to be added to graph */\n #pendingMessages: ContextFragment[] = [];\n #store: ContextStore;\n #chatId: string;\n #branchName: string;\n #branch: BranchData | null = null;\n #chatData: StoredChatData | null = null;\n #initialized = false;\n\n constructor(options: ContextEngineOptions) {\n if (!options.chatId) {\n throw new Error('chatId is required');\n }\n this.#store = options.store;\n this.#chatId = options.chatId;\n this.#branchName = options.branch ?? 'main';\n }\n\n /**\n * Initialize the chat and branch if they don't exist.\n */\n async #ensureInitialized(): Promise<void> {\n if (this.#initialized) {\n return;\n }\n\n this.#chatData = await this.#store.upsertChat({ id: this.#chatId });\n\n const existingBranch = await this.#store.getBranch(\n this.#chatId,\n this.#branchName,\n );\n if (existingBranch) {\n this.#branch = existingBranch;\n } else {\n this.#branch = {\n id: crypto.randomUUID(),\n chatId: this.#chatId,\n name: this.#branchName,\n headMessageId: null,\n isActive: true,\n createdAt: Date.now(),\n };\n await this.#store.createBranch(this.#branch);\n }\n\n this.#initialized = true;\n }\n\n /**\n * Get the current chat ID.\n */\n public get chatId(): string {\n return this.#chatId;\n }\n\n /**\n * Get the current branch name.\n */\n public get branch(): string {\n return this.#branchName;\n }\n\n /**\n * Get metadata for the current chat.\n * Returns null if the chat hasn't been initialized yet.\n */\n public get chat(): ChatMeta | null {\n if (!this.#chatData) {\n return null;\n }\n return {\n id: this.#chatData.id,\n createdAt: this.#chatData.createdAt,\n updatedAt: this.#chatData.updatedAt,\n title: this.#chatData.title,\n metadata: this.#chatData.metadata,\n };\n }\n\n /**\n * Add fragments to the context.\n *\n * - Message fragments (user/assistant) are queued for persistence\n * - Non-message fragments (role/hint) are kept in memory for system prompt\n */\n public set(...fragments: ContextFragment[]) {\n for (const fragment of fragments) {\n if (isMessageFragment(fragment)) {\n this.#pendingMessages.push(fragment);\n } else {\n this.#fragments.push(fragment);\n }\n }\n return this;\n }\n\n /**\n * Render all fragments using the provided renderer.\n * @internal Use resolve() instead for public API.\n */\n public render(renderer: ContextRenderer) {\n return renderer.render(this.#fragments);\n }\n\n /**\n * Resolve context into AI SDK-ready format.\n *\n * - Initializes chat and branch if needed\n * - Loads message history from the graph (walking parent chain)\n * - Separates context fragments for system prompt\n * - Combines with pending messages\n *\n * @example\n * ```ts\n * const context = new ContextEngine({ store, chatId: 'chat-1' })\n * .set(role('You are helpful'), user('Hello'));\n *\n * const { systemPrompt, messages } = await context.resolve();\n * await generateText({ system: systemPrompt, messages });\n * ```\n */\n public async resolve(options: ResolveOptions): Promise<ResolveResult> {\n await this.#ensureInitialized();\n\n const systemPrompt = options.renderer.render(this.#fragments);\n\n // Get persisted messages from graph\n const messages: unknown[] = [];\n if (this.#branch?.headMessageId) {\n const chain = await this.#store.getMessageChain(\n this.#branch.headMessageId,\n );\n\n for (const msg of chain) {\n messages.push(message(msg.data as never).codec?.decode());\n }\n }\n\n // Add pending messages (not yet saved)\n for (const fragment of this.#pendingMessages) {\n const decoded = fragment.codec!.decode();\n messages.push(decoded);\n }\n\n return { systemPrompt, messages };\n }\n\n /**\n * Save pending messages to the graph.\n *\n * Each message is added as a node with parentId pointing to the previous message.\n * The branch head is updated to point to the last message.\n *\n * @example\n * ```ts\n * context.set(user('Hello'));\n * // AI responds...\n * context.set(assistant('Hi there!'));\n * await context.save(); // Persist to graph\n * ```\n */\n public async save(): Promise<void> {\n await this.#ensureInitialized();\n\n if (this.#pendingMessages.length === 0) {\n return;\n }\n\n let parentId = this.#branch!.headMessageId;\n const now = Date.now();\n\n // Add each pending message to the graph\n for (const fragment of this.#pendingMessages) {\n const messageData: MessageData = {\n id: fragment.id ?? crypto.randomUUID(),\n chatId: this.#chatId,\n parentId,\n name: fragment.name,\n type: fragment.type,\n data: fragment.codec!.encode(),\n createdAt: now,\n };\n\n await this.#store.addMessage(messageData);\n parentId = messageData.id;\n }\n\n // Update branch head to last message\n await this.#store.updateBranchHead(this.#branch!.id, parentId);\n this.#branch!.headMessageId = parentId;\n\n // Clear pending messages\n this.#pendingMessages = [];\n }\n\n /**\n * Estimate token count and cost for the full context.\n *\n * Includes:\n * - System prompt fragments (role, hints, etc.)\n * - Persisted chat messages (from store)\n * - Pending messages (not yet saved)\n *\n * @param modelId - Model ID (e.g., \"openai:gpt-4o\", \"anthropic:claude-3-5-sonnet\")\n * @param options - Optional settings\n * @returns Estimate result with token counts, costs, and per-fragment breakdown\n */\n public async estimate(\n modelId: Models,\n options: {\n renderer?: ContextRenderer;\n } = {},\n ): Promise<EstimateResult> {\n await this.#ensureInitialized();\n\n const renderer = options.renderer ?? new XmlRenderer();\n const registry = getModelsRegistry();\n await registry.load();\n\n const model = registry.get(modelId);\n if (!model) {\n throw new Error(\n `Model \"${modelId}\" not found. Call load() first or check model ID.`,\n );\n }\n\n const tokenizer = registry.getTokenizer(modelId);\n const fragmentEstimates: FragmentEstimate[] = [];\n\n // 1. Estimate context fragments (system prompt)\n for (const fragment of this.#fragments) {\n const rendered = renderer.render([fragment]);\n const tokens = tokenizer.count(rendered);\n const cost = (tokens / 1_000_000) * model.cost.input;\n fragmentEstimates.push({\n id: fragment.id,\n name: fragment.name,\n tokens,\n cost,\n });\n }\n\n // 2. Estimate persisted messages from store\n if (this.#branch?.headMessageId) {\n const chain = await this.#store.getMessageChain(\n this.#branch.headMessageId,\n );\n for (const msg of chain) {\n const content = String(msg.data);\n const tokens = tokenizer.count(content);\n const cost = (tokens / 1_000_000) * model.cost.input;\n fragmentEstimates.push({\n name: msg.name,\n id: msg.id,\n tokens,\n cost,\n });\n }\n }\n\n // 3. Estimate pending messages (not yet saved)\n for (const fragment of this.#pendingMessages) {\n const content = String(fragment.data);\n const tokens = tokenizer.count(content);\n const cost = (tokens / 1_000_000) * model.cost.input;\n fragmentEstimates.push({\n name: fragment.name,\n id: fragment.id,\n tokens,\n cost,\n });\n }\n\n // Calculate totals\n const totalTokens = fragmentEstimates.reduce((sum, f) => sum + f.tokens, 0);\n const totalCost = fragmentEstimates.reduce((sum, f) => sum + f.cost, 0);\n\n return {\n model: model.id,\n provider: model.provider,\n tokens: totalTokens,\n cost: totalCost,\n limits: {\n context: model.limit.context,\n output: model.limit.output,\n exceedsContext: totalTokens > model.limit.context,\n },\n fragments: fragmentEstimates,\n };\n }\n\n /**\n * Rewind to a specific message by ID.\n *\n * Creates a new branch from that message, preserving the original branch.\n * The new branch becomes active.\n *\n * @param messageId - The message ID to rewind to\n * @returns The new branch info\n *\n * @example\n * ```ts\n * context.set(user('What is 2 + 2?', { id: 'q1' }));\n * context.set(assistant('The answer is 5.', { id: 'wrong' })); // Oops!\n * await context.save();\n *\n * // Rewind to the question, creates new branch\n * const newBranch = await context.rewind('q1');\n *\n * // Now add correct answer on new branch\n * context.set(assistant('The answer is 4.'));\n * await context.save();\n * ```\n */\n public async rewind(messageId: string): Promise<BranchInfo> {\n await this.#ensureInitialized();\n\n // Verify the message exists\n const message = await this.#store.getMessage(messageId);\n if (!message) {\n throw new Error(`Message \"${messageId}\" not found`);\n }\n if (message.chatId !== this.#chatId) {\n throw new Error(`Message \"${messageId}\" belongs to a different chat`);\n }\n\n // Count existing branches to generate name\n const branches = await this.#store.listBranches(this.#chatId);\n const newBranchName = `${this.#branchName}-v${branches.length + 1}`;\n\n // Create new branch pointing to the target message\n const newBranch: BranchData = {\n id: crypto.randomUUID(),\n chatId: this.#chatId,\n name: newBranchName,\n headMessageId: messageId,\n isActive: false,\n createdAt: Date.now(),\n };\n await this.#store.createBranch(newBranch);\n\n // Switch to new branch\n await this.#store.setActiveBranch(this.#chatId, newBranch.id);\n this.#branch = { ...newBranch, isActive: true };\n this.#branchName = newBranchName;\n\n // Clear pending messages (they were for the old branch)\n this.#pendingMessages = [];\n\n // Return branch info\n const chain = await this.#store.getMessageChain(messageId);\n return {\n id: newBranch.id,\n name: newBranch.name,\n headMessageId: newBranch.headMessageId,\n isActive: true,\n messageCount: chain.length,\n createdAt: newBranch.createdAt,\n };\n }\n\n /**\n * Create a checkpoint at the current position.\n *\n * A checkpoint is a named pointer to the current branch head.\n * Use restore() to return to this point later.\n *\n * @param name - Name for the checkpoint\n * @returns The checkpoint info\n *\n * @example\n * ```ts\n * context.set(user('I want to learn a new skill.'));\n * context.set(assistant('Would you like coding or cooking?'));\n * await context.save();\n *\n * // Save checkpoint before user's choice\n * const cp = await context.checkpoint('before-choice');\n * ```\n */\n public async checkpoint(name: string): Promise<CheckpointInfo> {\n await this.#ensureInitialized();\n\n if (!this.#branch?.headMessageId) {\n throw new Error('Cannot create checkpoint: no messages in conversation');\n }\n\n const checkpoint: CheckpointData = {\n id: crypto.randomUUID(),\n chatId: this.#chatId,\n name,\n messageId: this.#branch.headMessageId,\n createdAt: Date.now(),\n };\n\n await this.#store.createCheckpoint(checkpoint);\n\n return {\n id: checkpoint.id,\n name: checkpoint.name,\n messageId: checkpoint.messageId,\n createdAt: checkpoint.createdAt,\n };\n }\n\n /**\n * Restore to a checkpoint by creating a new branch from that point.\n *\n * @param name - Name of the checkpoint to restore\n * @returns The new branch info\n *\n * @example\n * ```ts\n * // User chose cooking, but wants to try coding path\n * await context.restore('before-choice');\n *\n * context.set(user('I want to learn coding.'));\n * context.set(assistant('Python is a great starting language!'));\n * await context.save();\n * ```\n */\n public async restore(name: string): Promise<BranchInfo> {\n await this.#ensureInitialized();\n\n const checkpoint = await this.#store.getCheckpoint(this.#chatId, name);\n if (!checkpoint) {\n throw new Error(\n `Checkpoint \"${name}\" not found in chat \"${this.#chatId}\"`,\n );\n }\n\n // Rewind to the checkpoint's message\n return this.rewind(checkpoint.messageId);\n }\n\n /**\n * Switch to a different branch by name.\n *\n * @param name - Branch name to switch to\n *\n * @example\n * ```ts\n * // List branches (via store)\n * const branches = await store.listBranches(context.chatId);\n * console.log(branches); // [{name: 'main', ...}, {name: 'main-v2', ...}]\n *\n * // Switch to original branch\n * await context.switchBranch('main');\n * ```\n */\n public async switchBranch(name: string): Promise<void> {\n await this.#ensureInitialized();\n\n const branch = await this.#store.getBranch(this.#chatId, name);\n if (!branch) {\n throw new Error(`Branch \"${name}\" not found in chat \"${this.#chatId}\"`);\n }\n\n await this.#store.setActiveBranch(this.#chatId, branch.id);\n this.#branch = { ...branch, isActive: true };\n this.#branchName = name;\n\n // Clear pending messages (they were for the old branch)\n this.#pendingMessages = [];\n }\n\n /**\n * Update metadata for the current chat.\n *\n * @param updates - Partial metadata to merge (title, metadata)\n *\n * @example\n * ```ts\n * await context.updateChat({\n * title: 'Coding Help Session',\n * metadata: { tags: ['python', 'debugging'] }\n * });\n * ```\n */\n public async updateChat(\n updates: Partial<Pick<ChatMeta, 'title' | 'metadata'>>,\n ): Promise<void> {\n await this.#ensureInitialized();\n\n const storeUpdates: Partial<Pick<ChatData, 'title' | 'metadata'>> = {};\n\n if (updates.title !== undefined) {\n storeUpdates.title = updates.title;\n }\n if (updates.metadata !== undefined) {\n // Merge with existing metadata\n storeUpdates.metadata = {\n ...this.#chatData?.metadata,\n ...updates.metadata,\n };\n }\n\n this.#chatData = await this.#store.updateChat(this.#chatId, storeUpdates);\n }\n\n /**\n * Consolidate context fragments (no-op for now).\n *\n * This is a placeholder for future functionality that merges context fragments\n * using specific rules. Currently, it does nothing.\n *\n * @experimental\n */\n public consolidate(): void {\n return void 0;\n }\n\n /**\n * Inspect the full context state for debugging.\n * Returns a comprehensive JSON-serializable object with all context information.\n *\n * @param options - Inspection options (modelId and renderer required)\n * @returns Complete inspection data including estimates, rendered output, fragments, and graph\n *\n * @example\n * ```ts\n * const inspection = await context.inspect({\n * modelId: 'openai:gpt-4o',\n * renderer: new XmlRenderer(),\n * });\n * console.log(JSON.stringify(inspection, null, 2));\n *\n * // Or write to file for analysis\n * await fs.writeFile('context-debug.json', JSON.stringify(inspection, null, 2));\n * ```\n */\n public async inspect(options: InspectOptions): Promise<InspectResult> {\n await this.#ensureInitialized();\n\n const { renderer } = options;\n\n // Get token/cost estimation\n const estimateResult = await this.estimate(options.modelId, { renderer });\n\n // Render using provided renderer\n const rendered = renderer.render(this.#fragments);\n\n // Get persisted messages from store\n const persistedMessages: MessageData[] = [];\n if (this.#branch?.headMessageId) {\n const chain = await this.#store.getMessageChain(\n this.#branch.headMessageId,\n );\n persistedMessages.push(...chain);\n }\n\n // Get conversation graph\n const graph = await this.#store.getGraph(this.#chatId);\n\n return {\n estimate: estimateResult,\n rendered,\n fragments: {\n context: [...this.#fragments],\n pending: [...this.#pendingMessages],\n persisted: persistedMessages,\n },\n graph,\n meta: {\n chatId: this.#chatId,\n branch: this.#branchName,\n timestamp: Date.now(),\n },\n };\n }\n}\n\nexport function hint(text: string): ContextFragment {\n return {\n name: 'hint',\n data: text,\n };\n}\n\nexport function fragment(\n name: string,\n ...children: ContextFragment[]\n): ContextFragment {\n return {\n name,\n data: children,\n };\n}\n\n/**\n * Create a role fragment for system prompt instructions.\n */\nexport function role(content: string): ContextFragment {\n return {\n name: 'role',\n data: content,\n };\n}\n\n/**\n * Create a user message fragment.\n * Message fragments are separated from regular fragments during resolve().\n *\n * @param content - The message content\n * @param options - Optional settings (id)\n *\n * @example\n * ```ts\n * context.set(user('Hello')); // Auto-generated ID\n * context.set(user('Hello', { id: 'msg-1' })); // Custom ID\n * ```\n */\nexport function user(content: string | UIMessage): ContextFragment {\n const message =\n typeof content === 'string'\n ? {\n id: generateId(),\n role: 'user',\n parts: [{ type: 'text', text: content }],\n }\n : content;\n return {\n id: message.id,\n name: 'user',\n data: 'content',\n type: 'message',\n persist: true,\n codec: {\n decode() {\n return message;\n },\n encode() {\n return message;\n },\n },\n };\n}\n\n/**\n * Create an assistant message fragment.\n * Message fragments are separated from regular fragments during resolve().\n *\n * @param message - The message content\n * @param options - Optional settings (id)\n *\n * @example\n * ```ts\n * context.set(assistant('Hi there!')); // Auto-generated ID\n * context.set(assistant('Hi there!', { id: 'resp-1' })); // Custom ID\n * ```\n */\nexport function assistant(message: UIMessage): ContextFragment {\n return {\n id: message.id,\n name: 'assistant',\n data: 'content',\n type: 'message',\n persist: true,\n codec: {\n decode() {\n return message;\n },\n encode() {\n return message;\n },\n },\n };\n}\nexport function message(content: string | UIMessage): ContextFragment {\n const message =\n typeof content === 'string'\n ? {\n id: generateId(),\n role: 'user',\n parts: [{ type: 'text', text: content }],\n }\n : content;\n return {\n id: message.id,\n name: 'message',\n data: 'content',\n type: 'message',\n persist: true,\n codec: {\n decode() {\n return message;\n },\n encode() {\n return message;\n },\n },\n };\n}\n\n/**\n * Create an assistant message fragment from text content.\n * Convenience wrapper that creates a UIMessage internally.\n *\n * @param content - The message text content\n * @param options - Optional settings (id)\n *\n * @example\n * ```ts\n * context.set(assistantText('Hi there!')); // Auto-generated ID\n * context.set(assistantText('Hi there!', { id: 'resp-1' })); // Custom ID\n * ```\n */\nexport function assistantText(\n content: string,\n options?: MessageOptions,\n): ContextFragment {\n const id = options?.id ?? crypto.randomUUID();\n return assistant({\n id,\n role: 'assistant',\n parts: [{ type: 'text', text: content }],\n });\n}\n", "import type { FragmentCodec } from './codec.ts';\n\n/**\n * Fragment type identifier.\n * - 'fragment': Regular context fragment (default)\n * - 'message': Conversation message (user/assistant)\n */\nexport type FragmentType = 'fragment' | 'message';\n\n/**\n * A context fragment containing a name and associated data.\n */\nexport interface ContextFragment {\n /**\n * Unique identifier for this fragment.\n * Auto-generated for user/assistant messages, optional for other fragments.\n */\n id?: string;\n name: string;\n data: FragmentData;\n /**\n * Fragment type for categorization.\n * Messages use 'message' type and are handled separately during resolve().\n */\n type?: FragmentType;\n /**\n * When true, this fragment will be persisted to the store on save().\n */\n persist?: boolean;\n /**\n * Codec for encoding/decoding this fragment.\n * Used by resolve() to convert to AI SDK format.\n */\n codec?: FragmentCodec;\n}\n\n/**\n * Fragment data can be a primitive, array, object, or nested fragment.\n */\nexport type FragmentData =\n | string\n | number\n | boolean\n | ContextFragment\n | FragmentData[]\n | { [key: string]: FragmentData };\n\n/**\n * Type guard to check if data is a ContextFragment.\n */\nexport function isFragment(data: unknown): data is ContextFragment {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'name' in data &&\n 'data' in data &&\n typeof (data as ContextFragment).name === 'string'\n );\n}\n\n/**\n * A plain object with string keys and FragmentData values.\n */\nexport type FragmentObject = Record<string, FragmentData>;\n\n/**\n * Type guard to check if data is a plain object (not array, not fragment, not primitive).\n */\nexport function isFragmentObject(data: unknown): data is FragmentObject {\n return (\n typeof data === 'object' &&\n data !== null &&\n !Array.isArray(data) &&\n !isFragment(data)\n );\n}\n\n/**\n * Type guard to check if a fragment is a message fragment.\n */\nexport function isMessageFragment(fragment: ContextFragment): boolean {\n return fragment.type === 'message';\n}\n", "import { encode } from 'gpt-tokenizer';\n\nimport type { ContextFragment } from './context.ts';\nimport type { Models } from './models.generated.ts';\nimport type { ContextRenderer } from './renderers/abstract.renderer.ts';\n\n/**\n * Cost information for a model (prices per 1M tokens)\n */\nexport interface ModelCost {\n input: number;\n output: number;\n cache_read?: number;\n cache_write?: number;\n reasoning?: number;\n}\n\n/**\n * Model information from models.dev\n */\nexport interface ModelInfo {\n id: string;\n name: string;\n family: string;\n cost: ModelCost;\n limit: {\n context: number;\n output: number;\n };\n provider: string;\n}\n\n/**\n * Estimate for a single fragment\n */\nexport interface FragmentEstimate {\n name: string;\n id?: string;\n tokens: number;\n cost: number;\n}\n\n/**\n * Estimate result returned by the estimate function\n */\nexport interface EstimateResult {\n model: string;\n provider: string;\n tokens: number;\n cost: number;\n limits: {\n context: number;\n output: number;\n exceedsContext: boolean;\n };\n fragments: FragmentEstimate[];\n}\n\n/**\n * Tokenizer interface for counting tokens\n */\nexport interface Tokenizer {\n encode(text: string): number[];\n count(text: string): number;\n}\n\n/**\n * Default tokenizer using gpt-tokenizer\n * Works reasonably well for most models (~5-10% variance)\n */\nexport const defaultTokenizer: Tokenizer = {\n encode(text: string): number[] {\n return encode(text);\n },\n count(text: string): number {\n return encode(text).length;\n },\n};\n\ntype ModelsDevResponse = Record<\n string,\n {\n id: string;\n name: string;\n models: Record<\n string,\n {\n id: string;\n name: string;\n family: string;\n cost: ModelCost;\n limit: { context: number; output: number };\n }\n >;\n }\n>;\n\n/**\n * Registry for AI model information from models.dev\n * Caches data and provides lookup by model ID\n */\nexport class ModelsRegistry {\n #cache: Map<string, ModelInfo> = new Map();\n #loaded = false;\n #tokenizers: Map<string, Tokenizer> = new Map();\n #defaultTokenizer: Tokenizer = defaultTokenizer;\n\n /**\n * Load models data from models.dev API\n */\n async load(): Promise<void> {\n if (this.#loaded) return;\n\n const response = await fetch('https://models.dev/api.json');\n if (!response.ok) {\n throw new Error(`Failed to fetch models: ${response.statusText}`);\n }\n\n const data = (await response.json()) as ModelsDevResponse;\n\n for (const [providerId, provider] of Object.entries(data)) {\n for (const [modelId, model] of Object.entries(provider.models)) {\n const info: ModelInfo = {\n id: model.id,\n name: model.name,\n family: model.family,\n cost: model.cost,\n limit: model.limit,\n provider: providerId,\n };\n\n // Store by full ID (provider:model)\n this.#cache.set(`${providerId}:${modelId}`, info);\n }\n }\n\n this.#loaded = true;\n }\n\n /**\n * Get model info by ID\n * @param modelId - Model ID (e.g., \"openai:gpt-4o\")\n */\n get(modelId: string): ModelInfo | undefined {\n return this.#cache.get(modelId);\n }\n\n /**\n * Check if a model exists in the registry\n */\n has(modelId: string): boolean {\n return this.#cache.has(modelId);\n }\n\n /**\n * List all available model IDs\n */\n list(): string[] {\n return [...this.#cache.keys()];\n }\n\n /**\n * Register a custom tokenizer for specific model families\n * @param family - Model family name (e.g., \"llama\", \"claude\")\n * @param tokenizer - Tokenizer implementation\n */\n registerTokenizer(family: string, tokenizer: Tokenizer): void {\n this.#tokenizers.set(family, tokenizer);\n }\n\n /**\n * Set the default tokenizer used when no family-specific tokenizer is registered\n */\n setDefaultTokenizer(tokenizer: Tokenizer): void {\n this.#defaultTokenizer = tokenizer;\n }\n\n /**\n * Get the appropriate tokenizer for a model\n */\n getTokenizer(modelId: string): Tokenizer {\n const model = this.get(modelId);\n if (model) {\n const familyTokenizer = this.#tokenizers.get(model.family);\n if (familyTokenizer) {\n return familyTokenizer;\n }\n }\n return this.#defaultTokenizer;\n }\n\n /**\n * Estimate token count and cost for given text and model\n * @param modelId - Model ID to use for pricing (e.g., \"openai:gpt-4o\")\n * @param input - Input text (prompt)\n */\n estimate(modelId: Models, input: string): EstimateResult {\n const model = this.get(modelId);\n if (!model) {\n throw new Error(\n `Model \"${modelId}\" not found. Call load() first or check model ID.`,\n );\n }\n\n const tokenizer = this.getTokenizer(modelId);\n const tokens = tokenizer.count(input);\n const cost = (tokens / 1_000_000) * model.cost.input;\n\n return {\n model: model.id,\n provider: model.provider,\n tokens,\n cost,\n limits: {\n context: model.limit.context,\n output: model.limit.output,\n exceedsContext: tokens > model.limit.context,\n },\n fragments: [],\n };\n }\n}\n\n// Singleton instance for convenience\nlet _registry: ModelsRegistry | null = null;\n\n/**\n * Get the shared ModelsRegistry instance\n */\nexport function getModelsRegistry(): ModelsRegistry {\n if (!_registry) {\n _registry = new ModelsRegistry();\n }\n return _registry;\n}\n\n/**\n * Convenience function to estimate cost for a model\n * Automatically loads the registry if not already loaded\n *\n * @param modelId - Model ID (e.g., \"openai:gpt-4o\", \"anthropic:claude-3-5-sonnet\")\n * @param renderer - Renderer to use for converting fragments to text\n * @param fragments - Context fragments to estimate\n */\nexport async function estimate(\n modelId: Models,\n renderer: ContextRenderer,\n ...fragments: ContextFragment[]\n): Promise<EstimateResult> {\n const registry = getModelsRegistry();\n await registry.load();\n\n // Calculate total (all fragments rendered together)\n const input = renderer.render(fragments);\n const model = registry.get(modelId);\n if (!model) {\n throw new Error(\n `Model \"${modelId}\" not found. Call load() first or check model ID.`,\n );\n }\n\n const tokenizer = registry.getTokenizer(modelId);\n const totalTokens = tokenizer.count(input);\n const totalCost = (totalTokens / 1_000_000) * model.cost.input;\n\n // Calculate per-fragment estimates\n const fragmentEstimates: FragmentEstimate[] = fragments.map((fragment) => {\n const rendered = renderer.render([fragment]);\n const tokens = tokenizer.count(rendered);\n const cost = (tokens / 1_000_000) * model.cost.input;\n return {\n id: fragment.id,\n name: fragment.name,\n tokens,\n cost,\n };\n });\n\n return {\n model: model.id,\n provider: model.provider,\n tokens: totalTokens,\n cost: totalCost,\n limits: {\n context: model.limit.context,\n output: model.limit.output,\n exceedsContext: totalTokens > model.limit.context,\n },\n fragments: fragmentEstimates,\n };\n}\n", "import pluralize from 'pluralize';\nimport { titlecase } from 'stringcase';\n\nimport {\n type ContextFragment,\n type FragmentData,\n type FragmentObject,\n isFragment,\n isFragmentObject,\n} from '../context.ts';\n\n/**\n * Render context passed through the template method.\n */\nexport interface RenderContext {\n depth: number;\n path: string[];\n}\n\n/**\n * Options for renderers.\n */\nexport interface RendererOptions {\n /**\n * When true, fragments with the same name are grouped under a pluralized parent tag.\n * e.g., multiple <hint> become <hints><hint>...</hint><hint>...</hint></hints>\n */\n groupFragments?: boolean;\n}\n\n/**\n * Base renderer implementing the Template Method pattern.\n * Subclasses implement the specific formatting hooks.\n */\nexport abstract class ContextRenderer {\n protected options: RendererOptions;\n\n constructor(options: RendererOptions = {}) {\n this.options = options;\n }\n\n abstract render(fragments: ContextFragment[]): string;\n\n /**\n * Check if data is a primitive (string, number, boolean).\n */\n protected isPrimitive(data: FragmentData): data is string | number | boolean {\n return (\n typeof data === 'string' ||\n typeof data === 'number' ||\n typeof data === 'boolean'\n );\n }\n\n /**\n * Group fragments by name for groupFragments option.\n */\n protected groupByName(\n fragments: ContextFragment[],\n ): Map<string, ContextFragment[]> {\n const groups = new Map<string, ContextFragment[]>();\n for (const fragment of fragments) {\n const existing = groups.get(fragment.name) ?? [];\n existing.push(fragment);\n groups.set(fragment.name, existing);\n }\n return groups;\n }\n\n /**\n * Template method - dispatches value to appropriate handler.\n */\n protected renderValue(\n key: string,\n value: unknown,\n ctx: RenderContext,\n ): string {\n if (value == null) {\n return '';\n }\n if (isFragment(value)) {\n return this.renderFragment(value, ctx);\n }\n if (Array.isArray(value)) {\n return this.renderArray(key, value, ctx);\n }\n if (isFragmentObject(value)) {\n return this.renderObject(key, value, ctx);\n }\n return this.renderPrimitive(key, String(value), ctx);\n }\n\n /**\n * Render a nested fragment - subclasses implement this.\n */\n protected abstract renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string;\n\n /**\n * Render all entries of an object.\n */\n protected renderEntries(data: FragmentObject, ctx: RenderContext): string[] {\n return Object.entries(data)\n .map(([key, value]) => this.renderValue(key, value, ctx))\n .filter(Boolean);\n }\n\n // Hooks - subclasses implement these\n protected abstract renderPrimitive(\n key: string,\n value: string,\n ctx: RenderContext,\n ): string;\n protected abstract renderArray(\n key: string,\n items: FragmentData[],\n ctx: RenderContext,\n ): string;\n protected abstract renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string;\n}\n\n/**\n * Renders context fragments as XML.\n */\nexport class XmlRenderer extends ContextRenderer {\n render(fragments: ContextFragment[]): string {\n return fragments\n .map((f) => this.#renderTopLevel(f))\n .filter(Boolean)\n .join('\\n');\n }\n\n #renderTopLevel(fragment: ContextFragment): string {\n if (this.isPrimitive(fragment.data)) {\n return this.#leafRoot(fragment.name, String(fragment.data));\n }\n if (Array.isArray(fragment.data)) {\n return this.#renderArray(fragment.name, fragment.data, 0);\n }\n if (isFragment(fragment.data)) {\n const child = this.renderFragment(fragment.data, { depth: 1, path: [] });\n return this.#wrap(fragment.name, [child]);\n }\n return this.#wrap(\n fragment.name,\n this.renderEntries(fragment.data, { depth: 1, path: [] }),\n );\n }\n\n #renderArray(name: string, items: FragmentData[], depth: number): string {\n const fragmentItems = items.filter(isFragment);\n const nonFragmentItems = items.filter((item) => !isFragment(item));\n\n const children: string[] = [];\n\n // Render non-fragment items\n for (const item of nonFragmentItems) {\n if (item != null) {\n children.push(\n this.#leaf(pluralize.singular(name), String(item), depth + 1),\n );\n }\n }\n\n // Render fragment items (possibly grouped)\n if (this.options.groupFragments && fragmentItems.length > 0) {\n const groups = this.groupByName(fragmentItems);\n for (const [groupName, groupFragments] of groups) {\n const groupChildren = groupFragments.map((frag) =>\n this.renderFragment(frag, { depth: depth + 2, path: [] }),\n );\n const pluralName = pluralize.plural(groupName);\n children.push(this.#wrapIndented(pluralName, groupChildren, depth + 1));\n }\n } else {\n for (const frag of fragmentItems) {\n children.push(\n this.renderFragment(frag, { depth: depth + 1, path: [] }),\n );\n }\n }\n\n return this.#wrap(name, children);\n }\n\n #leafRoot(tag: string, value: string): string {\n const safe = this.#escape(value);\n if (safe.includes('\\n')) {\n return `<${tag}>\\n${this.#indent(safe, 2)}\\n</${tag}>`;\n }\n return `<${tag}>${safe}</${tag}>`;\n }\n\n protected renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string {\n const { name, data } = fragment;\n if (this.isPrimitive(data)) {\n return this.#leaf(name, String(data), ctx.depth);\n }\n if (isFragment(data)) {\n const child = this.renderFragment(data, { ...ctx, depth: ctx.depth + 1 });\n return this.#wrapIndented(name, [child], ctx.depth);\n }\n if (Array.isArray(data)) {\n return this.#renderArrayIndented(name, data, ctx.depth);\n }\n const children = this.renderEntries(data, { ...ctx, depth: ctx.depth + 1 });\n return this.#wrapIndented(name, children, ctx.depth);\n }\n\n #renderArrayIndented(\n name: string,\n items: FragmentData[],\n depth: number,\n ): string {\n const fragmentItems = items.filter(isFragment);\n const nonFragmentItems = items.filter((item) => !isFragment(item));\n\n const children: string[] = [];\n\n // Render non-fragment items\n for (const item of nonFragmentItems) {\n if (item != null) {\n children.push(\n this.#leaf(pluralize.singular(name), String(item), depth + 1),\n );\n }\n }\n\n // Render fragment items (possibly grouped)\n if (this.options.groupFragments && fragmentItems.length > 0) {\n const groups = this.groupByName(fragmentItems);\n for (const [groupName, groupFragments] of groups) {\n const groupChildren = groupFragments.map((frag) =>\n this.renderFragment(frag, { depth: depth + 2, path: [] }),\n );\n const pluralName = pluralize.plural(groupName);\n children.push(this.#wrapIndented(pluralName, groupChildren, depth + 1));\n }\n } else {\n for (const frag of fragmentItems) {\n children.push(\n this.renderFragment(frag, { depth: depth + 1, path: [] }),\n );\n }\n }\n\n return this.#wrapIndented(name, children, depth);\n }\n\n protected renderPrimitive(\n key: string,\n value: string,\n ctx: RenderContext,\n ): string {\n return this.#leaf(key, value, ctx.depth);\n }\n\n protected renderArray(\n key: string,\n items: FragmentData[],\n ctx: RenderContext,\n ): string {\n if (!items.length) {\n return '';\n }\n const itemTag = pluralize.singular(key);\n const children = items\n .filter((item) => item != null)\n .map((item) => this.#leaf(itemTag, String(item), ctx.depth + 1));\n return this.#wrapIndented(key, children, ctx.depth);\n }\n\n protected renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string {\n const children = this.renderEntries(obj, { ...ctx, depth: ctx.depth + 1 });\n return this.#wrapIndented(key, children, ctx.depth);\n }\n\n #escape(value: string): string {\n if (value == null) {\n return '';\n }\n return value\n .replaceAll(/&/g, '&amp;')\n .replaceAll(/</g, '&lt;')\n .replaceAll(/>/g, '&gt;')\n .replaceAll(/\"/g, '&quot;')\n .replaceAll(/'/g, '&apos;');\n }\n\n #indent(text: string, spaces: number): string {\n if (!text.trim()) {\n return '';\n }\n const padding = ' '.repeat(spaces);\n return text\n .split('\\n')\n .map((line) => (line.length ? padding + line : padding))\n .join('\\n');\n }\n\n #leaf(tag: string, value: string, depth: number): string {\n const safe = this.#escape(value);\n const pad = ' '.repeat(depth);\n if (safe.includes('\\n')) {\n return `${pad}<${tag}>\\n${this.#indent(safe, (depth + 1) * 2)}\\n${pad}</${tag}>`;\n }\n return `${pad}<${tag}>${safe}</${tag}>`;\n }\n\n #wrap(tag: string, children: string[]): string {\n const content = children.filter(Boolean).join('\\n');\n if (!content) {\n return '';\n }\n return `<${tag}>\\n${content}\\n</${tag}>`;\n }\n\n #wrapIndented(tag: string, children: string[], depth: number): string {\n const content = children.filter(Boolean).join('\\n');\n if (!content) {\n return '';\n }\n const pad = ' '.repeat(depth);\n return `${pad}<${tag}>\\n${content}\\n${pad}</${tag}>`;\n }\n}\n\n/**\n * Renders context fragments as Markdown.\n */\nexport class MarkdownRenderer extends ContextRenderer {\n render(fragments: ContextFragment[]): string {\n return fragments\n .map((f) => {\n const title = `## ${titlecase(f.name)}`;\n if (this.isPrimitive(f.data)) {\n return `${title}\\n${String(f.data)}`;\n }\n if (Array.isArray(f.data)) {\n return `${title}\\n${this.#renderArray(f.data, 0)}`;\n }\n if (isFragment(f.data)) {\n return `${title}\\n${this.renderFragment(f.data, { depth: 0, path: [] })}`;\n }\n return `${title}\\n${this.renderEntries(f.data, { depth: 0, path: [] }).join('\\n')}`;\n })\n .join('\\n\\n');\n }\n\n #renderArray(items: FragmentData[], depth: number): string {\n const fragmentItems = items.filter(isFragment);\n const nonFragmentItems = items.filter((item) => !isFragment(item));\n\n const lines: string[] = [];\n\n // Render non-fragment items\n for (const item of nonFragmentItems) {\n if (item != null) {\n lines.push(`${this.#pad(depth)}- ${String(item)}`);\n }\n }\n\n // Render fragment items (possibly grouped)\n if (this.options.groupFragments && fragmentItems.length > 0) {\n const groups = this.groupByName(fragmentItems);\n for (const [groupName, groupFragments] of groups) {\n const pluralName = pluralize.plural(groupName);\n lines.push(`${this.#pad(depth)}- **${titlecase(pluralName)}**:`);\n for (const frag of groupFragments) {\n lines.push(this.renderFragment(frag, { depth: depth + 1, path: [] }));\n }\n }\n } else {\n for (const frag of fragmentItems) {\n lines.push(this.renderFragment(frag, { depth, path: [] }));\n }\n }\n\n return lines.join('\\n');\n }\n\n #pad(depth: number): string {\n return ' '.repeat(depth);\n }\n\n #leaf(key: string, value: string, depth: number): string {\n return `${this.#pad(depth)}- **${key}**: ${value}`;\n }\n\n #arrayItem(item: unknown, depth: number): string {\n if (isFragment(item)) {\n return this.renderFragment(item, { depth, path: [] });\n }\n if (isFragmentObject(item)) {\n return this.renderEntries(item, {\n depth,\n path: [],\n }).join('\\n');\n }\n return `${this.#pad(depth)}- ${String(item)}`;\n }\n\n protected renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string {\n const { name, data } = fragment;\n const header = `${this.#pad(ctx.depth)}- **${name}**:`;\n if (this.isPrimitive(data)) {\n return `${this.#pad(ctx.depth)}- **${name}**: ${String(data)}`;\n }\n if (isFragment(data)) {\n const child = this.renderFragment(data, { ...ctx, depth: ctx.depth + 1 });\n return [header, child].join('\\n');\n }\n if (Array.isArray(data)) {\n const children = data\n .filter((item) => item != null)\n .map((item) => this.#arrayItem(item, ctx.depth + 1));\n return [header, ...children].join('\\n');\n }\n const children = this.renderEntries(data, {\n ...ctx,\n depth: ctx.depth + 1,\n }).join('\\n');\n return [header, children].join('\\n');\n }\n\n protected renderPrimitive(\n key: string,\n value: string,\n ctx: RenderContext,\n ): string {\n return this.#leaf(key, value, ctx.depth);\n }\n\n protected renderArray(\n key: string,\n items: FragmentData[],\n ctx: RenderContext,\n ): string {\n const header = `${this.#pad(ctx.depth)}- **${key}**:`;\n const children = items\n .filter((item) => item != null)\n .map((item) => this.#arrayItem(item, ctx.depth + 1));\n return [header, ...children].join('\\n');\n }\n\n protected renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string {\n const header = `${this.#pad(ctx.depth)}- **${key}**:`;\n const children = this.renderEntries(obj, {\n ...ctx,\n depth: ctx.depth + 1,\n }).join('\\n');\n return [header, children].join('\\n');\n }\n}\n\n/**\n * Renders context fragments as TOML.\n */\nexport class TomlRenderer extends ContextRenderer {\n render(fragments: ContextFragment[]): string {\n return fragments\n .map((f) => {\n if (this.isPrimitive(f.data)) {\n return `${f.name} = ${this.#formatValue(f.data)}`;\n }\n if (Array.isArray(f.data)) {\n return this.#renderTopLevelArray(f.name, f.data);\n }\n if (isFragment(f.data)) {\n return [\n `[${f.name}]`,\n this.renderFragment(f.data, { depth: 0, path: [f.name] }),\n ].join('\\n');\n }\n const entries = this.#renderObjectEntries(f.data, [f.name]);\n return [`[${f.name}]`, ...entries].join('\\n');\n })\n .join('\\n\\n');\n }\n\n #renderTopLevelArray(name: string, items: FragmentData[]): string {\n const fragmentItems = items.filter(isFragment);\n const nonFragmentItems = items.filter(\n (item) => !isFragment(item) && item != null,\n );\n\n // If array contains fragments, render as sections\n if (fragmentItems.length > 0) {\n const parts: string[] = [`[${name}]`];\n for (const frag of fragmentItems) {\n parts.push(this.renderFragment(frag, { depth: 0, path: [name] }));\n }\n return parts.join('\\n');\n }\n\n // Otherwise render as inline array\n const values = nonFragmentItems.map((item) => this.#formatValue(item));\n return `${name} = [${values.join(', ')}]`;\n }\n\n /**\n * Override renderValue to preserve type information for TOML formatting.\n */\n protected override renderValue(\n key: string,\n value: unknown,\n ctx: RenderContext,\n ): string {\n if (value == null) {\n return '';\n }\n if (isFragment(value)) {\n return this.renderFragment(value, ctx);\n }\n if (Array.isArray(value)) {\n return this.renderArray(key, value, ctx);\n }\n if (isFragmentObject(value)) {\n return this.renderObject(key, value, ctx);\n }\n // Preserve original type for TOML formatting\n return `${key} = ${this.#formatValue(value)}`;\n }\n\n protected renderPrimitive(\n key: string,\n value: string,\n _ctx: RenderContext,\n ): string {\n return `${key} = ${this.#formatValue(value)}`;\n }\n\n protected renderArray(\n key: string,\n items: FragmentData[],\n _ctx: RenderContext,\n ): string {\n const values = items\n .filter((item) => item != null)\n .map((item) => this.#formatValue(item));\n return `${key} = [${values.join(', ')}]`;\n }\n\n protected renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string {\n const newPath = [...ctx.path, key];\n const entries = this.#renderObjectEntries(obj, newPath);\n return ['', `[${newPath.join('.')}]`, ...entries].join('\\n');\n }\n\n #renderObjectEntries(obj: FragmentObject, path: string[]): string[] {\n return Object.entries(obj)\n .map(([key, value]) => {\n if (value == null) {\n return '';\n }\n if (isFragmentObject(value)) {\n const newPath = [...path, key];\n const entries = this.#renderObjectEntries(value, newPath);\n return ['', `[${newPath.join('.')}]`, ...entries].join('\\n');\n }\n if (Array.isArray(value)) {\n const values = value\n .filter((item) => item != null)\n .map((item) => this.#formatValue(item));\n return `${key} = [${values.join(', ')}]`;\n }\n return `${key} = ${this.#formatValue(value)}`;\n })\n .filter(Boolean);\n }\n\n protected renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string {\n const { name, data } = fragment;\n const newPath = [...ctx.path, name];\n if (this.isPrimitive(data)) {\n return `${name} = ${this.#formatValue(data)}`;\n }\n if (isFragment(data)) {\n return [\n '',\n `[${newPath.join('.')}]`,\n this.renderFragment(data, { ...ctx, path: newPath }),\n ].join('\\n');\n }\n if (Array.isArray(data)) {\n const fragmentItems = data.filter(isFragment);\n const nonFragmentItems = data.filter(\n (item) => !isFragment(item) && item != null,\n );\n\n if (fragmentItems.length > 0) {\n const parts: string[] = ['', `[${newPath.join('.')}]`];\n for (const frag of fragmentItems) {\n parts.push(this.renderFragment(frag, { ...ctx, path: newPath }));\n }\n return parts.join('\\n');\n }\n\n const values = nonFragmentItems.map((item) => this.#formatValue(item));\n return `${name} = [${values.join(', ')}]`;\n }\n const entries = this.#renderObjectEntries(data, newPath);\n return ['', `[${newPath.join('.')}]`, ...entries].join('\\n');\n }\n\n #escape(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n }\n\n #formatValue(value: unknown): string {\n if (typeof value === 'string') {\n return `\"${this.#escape(value)}\"`;\n }\n if (typeof value === 'boolean' || typeof value === 'number') {\n return String(value);\n }\n if (typeof value === 'object' && value !== null) {\n return JSON.stringify(value);\n }\n return `\"${String(value)}\"`;\n }\n}\n\n/**\n * Renders context fragments as TOON (Token-Oriented Object Notation).\n * TOON is a compact, token-efficient format for LLM prompts that combines\n * YAML-like indentation with CSV-like tabular arrays.\n */\nexport class ToonRenderer extends ContextRenderer {\n render(fragments: ContextFragment[]): string {\n return fragments\n .map((f) => this.#renderTopLevel(f))\n .filter(Boolean)\n .join('\\n');\n }\n\n #renderTopLevel(fragment: ContextFragment): string {\n const { name, data } = fragment;\n if (this.isPrimitive(data)) {\n return `${name}: ${this.#formatValue(data)}`;\n }\n if (Array.isArray(data)) {\n return this.#renderArrayField(name, data, 0);\n }\n if (isFragment(data)) {\n const child = this.renderFragment(data, { depth: 1, path: [] });\n return `${name}:\\n${child}`;\n }\n if (isFragmentObject(data)) {\n const entries = this.#renderObjectEntries(data, 1);\n if (!entries) {\n return `${name}:`;\n }\n return `${name}:\\n${entries}`;\n }\n return `${name}:`;\n }\n\n #renderArrayField(key: string, items: FragmentData[], depth: number): string {\n const filtered = items.filter((item) => item != null);\n if (filtered.length === 0) {\n return `${this.#pad(depth)}${key}[0]:`;\n }\n\n // Check for ContextFragment items\n const fragmentItems = filtered.filter(isFragment);\n if (fragmentItems.length > 0) {\n return this.#renderMixedArray(key, filtered, depth);\n }\n\n // Check if all items are primitives\n if (filtered.every((item) => this.#isPrimitiveValue(item))) {\n return this.#renderPrimitiveArray(key, filtered, depth);\n }\n\n // Check if tabular (uniform objects with primitive values)\n if (this.#isTabularArray(filtered)) {\n return this.#renderTabularArray(key, filtered, depth);\n }\n\n // Mixed array\n return this.#renderMixedArray(key, filtered, depth);\n }\n\n #isPrimitiveValue(value: unknown): boolean {\n return (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n );\n }\n\n #isTabularArray(items: FragmentData[]): items is FragmentObject[] {\n if (items.length === 0) return false;\n\n // All items must be objects (not arrays, not primitives, not fragments)\n const objects = items.filter(isFragmentObject);\n if (objects.length !== items.length) return false;\n\n // Get keys from first object\n const firstKeys = Object.keys(objects[0]).sort().join(',');\n\n // All objects must have same keys\n for (const obj of objects) {\n if (Object.keys(obj).sort().join(',') !== firstKeys) {\n return false;\n }\n // All values must be primitives\n for (const value of Object.values(obj)) {\n if (!this.#isPrimitiveValue(value) && value !== null) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n #renderPrimitiveArray(\n key: string,\n items: FragmentData[],\n depth: number,\n ): string {\n const values = items.map((item) => this.#formatValue(item)).join(',');\n return `${this.#pad(depth)}${key}[${items.length}]: ${values}`;\n }\n\n #renderTabularArray(\n key: string,\n items: FragmentObject[],\n depth: number,\n ): string {\n if (items.length === 0) {\n return `${this.#pad(depth)}${key}[0]:`;\n }\n\n const fields = Object.keys(items[0]);\n const header = `${this.#pad(depth)}${key}[${items.length}]{${fields.join(',')}}:`;\n\n const rows = items.map((obj) => {\n const values = fields.map((f) => this.#formatValue(obj[f]));\n return `${this.#pad(depth + 1)}${values.join(',')}`;\n });\n\n return [header, ...rows].join('\\n');\n }\n\n #renderMixedArray(key: string, items: FragmentData[], depth: number): string {\n const header = `${this.#pad(depth)}${key}[${items.length}]:`;\n const lines = items.map((item) => this.#renderListItem(item, depth + 1));\n return [header, ...lines].join('\\n');\n }\n\n #renderListItem(item: FragmentData, depth: number): string {\n if (this.#isPrimitiveValue(item)) {\n return `${this.#pad(depth)}- ${this.#formatValue(item)}`;\n }\n if (isFragment(item)) {\n const rendered = this.renderFragment(item, {\n depth: depth + 1,\n path: [],\n });\n // For fragments, render key: value on same line as hyphen if primitive\n if (this.isPrimitive(item.data)) {\n return `${this.#pad(depth)}- ${item.name}: ${this.#formatValue(item.data)}`;\n }\n return `${this.#pad(depth)}- ${item.name}:\\n${rendered.split('\\n').slice(1).join('\\n')}`;\n }\n if (Array.isArray(item)) {\n // Nested array\n const content = this.#renderArrayField('', item, depth + 1);\n return `${this.#pad(depth)}-${content.trimStart()}`;\n }\n if (isFragmentObject(item)) {\n // Object in list\n const entries = this.#renderObjectEntries(item, depth + 1);\n if (!entries) {\n return `${this.#pad(depth)}-`;\n }\n // First line on same line as hyphen\n const lines = entries.split('\\n');\n const first = lines[0].trimStart();\n const rest = lines.slice(1).join('\\n');\n return rest\n ? `${this.#pad(depth)}- ${first}\\n${rest}`\n : `${this.#pad(depth)}- ${first}`;\n }\n return `${this.#pad(depth)}- ${this.#formatValue(item)}`;\n }\n\n #renderObjectEntries(obj: FragmentObject, depth: number): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(obj)) {\n if (value == null) continue;\n\n if (this.#isPrimitiveValue(value)) {\n lines.push(`${this.#pad(depth)}${key}: ${this.#formatValue(value)}`);\n } else if (Array.isArray(value)) {\n lines.push(this.#renderArrayField(key, value, depth));\n } else if (isFragmentObject(value)) {\n const nested = this.#renderObjectEntries(value, depth + 1);\n if (nested) {\n lines.push(`${this.#pad(depth)}${key}:\\n${nested}`);\n } else {\n lines.push(`${this.#pad(depth)}${key}:`);\n }\n }\n }\n return lines.join('\\n');\n }\n\n protected renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string {\n const { name, data } = fragment;\n if (this.isPrimitive(data)) {\n return `${this.#pad(ctx.depth)}${name}: ${this.#formatValue(data)}`;\n }\n if (isFragment(data)) {\n const child = this.renderFragment(data, {\n ...ctx,\n depth: ctx.depth + 1,\n });\n return `${this.#pad(ctx.depth)}${name}:\\n${child}`;\n }\n if (Array.isArray(data)) {\n return this.#renderArrayField(name, data, ctx.depth);\n }\n if (isFragmentObject(data)) {\n const entries = this.#renderObjectEntries(data, ctx.depth + 1);\n if (!entries) {\n return `${this.#pad(ctx.depth)}${name}:`;\n }\n return `${this.#pad(ctx.depth)}${name}:\\n${entries}`;\n }\n return `${this.#pad(ctx.depth)}${name}:`;\n }\n\n protected renderPrimitive(\n key: string,\n value: string,\n ctx: RenderContext,\n ): string {\n return `${this.#pad(ctx.depth)}${key}: ${this.#formatValue(value)}`;\n }\n\n protected renderArray(\n key: string,\n items: FragmentData[],\n ctx: RenderContext,\n ): string {\n return this.#renderArrayField(key, items, ctx.depth);\n }\n\n protected renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string {\n const entries = this.#renderObjectEntries(obj, ctx.depth + 1);\n if (!entries) {\n return `${this.#pad(ctx.depth)}${key}:`;\n }\n return `${this.#pad(ctx.depth)}${key}:\\n${entries}`;\n }\n\n #pad(depth: number): string {\n return ' '.repeat(depth);\n }\n\n #needsQuoting(value: string): boolean {\n if (value === '') return true;\n if (value !== value.trim()) return true;\n if (['true', 'false', 'null'].includes(value.toLowerCase())) return true;\n if (/^-?\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?$/i.test(value)) return true;\n if (/[:\\\\\"'[\\]{}|,\\t\\n\\r]/.test(value)) return true;\n if (value.startsWith('-')) return true;\n return false;\n }\n\n #escape(value: string): string {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n }\n\n #canonicalizeNumber(n: number): string {\n if (!Number.isFinite(n)) return 'null';\n if (Object.is(n, -0)) return '0';\n return String(n);\n }\n\n #formatValue(value: unknown): string {\n if (value === null) return 'null';\n if (typeof value === 'boolean') return String(value);\n if (typeof value === 'number') return this.#canonicalizeNumber(value);\n if (typeof value === 'string') {\n if (this.#needsQuoting(value)) {\n return `\"${this.#escape(value)}\"`;\n }\n return value;\n }\n // Fallback for objects/arrays in primitive context\n return `\"${this.#escape(JSON.stringify(value))}\"`;\n }\n}\n", "/**\n * Graph-based context store types and abstract interface.\n *\n * The storage model uses a DAG (Directed Acyclic Graph) for messages:\n * - Messages are immutable nodes with parentId forming the graph\n * - Branches are pointers to head (tip) messages\n * - Checkpoints are pointers to specific messages\n * - History is preserved through branching (rewind creates new branch)\n */\n\n// ============================================================================\n// Chat Types\n// ============================================================================\n\n/**\n * Data for creating/storing a chat.\n */\nexport interface ChatData {\n id: string;\n title?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Stored chat data returned from database (includes timestamps).\n */\nexport interface StoredChatData extends ChatData {\n createdAt: number;\n updatedAt: number;\n}\n\n/**\n * Information about a chat for listing.\n */\nexport interface ChatInfo {\n id: string;\n title?: string;\n messageCount: number;\n branchCount: number;\n createdAt: number;\n updatedAt: number;\n}\n\n// ============================================================================\n// Message Types (Graph Nodes)\n// ============================================================================\n\n/**\n * Data for creating/storing a message (graph node).\n */\nexport interface MessageData {\n id: string;\n chatId: string;\n parentId: string | null; // null for root messages\n name: string; // 'user', 'assistant', 'role', 'hint', etc.\n type?: string; // 'message', 'fragment'\n data: unknown; // JSON-serializable content\n createdAt: number;\n}\n\n/**\n * Message with computed properties for listing.\n */\nexport interface MessageInfo extends MessageData {\n hasChildren: boolean;\n}\n\n// ============================================================================\n// Branch Types\n// ============================================================================\n\n/**\n * Data for creating/storing a branch.\n * A branch is a pointer to a head message in the graph.\n */\nexport interface BranchData {\n id: string;\n chatId: string;\n name: string; // 'main', 'alt-1', etc.\n headMessageId: string | null; // null if branch is empty\n isActive: boolean;\n createdAt: number;\n}\n\n/**\n * Information about a branch for listing.\n */\nexport interface BranchInfo {\n id: string;\n name: string;\n headMessageId: string | null;\n isActive: boolean;\n messageCount: number; // count of messages in this branch's chain\n createdAt: number;\n}\n\n// ============================================================================\n// Checkpoint Types\n// ============================================================================\n\n/**\n * Data for creating/storing a checkpoint.\n * A checkpoint is a pointer to a specific message in the graph.\n */\nexport interface CheckpointData {\n id: string;\n chatId: string;\n name: string;\n messageId: string;\n createdAt: number;\n}\n\n/**\n * Information about a checkpoint for listing.\n */\nexport interface CheckpointInfo {\n id: string;\n name: string;\n messageId: string;\n createdAt: number;\n}\n\n// ============================================================================\n// Search Types\n// ============================================================================\n\n/**\n * Options for searching messages.\n */\nexport interface SearchOptions {\n /** Only search in specific roles (e.g., ['user', 'assistant']) */\n roles?: string[];\n /** Maximum results to return (default: 20) */\n limit?: number;\n}\n\n/**\n * Search result with relevance ranking.\n */\nexport interface SearchResult {\n /** The matched message */\n message: MessageData;\n /** BM25 relevance score (lower = more relevant) */\n rank: number;\n /** Highlighted snippet with matched terms */\n snippet?: string;\n}\n\n// ============================================================================\n// Graph Visualization Types\n// ============================================================================\n\n/**\n * A node in the visualization graph.\n */\nexport interface GraphNode {\n id: string;\n parentId: string | null;\n role: string; // 'user', 'assistant', etc.\n content: string; // Truncated preview of message content\n createdAt: number;\n}\n\n/**\n * A branch pointer for visualization.\n */\nexport interface GraphBranch {\n name: string;\n headMessageId: string | null;\n isActive: boolean;\n}\n\n/**\n * A checkpoint pointer for visualization.\n */\nexport interface GraphCheckpoint {\n name: string;\n messageId: string;\n}\n\n/**\n * Complete graph data for visualization.\n */\nexport interface GraphData {\n chatId: string;\n nodes: GraphNode[];\n branches: GraphBranch[];\n checkpoints: GraphCheckpoint[];\n}\n\n// ============================================================================\n// Abstract Store Interface\n// ============================================================================\n\n/**\n * Abstract base class for graph-based context storage.\n *\n * Implementations provide persistence for the message graph, branches,\n * and checkpoints. The graph model enables:\n * - Branching: rewind creates a new branch, original stays intact\n * - Checkpoints: pointers to specific messages for easy restore\n * - No data loss: soft delete only, all history preserved\n */\nexport abstract class ContextStore {\n // ==========================================================================\n // Chat Operations\n // ==========================================================================\n\n /**\n * Create a new chat.\n */\n abstract createChat(chat: ChatData): Promise<void>;\n\n /**\n * Create a chat if it doesn't exist, or return existing one.\n * Returns the stored chat data with timestamps.\n */\n abstract upsertChat(chat: ChatData): Promise<StoredChatData>;\n\n /**\n * Get a chat by ID.\n */\n abstract getChat(chatId: string): Promise<StoredChatData | undefined>;\n\n /**\n * Update chat metadata.\n * Note: updatedAt is automatically managed by database triggers.\n * Returns the updated chat data.\n */\n abstract updateChat(\n chatId: string,\n updates: Partial<Pick<ChatData, 'title' | 'metadata'>>,\n ): Promise<StoredChatData>;\n\n /**\n * List all chats, sorted by updatedAt descending.\n */\n abstract listChats(): Promise<ChatInfo[]>;\n\n // ==========================================================================\n // Message Operations (Graph Nodes)\n // ==========================================================================\n\n /**\n * Add a message to the graph.\n */\n abstract addMessage(message: MessageData): Promise<void>;\n\n /**\n * Get a message by ID.\n */\n abstract getMessage(messageId: string): Promise<MessageData | undefined>;\n\n /**\n * Walk up the parent chain from a head message, returning messages in\n * chronological order (root first).\n */\n abstract getMessageChain(headId: string): Promise<MessageData[]>;\n\n /**\n * Check if a message has children (is a fork point).\n */\n abstract hasChildren(messageId: string): Promise<boolean>;\n\n // ==========================================================================\n // Branch Operations\n // ==========================================================================\n\n /**\n * Create a new branch.\n */\n abstract createBranch(branch: BranchData): Promise<void>;\n\n /**\n * Get a branch by chat ID and name.\n */\n abstract getBranch(\n chatId: string,\n name: string,\n ): Promise<BranchData | undefined>;\n\n /**\n * Get the active branch for a chat.\n */\n abstract getActiveBranch(chatId: string): Promise<BranchData | undefined>;\n\n /**\n * Set a branch as active (and deactivate others).\n */\n abstract setActiveBranch(chatId: string, branchId: string): Promise<void>;\n\n /**\n * Update a branch's head message.\n */\n abstract updateBranchHead(\n branchId: string,\n messageId: string | null,\n ): Promise<void>;\n\n /**\n * List all branches for a chat.\n */\n abstract listBranches(chatId: string): Promise<BranchInfo[]>;\n\n // ==========================================================================\n // Checkpoint Operations\n // ==========================================================================\n\n /**\n * Create a checkpoint.\n */\n abstract createCheckpoint(checkpoint: CheckpointData): Promise<void>;\n\n /**\n * Get a checkpoint by chat ID and name.\n */\n abstract getCheckpoint(\n chatId: string,\n name: string,\n ): Promise<CheckpointData | undefined>;\n\n /**\n * List all checkpoints for a chat.\n */\n abstract listCheckpoints(chatId: string): Promise<CheckpointInfo[]>;\n\n /**\n * Delete a checkpoint.\n */\n abstract deleteCheckpoint(chatId: string, name: string): Promise<void>;\n\n // ==========================================================================\n // Search Operations\n // ==========================================================================\n\n /**\n * Search messages using full-text search.\n *\n * @param chatId - The chat to search in\n * @param query - FTS5 query string (supports AND, OR, NOT, phrases, prefix*)\n * @param options - Search options\n * @returns Search results ordered by relevance (lower rank = more relevant)\n */\n abstract searchMessages(\n chatId: string,\n query: string,\n options?: SearchOptions,\n ): Promise<SearchResult[]>;\n\n // ==========================================================================\n // Visualization Operations\n // ==========================================================================\n\n /**\n * Get the complete graph data for a chat.\n * Returns all messages, branches, and checkpoints.\n */\n abstract getGraph(chatId: string): Promise<GraphData>;\n}\n", "import { DatabaseSync, type SQLInputValue } from 'node:sqlite';\n\nimport type {\n BranchData,\n BranchInfo,\n ChatData,\n ChatInfo,\n CheckpointData,\n CheckpointInfo,\n GraphBranch,\n GraphCheckpoint,\n GraphData,\n GraphNode,\n MessageData,\n SearchOptions,\n SearchResult,\n StoredChatData,\n} from './store.ts';\nimport { ContextStore } from './store.ts';\n\nconst STORE_DDL = `\n-- Chats table\n-- createdAt/updatedAt: DEFAULT for insert, inline SET for updates\nCREATE TABLE IF NOT EXISTS chats (\n id TEXT PRIMARY KEY,\n title TEXT,\n metadata TEXT,\n createdAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n updatedAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000)\n);\n\nCREATE INDEX IF NOT EXISTS idx_chats_updatedAt ON chats(updatedAt);\n\n-- Messages table (nodes in the DAG)\nCREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n parentId TEXT,\n name TEXT NOT NULL,\n type TEXT,\n data TEXT NOT NULL,\n createdAt INTEGER NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (parentId) REFERENCES messages(id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_messages_chatId ON messages(chatId);\nCREATE INDEX IF NOT EXISTS idx_messages_parentId ON messages(parentId);\n\n-- Branches table (pointers to head messages)\nCREATE TABLE IF NOT EXISTS branches (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n name TEXT NOT NULL,\n headMessageId TEXT,\n isActive INTEGER NOT NULL DEFAULT 0,\n createdAt INTEGER NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (headMessageId) REFERENCES messages(id),\n UNIQUE(chatId, name)\n);\n\nCREATE INDEX IF NOT EXISTS idx_branches_chatId ON branches(chatId);\n\n-- Checkpoints table (pointers to message nodes)\nCREATE TABLE IF NOT EXISTS checkpoints (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n name TEXT NOT NULL,\n messageId TEXT NOT NULL,\n createdAt INTEGER NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (messageId) REFERENCES messages(id),\n UNIQUE(chatId, name)\n);\n\nCREATE INDEX IF NOT EXISTS idx_checkpoints_chatId ON checkpoints(chatId);\n\n-- FTS5 virtual table for full-text search\n-- messageId/chatId/name are UNINDEXED (stored but not searchable, used for filtering/joining)\n-- Only 'content' is indexed for full-text search\nCREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(\n messageId UNINDEXED,\n chatId UNINDEXED,\n name UNINDEXED,\n content,\n tokenize='porter unicode61'\n);\n`;\n\n/**\n * SQLite-based context store using graph model.\n *\n * Uses node:sqlite's synchronous DatabaseSync for persistence.\n * Messages are stored as nodes in a DAG with parentId links.\n */\nexport class SqliteContextStore extends ContextStore {\n #db: DatabaseSync;\n\n constructor(path: string) {\n super();\n this.#db = new DatabaseSync(path);\n this.#db.exec('PRAGMA foreign_keys = ON');\n this.#db.exec(STORE_DDL);\n }\n\n // ==========================================================================\n // Chat Operations\n // ==========================================================================\n\n async createChat(chat: ChatData): Promise<void> {\n // createdAt and updatedAt are auto-set by SQLite DEFAULT\n this.#db\n .prepare(\n `INSERT INTO chats (id, title, metadata)\n VALUES (?, ?, ?)`,\n )\n .run(\n chat.id,\n chat.title ?? null,\n chat.metadata ? JSON.stringify(chat.metadata) : null,\n );\n }\n\n async upsertChat(chat: ChatData): Promise<StoredChatData> {\n // Insert if not exists, no-op update if exists (to trigger RETURNING)\n const row = this.#db\n .prepare(\n `INSERT INTO chats (id, title, metadata)\n VALUES (?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET id = excluded.id\n RETURNING *`,\n )\n .get(\n chat.id,\n chat.title ?? null,\n chat.metadata ? JSON.stringify(chat.metadata) : null,\n ) as {\n id: string;\n title: string | null;\n metadata: string | null;\n createdAt: number;\n updatedAt: number;\n };\n\n return {\n id: row.id,\n title: row.title ?? undefined,\n metadata: row.metadata ? JSON.parse(row.metadata) : undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n async getChat(chatId: string): Promise<StoredChatData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM chats WHERE id = ?')\n .get(chatId) as\n | {\n id: string;\n title: string | null;\n metadata: string | null;\n createdAt: number;\n updatedAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n title: row.title ?? undefined,\n metadata: row.metadata ? JSON.parse(row.metadata) : undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n async updateChat(\n chatId: string,\n updates: Partial<Pick<ChatData, 'title' | 'metadata'>>,\n ): Promise<StoredChatData> {\n const setClauses: string[] = [\"updatedAt = strftime('%s', 'now') * 1000\"];\n const params: SQLInputValue[] = [];\n\n if (updates.title !== undefined) {\n setClauses.push('title = ?');\n params.push(updates.title ?? null);\n }\n if (updates.metadata !== undefined) {\n setClauses.push('metadata = ?');\n params.push(JSON.stringify(updates.metadata));\n }\n\n params.push(chatId);\n const row = this.#db\n .prepare(\n `UPDATE chats SET ${setClauses.join(', ')} WHERE id = ? RETURNING *`,\n )\n .get(...params) as {\n id: string;\n title: string | null;\n metadata: string | null;\n createdAt: number;\n updatedAt: number;\n };\n\n return {\n id: row.id,\n title: row.title ?? undefined,\n metadata: row.metadata ? JSON.parse(row.metadata) : undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n async listChats(): Promise<ChatInfo[]> {\n const rows = this.#db\n .prepare(\n `SELECT\n c.id,\n c.title,\n c.createdAt,\n c.updatedAt,\n COUNT(DISTINCT m.id) as messageCount,\n COUNT(DISTINCT b.id) as branchCount\n FROM chats c\n LEFT JOIN messages m ON m.chatId = c.id\n LEFT JOIN branches b ON b.chatId = c.id\n GROUP BY c.id\n ORDER BY c.updatedAt DESC`,\n )\n .all() as {\n id: string;\n title: string | null;\n createdAt: number;\n updatedAt: number;\n messageCount: number;\n branchCount: number;\n }[];\n\n return rows.map((row) => ({\n id: row.id,\n title: row.title ?? undefined,\n messageCount: row.messageCount,\n branchCount: row.branchCount,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n }));\n }\n\n // ==========================================================================\n // Message Operations (Graph Nodes)\n // ==========================================================================\n\n async addMessage(message: MessageData): Promise<void> {\n // Upsert the message\n this.#db\n .prepare(\n `INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n parentId = excluded.parentId,\n name = excluded.name,\n type = excluded.type,\n data = excluded.data`,\n )\n .run(\n message.id,\n message.chatId,\n message.parentId,\n message.name,\n message.type ?? null,\n JSON.stringify(message.data),\n message.createdAt,\n );\n\n // Index in FTS for search\n const content =\n typeof message.data === 'string'\n ? message.data\n : JSON.stringify(message.data);\n\n // Delete existing FTS entry if any (for upsert), then insert new one\n this.#db\n .prepare(`DELETE FROM messages_fts WHERE messageId = ?`)\n .run(message.id);\n this.#db\n .prepare(\n `INSERT INTO messages_fts(messageId, chatId, name, content)\n VALUES (?, ?, ?, ?)`,\n )\n .run(message.id, message.chatId, message.name, content);\n }\n\n async getMessage(messageId: string): Promise<MessageData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM messages WHERE id = ?')\n .get(messageId) as\n | {\n id: string;\n chatId: string;\n parentId: string | null;\n name: string;\n type: string | null;\n data: string;\n createdAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n chatId: row.chatId,\n parentId: row.parentId,\n name: row.name,\n type: row.type ?? undefined,\n data: JSON.parse(row.data),\n createdAt: row.createdAt,\n };\n }\n\n async getMessageChain(headId: string): Promise<MessageData[]> {\n // Walk up the parent chain using recursive CTE with depth tracking\n // The CTE walks from head (newest) to root (oldest), so we track depth\n // and order by depth DESC to get chronological order (root first)\n const rows = this.#db\n .prepare(\n `WITH RECURSIVE chain AS (\n SELECT *, 0 as depth FROM messages WHERE id = ?\n UNION ALL\n SELECT m.*, c.depth + 1 FROM messages m\n INNER JOIN chain c ON m.id = c.parentId\n )\n SELECT * FROM chain\n ORDER BY depth DESC`,\n )\n .all(headId) as {\n id: string;\n chatId: string;\n parentId: string | null;\n name: string;\n type: string | null;\n data: string;\n createdAt: number;\n depth: number;\n }[];\n\n return rows.map((row) => ({\n id: row.id,\n chatId: row.chatId,\n parentId: row.parentId,\n name: row.name,\n type: row.type ?? undefined,\n data: JSON.parse(row.data),\n createdAt: row.createdAt,\n }));\n }\n\n async hasChildren(messageId: string): Promise<boolean> {\n const row = this.#db\n .prepare(\n 'SELECT EXISTS(SELECT 1 FROM messages WHERE parentId = ?) as hasChildren',\n )\n .get(messageId) as { hasChildren: number };\n\n return row.hasChildren === 1;\n }\n\n // ==========================================================================\n // Branch Operations\n // ==========================================================================\n\n async createBranch(branch: BranchData): Promise<void> {\n this.#db\n .prepare(\n `INSERT INTO branches (id, chatId, name, headMessageId, isActive, createdAt)\n VALUES (?, ?, ?, ?, ?, ?)`,\n )\n .run(\n branch.id,\n branch.chatId,\n branch.name,\n branch.headMessageId,\n branch.isActive ? 1 : 0,\n branch.createdAt,\n );\n }\n\n async getBranch(\n chatId: string,\n name: string,\n ): Promise<BranchData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM branches WHERE chatId = ? AND name = ?')\n .get(chatId, name) as\n | {\n id: string;\n chatId: string;\n name: string;\n headMessageId: string | null;\n isActive: number;\n createdAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n chatId: row.chatId,\n name: row.name,\n headMessageId: row.headMessageId,\n isActive: row.isActive === 1,\n createdAt: row.createdAt,\n };\n }\n\n async getActiveBranch(chatId: string): Promise<BranchData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM branches WHERE chatId = ? AND isActive = 1')\n .get(chatId) as\n | {\n id: string;\n chatId: string;\n name: string;\n headMessageId: string | null;\n isActive: number;\n createdAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n chatId: row.chatId,\n name: row.name,\n headMessageId: row.headMessageId,\n isActive: true,\n createdAt: row.createdAt,\n };\n }\n\n async setActiveBranch(chatId: string, branchId: string): Promise<void> {\n // Deactivate all branches for this chat\n this.#db\n .prepare('UPDATE branches SET isActive = 0 WHERE chatId = ?')\n .run(chatId);\n\n // Activate the specified branch\n this.#db\n .prepare('UPDATE branches SET isActive = 1 WHERE id = ?')\n .run(branchId);\n }\n\n async updateBranchHead(\n branchId: string,\n messageId: string | null,\n ): Promise<void> {\n this.#db\n .prepare('UPDATE branches SET headMessageId = ? WHERE id = ?')\n .run(messageId, branchId);\n }\n\n async listBranches(chatId: string): Promise<BranchInfo[]> {\n // Get branches with message count by walking the chain\n const branches = this.#db\n .prepare(\n `SELECT\n b.id,\n b.name,\n b.headMessageId,\n b.isActive,\n b.createdAt\n FROM branches b\n WHERE b.chatId = ?\n ORDER BY b.createdAt ASC`,\n )\n .all(chatId) as {\n id: string;\n name: string;\n headMessageId: string | null;\n isActive: number;\n createdAt: number;\n }[];\n\n // For each branch, count messages in the chain\n const result: BranchInfo[] = [];\n for (const branch of branches) {\n let messageCount = 0;\n if (branch.headMessageId) {\n const countRow = this.#db\n .prepare(\n `WITH RECURSIVE chain AS (\n SELECT id, parentId FROM messages WHERE id = ?\n UNION ALL\n SELECT m.id, m.parentId FROM messages m\n INNER JOIN chain c ON m.id = c.parentId\n )\n SELECT COUNT(*) as count FROM chain`,\n )\n .get(branch.headMessageId) as { count: number };\n messageCount = countRow.count;\n }\n\n result.push({\n id: branch.id,\n name: branch.name,\n headMessageId: branch.headMessageId,\n isActive: branch.isActive === 1,\n messageCount,\n createdAt: branch.createdAt,\n });\n }\n\n return result;\n }\n\n // ==========================================================================\n // Checkpoint Operations\n // ==========================================================================\n\n async createCheckpoint(checkpoint: CheckpointData): Promise<void> {\n this.#db\n .prepare(\n `INSERT INTO checkpoints (id, chatId, name, messageId, createdAt)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(chatId, name) DO UPDATE SET\n messageId = excluded.messageId,\n createdAt = excluded.createdAt`,\n )\n .run(\n checkpoint.id,\n checkpoint.chatId,\n checkpoint.name,\n checkpoint.messageId,\n checkpoint.createdAt,\n );\n }\n\n async getCheckpoint(\n chatId: string,\n name: string,\n ): Promise<CheckpointData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM checkpoints WHERE chatId = ? AND name = ?')\n .get(chatId, name) as\n | {\n id: string;\n chatId: string;\n name: string;\n messageId: string;\n createdAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n chatId: row.chatId,\n name: row.name,\n messageId: row.messageId,\n createdAt: row.createdAt,\n };\n }\n\n async listCheckpoints(chatId: string): Promise<CheckpointInfo[]> {\n const rows = this.#db\n .prepare(\n `SELECT id, name, messageId, createdAt\n FROM checkpoints\n WHERE chatId = ?\n ORDER BY createdAt DESC`,\n )\n .all(chatId) as {\n id: string;\n name: string;\n messageId: string;\n createdAt: number;\n }[];\n\n return rows.map((row) => ({\n id: row.id,\n name: row.name,\n messageId: row.messageId,\n createdAt: row.createdAt,\n }));\n }\n\n async deleteCheckpoint(chatId: string, name: string): Promise<void> {\n this.#db\n .prepare('DELETE FROM checkpoints WHERE chatId = ? AND name = ?')\n .run(chatId, name);\n }\n\n // ==========================================================================\n // Search Operations\n // ==========================================================================\n\n async searchMessages(\n chatId: string,\n query: string,\n options?: SearchOptions,\n ): Promise<SearchResult[]> {\n const limit = options?.limit ?? 20;\n const roles = options?.roles;\n\n // Build the query dynamically based on options\n let sql = `\n SELECT\n m.id,\n m.chatId,\n m.parentId,\n m.name,\n m.type,\n m.data,\n m.createdAt,\n fts.rank,\n snippet(messages_fts, 3, '<mark>', '</mark>', '...', 32) as snippet\n FROM messages_fts fts\n JOIN messages m ON m.id = fts.messageId\n WHERE messages_fts MATCH ?\n AND fts.chatId = ?\n `;\n\n const params: SQLInputValue[] = [query, chatId];\n\n if (roles && roles.length > 0) {\n const placeholders = roles.map(() => '?').join(', ');\n sql += ` AND fts.name IN (${placeholders})`;\n params.push(...roles);\n }\n\n sql += ' ORDER BY fts.rank LIMIT ?';\n params.push(limit);\n\n const rows = this.#db.prepare(sql).all(...params) as {\n id: string;\n chatId: string;\n parentId: string | null;\n name: string;\n type: string | null;\n data: string;\n createdAt: number;\n rank: number;\n snippet: string;\n }[];\n\n return rows.map((row) => ({\n message: {\n id: row.id,\n chatId: row.chatId,\n parentId: row.parentId,\n name: row.name,\n type: row.type ?? undefined,\n data: JSON.parse(row.data),\n createdAt: row.createdAt,\n },\n rank: row.rank,\n snippet: row.snippet,\n }));\n }\n\n // ==========================================================================\n // Visualization Operations\n // ==========================================================================\n\n async getGraph(chatId: string): Promise<GraphData> {\n // Get all messages for complete graph\n const messageRows = this.#db\n .prepare(\n `SELECT id, parentId, name, data, createdAt\n FROM messages\n WHERE chatId = ?\n ORDER BY createdAt ASC`,\n )\n .all(chatId) as {\n id: string;\n parentId: string | null;\n name: string;\n data: string;\n createdAt: number;\n }[];\n\n const nodes: GraphNode[] = messageRows.map((row) => {\n const data = JSON.parse(row.data);\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n id: row.id,\n parentId: row.parentId,\n role: row.name,\n content: content.length > 50 ? content.slice(0, 50) + '...' : content,\n createdAt: row.createdAt,\n };\n });\n\n // Get all branches\n const branchRows = this.#db\n .prepare(\n `SELECT name, headMessageId, isActive\n FROM branches\n WHERE chatId = ?\n ORDER BY createdAt ASC`,\n )\n .all(chatId) as {\n name: string;\n headMessageId: string | null;\n isActive: number;\n }[];\n\n const branches: GraphBranch[] = branchRows.map((row) => ({\n name: row.name,\n headMessageId: row.headMessageId,\n isActive: row.isActive === 1,\n }));\n\n // Get all checkpoints\n const checkpointRows = this.#db\n .prepare(\n `SELECT name, messageId\n FROM checkpoints\n WHERE chatId = ?\n ORDER BY createdAt ASC`,\n )\n .all(chatId) as {\n name: string;\n messageId: string;\n }[];\n\n const checkpoints: GraphCheckpoint[] = checkpointRows.map((row) => ({\n name: row.name,\n messageId: row.messageId,\n }));\n\n return {\n chatId,\n nodes,\n branches,\n checkpoints,\n };\n }\n}\n", "import { SqliteContextStore } from './sqlite.store.ts';\n\n/**\n * In-memory context store.\n *\n * Uses SQLite's :memory: database for non-persistent storage.\n * Useful for testing and short-lived sessions.\n */\nexport class InMemoryContextStore extends SqliteContextStore {\n constructor() {\n super(':memory:');\n }\n}\n", "import type { GraphData, GraphNode } from './store/store.ts';\n\n/**\n * Render a graph as ASCII art.\n *\n * @param data - The graph data to visualize\n * @returns ASCII art representation of the graph\n *\n * @example\n * ```ts\n * const graph = await store.getGraph('my-chat');\n * console.log(visualizeGraph(graph));\n * ```\n */\nexport function visualizeGraph(data: GraphData): string {\n if (data.nodes.length === 0) {\n return `[chat: ${data.chatId}]\\n\\n(empty)`;\n }\n\n // Build lookup maps\n const childrenByParentId = new Map<string | null, GraphNode[]>();\n const branchHeads = new Map<string, string[]>(); // messageId -> branch names\n const checkpointsByMessageId = new Map<string, string[]>(); // messageId -> checkpoint names\n\n for (const node of data.nodes) {\n const children = childrenByParentId.get(node.parentId) ?? [];\n children.push(node);\n childrenByParentId.set(node.parentId, children);\n }\n\n for (const branch of data.branches) {\n if (branch.headMessageId) {\n const heads = branchHeads.get(branch.headMessageId) ?? [];\n heads.push(branch.isActive ? `${branch.name} *` : branch.name);\n branchHeads.set(branch.headMessageId, heads);\n }\n }\n\n for (const checkpoint of data.checkpoints) {\n const cps = checkpointsByMessageId.get(checkpoint.messageId) ?? [];\n cps.push(checkpoint.name);\n checkpointsByMessageId.set(checkpoint.messageId, cps);\n }\n\n // Find root nodes (parentId === null)\n const roots = childrenByParentId.get(null) ?? [];\n\n const lines: string[] = [`[chat: ${data.chatId}]`, ''];\n\n // Recursively render the tree\n function renderNode(\n node: GraphNode,\n prefix: string,\n isLast: boolean,\n isRoot: boolean,\n ): void {\n const connector = isRoot ? '' : isLast ? '\u2514\u2500\u2500 ' : '\u251C\u2500\u2500 ';\n const contentPreview = node.content.replace(/\\n/g, ' ');\n\n let line = `${prefix}${connector}${node.id.slice(0, 8)} (${node.role}): \"${contentPreview}\"`;\n\n // Add branch markers\n const branches = branchHeads.get(node.id);\n if (branches) {\n line += ` <- [${branches.join(', ')}]`;\n }\n\n // Add checkpoint markers\n const checkpoints = checkpointsByMessageId.get(node.id);\n if (checkpoints) {\n line += ` {${checkpoints.join(', ')}}`;\n }\n\n lines.push(line);\n\n // Render children\n const children = childrenByParentId.get(node.id) ?? [];\n const childPrefix = isRoot ? '' : prefix + (isLast ? ' ' : '\u2502 ');\n\n for (let i = 0; i < children.length; i++) {\n renderNode(children[i], childPrefix, i === children.length - 1, false);\n }\n }\n\n // Render each root\n for (let i = 0; i < roots.length; i++) {\n renderNode(roots[i], '', i === roots.length - 1, true);\n }\n\n // Add legend\n lines.push('');\n lines.push('Legend: * = active branch, {...} = checkpoint');\n\n return lines.join('\\n');\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { type UIMessage, generateId } from 'ai';\n\nimport type { ContextFragment } from './lib/context.ts';\nimport { isMessageFragment } from './lib/context.ts';\nimport {\n type EstimateResult,\n type FragmentEstimate,\n getModelsRegistry,\n} from './lib/estimate.ts';\nimport type { Models } from './lib/models.generated.ts';\nimport {\n type ContextRenderer,\n XmlRenderer,\n} from './lib/renderers/abstract.renderer.ts';\nimport {\n type BranchData,\n type BranchInfo,\n type ChatData,\n type CheckpointData,\n type CheckpointInfo,\n ContextStore,\n type GraphData,\n type MessageData,\n type StoredChatData,\n} from './lib/store/store.ts';\n\nexport type { FragmentCodec } from './lib/codec.ts';\nexport { isMessageFragment } from './lib/context.ts';\nexport type { ContextFragment, FragmentType } from './lib/context.ts';\nexport { InMemoryContextStore } from './lib/store/memory.store.ts';\nexport { SqliteContextStore } from './lib/store/sqlite.store.ts';\nexport {\n ContextStore,\n type BranchData,\n type BranchInfo,\n type ChatData,\n type ChatInfo,\n type CheckpointData,\n type CheckpointInfo,\n type GraphBranch,\n type GraphCheckpoint,\n type GraphData,\n type GraphNode,\n type MessageData,\n type MessageInfo,\n type SearchOptions,\n type SearchResult,\n type StoredChatData,\n} from './lib/store/store.ts';\nexport { visualizeGraph } from './lib/visualize.ts';\n\n/**\n * Result of resolving context - ready for AI SDK consumption.\n */\nexport interface ResolveResult {\n /** Rendered non-message fragments for system prompt */\n systemPrompt: string;\n /** Message fragments decoded to AI SDK format */\n messages: unknown[];\n}\n\n/**\n * Options for resolve().\n */\nexport interface ResolveOptions {\n /** Renderer to use for system prompt (defaults to XmlRenderer) */\n renderer: ContextRenderer;\n}\n\n/**\n * Options for creating a ContextEngine.\n */\nexport interface ContextEngineOptions {\n /** Store for persisting fragments (required) */\n store: ContextStore;\n /** Unique identifier for this chat (required) */\n chatId: string;\n /** Branch name (defaults to 'main') */\n branch?: string;\n}\n\n/**\n * Options for creating message fragments.\n */\nexport interface MessageOptions {\n /** Custom ID for the fragment. If not provided, auto-generates UUID. */\n id?: string;\n}\n\n/**\n * Metadata about a chat.\n */\nexport interface ChatMeta {\n /** Unique chat identifier */\n id: string;\n /** When the chat was created */\n createdAt: number;\n /** When the chat was last updated */\n updatedAt: number;\n /** Optional user-provided title */\n title?: string;\n /** Optional custom metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Options for context inspection.\n */\nexport interface InspectOptions {\n /** Model ID for cost estimation (required) */\n modelId: Models;\n /** Renderer for estimation (required) */\n renderer: ContextRenderer;\n}\n\n/**\n * Result of inspecting context state.\n * Provides a comprehensive JSON-serializable snapshot for debugging.\n */\nexport interface InspectResult {\n /** Token usage and cost estimation */\n estimate: EstimateResult;\n /** Rendered output using the provided renderer */\n rendered: string;\n /** Fragment structure breakdown */\n fragments: {\n /** Non-message fragments (role, hints, etc.) */\n context: ContextFragment[];\n /** Pending messages not yet saved to store */\n pending: ContextFragment[];\n /** Persisted messages from the store */\n persisted: MessageData[];\n };\n /** Conversation graph with branches and checkpoints */\n graph: GraphData;\n /** Inspection metadata */\n meta: {\n chatId: string;\n branch: string;\n timestamp: number;\n };\n}\n\nexport {\n ModelsRegistry,\n defaultTokenizer,\n estimate,\n getModelsRegistry,\n type EstimateResult,\n type FragmentEstimate,\n type ModelCost,\n type ModelInfo,\n type Tokenizer,\n} from './lib/estimate.ts';\nexport type { KnownModels, Models } from './lib/models.generated.ts';\nexport {\n MarkdownRenderer,\n TomlRenderer,\n ToonRenderer,\n XmlRenderer,\n type ContextRenderer,\n type RendererOptions,\n} from './lib/renderers/abstract.renderer.ts';\n\n/**\n * Context engine for managing AI conversation context with graph-based storage.\n *\n * The engine uses a DAG (Directed Acyclic Graph) model for messages:\n * - Messages are immutable nodes with parentId forming the graph\n * - Branches are pointers to head (tip) messages\n * - Checkpoints are pointers to specific messages\n * - History is preserved through branching (rewind creates new branch)\n */\nexport class ContextEngine {\n /** Non-message fragments (role, hints, etc.) - not persisted in graph */\n #fragments: ContextFragment[] = [];\n /** Pending message fragments to be added to graph */\n #pendingMessages: ContextFragment[] = [];\n #store: ContextStore;\n #chatId: string;\n #branchName: string;\n #branch: BranchData | null = null;\n #chatData: StoredChatData | null = null;\n #initialized = false;\n\n constructor(options: ContextEngineOptions) {\n if (!options.chatId) {\n throw new Error('chatId is required');\n }\n this.#store = options.store;\n this.#chatId = options.chatId;\n this.#branchName = options.branch ?? 'main';\n }\n\n /**\n * Initialize the chat and branch if they don't exist.\n */\n async #ensureInitialized(): Promise<void> {\n if (this.#initialized) {\n return;\n }\n\n this.#chatData = await this.#store.upsertChat({ id: this.#chatId });\n\n const existingBranch = await this.#store.getBranch(\n this.#chatId,\n this.#branchName,\n );\n if (existingBranch) {\n this.#branch = existingBranch;\n } else {\n this.#branch = {\n id: crypto.randomUUID(),\n chatId: this.#chatId,\n name: this.#branchName,\n headMessageId: null,\n isActive: true,\n createdAt: Date.now(),\n };\n await this.#store.createBranch(this.#branch);\n }\n\n this.#initialized = true;\n }\n\n /**\n * Create a new branch from a specific message.\n * Shared logic between rewind() and btw().\n */\n async #createBranchFrom(\n messageId: string,\n switchTo: boolean,\n ): Promise<BranchInfo> {\n // Generate branch name based on same-prefix count (e.g., main-v2, main-v3)\n const branches = await this.#store.listBranches(this.#chatId);\n const samePrefix = branches.filter(\n (b) =>\n b.name === this.#branchName ||\n b.name.startsWith(`${this.#branchName}-v`),\n );\n const newBranchName = `${this.#branchName}-v${samePrefix.length + 1}`;\n\n // Create new branch pointing to the target message\n const newBranch: BranchData = {\n id: crypto.randomUUID(),\n chatId: this.#chatId,\n name: newBranchName,\n headMessageId: messageId,\n isActive: false,\n createdAt: Date.now(),\n };\n await this.#store.createBranch(newBranch);\n\n if (switchTo) {\n // Switch to the new branch\n await this.#store.setActiveBranch(this.#chatId, newBranch.id);\n this.#branch = { ...newBranch, isActive: true };\n this.#branchName = newBranchName;\n // Clear pending messages (they were for the old branch)\n this.#pendingMessages = [];\n }\n\n // Get message count for branch info\n const chain = await this.#store.getMessageChain(messageId);\n\n return {\n id: newBranch.id,\n name: newBranch.name,\n headMessageId: newBranch.headMessageId,\n isActive: switchTo,\n messageCount: chain.length,\n createdAt: newBranch.createdAt,\n };\n }\n\n /**\n * Get the current chat ID.\n */\n public get chatId(): string {\n return this.#chatId;\n }\n\n /**\n * Get the current branch name.\n */\n public get branch(): string {\n return this.#branchName;\n }\n\n /**\n * Get metadata for the current chat.\n * Returns null if the chat hasn't been initialized yet.\n */\n public get chat(): ChatMeta | null {\n if (!this.#chatData) {\n return null;\n }\n return {\n id: this.#chatData.id,\n createdAt: this.#chatData.createdAt,\n updatedAt: this.#chatData.updatedAt,\n title: this.#chatData.title,\n metadata: this.#chatData.metadata,\n };\n }\n\n /**\n * Add fragments to the context.\n *\n * - Message fragments (user/assistant) are queued for persistence\n * - Non-message fragments (role/hint) are kept in memory for system prompt\n */\n public set(...fragments: ContextFragment[]) {\n for (const fragment of fragments) {\n if (isMessageFragment(fragment)) {\n this.#pendingMessages.push(fragment);\n } else {\n this.#fragments.push(fragment);\n }\n }\n return this;\n }\n\n /**\n * Render all fragments using the provided renderer.\n * @internal Use resolve() instead for public API.\n */\n public render(renderer: ContextRenderer) {\n return renderer.render(this.#fragments);\n }\n\n /**\n * Resolve context into AI SDK-ready format.\n *\n * - Initializes chat and branch if needed\n * - Loads message history from the graph (walking parent chain)\n * - Separates context fragments for system prompt\n * - Combines with pending messages\n *\n * @example\n * ```ts\n * const context = new ContextEngine({ store, chatId: 'chat-1' })\n * .set(role('You are helpful'), user('Hello'));\n *\n * const { systemPrompt, messages } = await context.resolve();\n * await generateText({ system: systemPrompt, messages });\n * ```\n */\n public async resolve(options: ResolveOptions): Promise<ResolveResult> {\n await this.#ensureInitialized();\n\n const systemPrompt = options.renderer.render(this.#fragments);\n\n // Get persisted messages from graph\n const messages: unknown[] = [];\n if (this.#branch?.headMessageId) {\n const chain = await this.#store.getMessageChain(\n this.#branch.headMessageId,\n );\n\n for (const msg of chain) {\n messages.push(message(msg.data as never).codec?.decode());\n }\n }\n\n // Add pending messages (not yet saved)\n for (const fragment of this.#pendingMessages) {\n const decoded = fragment.codec!.decode();\n messages.push(decoded);\n }\n\n return { systemPrompt, messages };\n }\n\n /**\n * Save pending messages to the graph.\n *\n * Each message is added as a node with parentId pointing to the previous message.\n * The branch head is updated to point to the last message.\n *\n * @example\n * ```ts\n * context.set(user('Hello'));\n * // AI responds...\n * context.set(assistant('Hi there!'));\n * await context.save(); // Persist to graph\n * ```\n */\n public async save(): Promise<void> {\n await this.#ensureInitialized();\n\n if (this.#pendingMessages.length === 0) {\n return;\n }\n\n let parentId = this.#branch!.headMessageId;\n const now = Date.now();\n\n // Add each pending message to the graph\n for (const fragment of this.#pendingMessages) {\n const messageData: MessageData = {\n id: fragment.id ?? crypto.randomUUID(),\n chatId: this.#chatId,\n parentId,\n name: fragment.name,\n type: fragment.type,\n data: fragment.codec!.encode(),\n createdAt: now,\n };\n\n await this.#store.addMessage(messageData);\n parentId = messageData.id;\n }\n\n // Update branch head to last message\n await this.#store.updateBranchHead(this.#branch!.id, parentId);\n this.#branch!.headMessageId = parentId;\n\n // Clear pending messages\n this.#pendingMessages = [];\n }\n\n /**\n * Estimate token count and cost for the full context.\n *\n * Includes:\n * - System prompt fragments (role, hints, etc.)\n * - Persisted chat messages (from store)\n * - Pending messages (not yet saved)\n *\n * @param modelId - Model ID (e.g., \"openai:gpt-4o\", \"anthropic:claude-3-5-sonnet\")\n * @param options - Optional settings\n * @returns Estimate result with token counts, costs, and per-fragment breakdown\n */\n public async estimate(\n modelId: Models,\n options: {\n renderer?: ContextRenderer;\n } = {},\n ): Promise<EstimateResult> {\n await this.#ensureInitialized();\n\n const renderer = options.renderer ?? new XmlRenderer();\n const registry = getModelsRegistry();\n await registry.load();\n\n const model = registry.get(modelId);\n if (!model) {\n throw new Error(\n `Model \"${modelId}\" not found. Call load() first or check model ID.`,\n );\n }\n\n const tokenizer = registry.getTokenizer(modelId);\n const fragmentEstimates: FragmentEstimate[] = [];\n\n // 1. Estimate context fragments (system prompt)\n for (const fragment of this.#fragments) {\n const rendered = renderer.render([fragment]);\n const tokens = tokenizer.count(rendered);\n const cost = (tokens / 1_000_000) * model.cost.input;\n fragmentEstimates.push({\n id: fragment.id,\n name: fragment.name,\n tokens,\n cost,\n });\n }\n\n // 2. Estimate persisted messages from store\n if (this.#branch?.headMessageId) {\n const chain = await this.#store.getMessageChain(\n this.#branch.headMessageId,\n );\n for (const msg of chain) {\n const content = String(msg.data);\n const tokens = tokenizer.count(content);\n const cost = (tokens / 1_000_000) * model.cost.input;\n fragmentEstimates.push({\n name: msg.name,\n id: msg.id,\n tokens,\n cost,\n });\n }\n }\n\n // 3. Estimate pending messages (not yet saved)\n for (const fragment of this.#pendingMessages) {\n const content = String(fragment.data);\n const tokens = tokenizer.count(content);\n const cost = (tokens / 1_000_000) * model.cost.input;\n fragmentEstimates.push({\n name: fragment.name,\n id: fragment.id,\n tokens,\n cost,\n });\n }\n\n // Calculate totals\n const totalTokens = fragmentEstimates.reduce((sum, f) => sum + f.tokens, 0);\n const totalCost = fragmentEstimates.reduce((sum, f) => sum + f.cost, 0);\n\n return {\n model: model.id,\n provider: model.provider,\n tokens: totalTokens,\n cost: totalCost,\n limits: {\n context: model.limit.context,\n output: model.limit.output,\n exceedsContext: totalTokens > model.limit.context,\n },\n fragments: fragmentEstimates,\n };\n }\n\n /**\n * Rewind to a specific message by ID.\n *\n * Creates a new branch from that message, preserving the original branch.\n * The new branch becomes active.\n *\n * @param messageId - The message ID to rewind to\n * @returns The new branch info\n *\n * @example\n * ```ts\n * context.set(user('What is 2 + 2?', { id: 'q1' }));\n * context.set(assistant('The answer is 5.', { id: 'wrong' })); // Oops!\n * await context.save();\n *\n * // Rewind to the question, creates new branch\n * const newBranch = await context.rewind('q1');\n *\n * // Now add correct answer on new branch\n * context.set(assistant('The answer is 4.'));\n * await context.save();\n * ```\n */\n public async rewind(messageId: string): Promise<BranchInfo> {\n await this.#ensureInitialized();\n\n // Verify the message exists\n const message = await this.#store.getMessage(messageId);\n if (!message) {\n throw new Error(`Message \"${messageId}\" not found`);\n }\n if (message.chatId !== this.#chatId) {\n throw new Error(`Message \"${messageId}\" belongs to a different chat`);\n }\n\n return this.#createBranchFrom(messageId, true);\n }\n\n /**\n * Create a checkpoint at the current position.\n *\n * A checkpoint is a named pointer to the current branch head.\n * Use restore() to return to this point later.\n *\n * @param name - Name for the checkpoint\n * @returns The checkpoint info\n *\n * @example\n * ```ts\n * context.set(user('I want to learn a new skill.'));\n * context.set(assistant('Would you like coding or cooking?'));\n * await context.save();\n *\n * // Save checkpoint before user's choice\n * const cp = await context.checkpoint('before-choice');\n * ```\n */\n public async checkpoint(name: string): Promise<CheckpointInfo> {\n await this.#ensureInitialized();\n\n if (!this.#branch?.headMessageId) {\n throw new Error('Cannot create checkpoint: no messages in conversation');\n }\n\n const checkpoint: CheckpointData = {\n id: crypto.randomUUID(),\n chatId: this.#chatId,\n name,\n messageId: this.#branch.headMessageId,\n createdAt: Date.now(),\n };\n\n await this.#store.createCheckpoint(checkpoint);\n\n return {\n id: checkpoint.id,\n name: checkpoint.name,\n messageId: checkpoint.messageId,\n createdAt: checkpoint.createdAt,\n };\n }\n\n /**\n * Restore to a checkpoint by creating a new branch from that point.\n *\n * @param name - Name of the checkpoint to restore\n * @returns The new branch info\n *\n * @example\n * ```ts\n * // User chose cooking, but wants to try coding path\n * await context.restore('before-choice');\n *\n * context.set(user('I want to learn coding.'));\n * context.set(assistant('Python is a great starting language!'));\n * await context.save();\n * ```\n */\n public async restore(name: string): Promise<BranchInfo> {\n await this.#ensureInitialized();\n\n const checkpoint = await this.#store.getCheckpoint(this.#chatId, name);\n if (!checkpoint) {\n throw new Error(\n `Checkpoint \"${name}\" not found in chat \"${this.#chatId}\"`,\n );\n }\n\n // Rewind to the checkpoint's message\n return this.rewind(checkpoint.messageId);\n }\n\n /**\n * Switch to a different branch by name.\n *\n * @param name - Branch name to switch to\n *\n * @example\n * ```ts\n * // List branches (via store)\n * const branches = await store.listBranches(context.chatId);\n * console.log(branches); // [{name: 'main', ...}, {name: 'main-v2', ...}]\n *\n * // Switch to original branch\n * await context.switchBranch('main');\n * ```\n */\n public async switchBranch(name: string): Promise<void> {\n await this.#ensureInitialized();\n\n const branch = await this.#store.getBranch(this.#chatId, name);\n if (!branch) {\n throw new Error(`Branch \"${name}\" not found in chat \"${this.#chatId}\"`);\n }\n\n await this.#store.setActiveBranch(this.#chatId, branch.id);\n this.#branch = { ...branch, isActive: true };\n this.#branchName = name;\n\n // Clear pending messages (they were for the old branch)\n this.#pendingMessages = [];\n }\n\n /**\n * Create a parallel branch from the current position (\"by the way\").\n *\n * Use this when you want to fork the conversation without leaving\n * the current branch. Common use case: user wants to ask another\n * question while waiting for the model to respond.\n *\n * Unlike rewind(), this method:\n * - Uses the current HEAD (no messageId needed)\n * - Does NOT switch to the new branch\n * - Keeps pending messages intact\n *\n * @returns The new branch info (does not switch to it)\n * @throws Error if no messages exist in the conversation\n *\n * @example\n * ```ts\n * // User asked a question, model is generating...\n * context.set(user('What is the weather?'));\n * await context.save();\n *\n * // User wants to ask something else without waiting\n * const newBranch = await context.btw();\n * // newBranch = { name: 'main-v2', ... }\n *\n * // Later, switch to the new branch and add the question\n * await context.switchBranch(newBranch.name);\n * context.set(user('Also, what time is it?'));\n * await context.save();\n * ```\n */\n public async btw(): Promise<BranchInfo> {\n await this.#ensureInitialized();\n\n if (!this.#branch?.headMessageId) {\n throw new Error('Cannot create btw branch: no messages in conversation');\n }\n\n return this.#createBranchFrom(this.#branch.headMessageId, false);\n }\n\n /**\n * Update metadata for the current chat.\n *\n * @param updates - Partial metadata to merge (title, metadata)\n *\n * @example\n * ```ts\n * await context.updateChat({\n * title: 'Coding Help Session',\n * metadata: { tags: ['python', 'debugging'] }\n * });\n * ```\n */\n public async updateChat(\n updates: Partial<Pick<ChatMeta, 'title' | 'metadata'>>,\n ): Promise<void> {\n await this.#ensureInitialized();\n\n const storeUpdates: Partial<Pick<ChatData, 'title' | 'metadata'>> = {};\n\n if (updates.title !== undefined) {\n storeUpdates.title = updates.title;\n }\n if (updates.metadata !== undefined) {\n // Merge with existing metadata\n storeUpdates.metadata = {\n ...this.#chatData?.metadata,\n ...updates.metadata,\n };\n }\n\n this.#chatData = await this.#store.updateChat(this.#chatId, storeUpdates);\n }\n\n /**\n * Consolidate context fragments (no-op for now).\n *\n * This is a placeholder for future functionality that merges context fragments\n * using specific rules. Currently, it does nothing.\n *\n * @experimental\n */\n public consolidate(): void {\n return void 0;\n }\n\n /**\n * Inspect the full context state for debugging.\n * Returns a comprehensive JSON-serializable object with all context information.\n *\n * @param options - Inspection options (modelId and renderer required)\n * @returns Complete inspection data including estimates, rendered output, fragments, and graph\n *\n * @example\n * ```ts\n * const inspection = await context.inspect({\n * modelId: 'openai:gpt-4o',\n * renderer: new XmlRenderer(),\n * });\n * console.log(JSON.stringify(inspection, null, 2));\n *\n * // Or write to file for analysis\n * await fs.writeFile('context-debug.json', JSON.stringify(inspection, null, 2));\n * ```\n */\n public async inspect(options: InspectOptions): Promise<InspectResult> {\n await this.#ensureInitialized();\n\n const { renderer } = options;\n\n // Get token/cost estimation\n const estimateResult = await this.estimate(options.modelId, { renderer });\n\n // Render using provided renderer\n const rendered = renderer.render(this.#fragments);\n\n // Get persisted messages from store\n const persistedMessages: MessageData[] = [];\n if (this.#branch?.headMessageId) {\n const chain = await this.#store.getMessageChain(\n this.#branch.headMessageId,\n );\n persistedMessages.push(...chain);\n }\n\n // Get conversation graph\n const graph = await this.#store.getGraph(this.#chatId);\n\n return {\n estimate: estimateResult,\n rendered,\n fragments: {\n context: [...this.#fragments],\n pending: [...this.#pendingMessages],\n persisted: persistedMessages,\n },\n graph,\n meta: {\n chatId: this.#chatId,\n branch: this.#branchName,\n timestamp: Date.now(),\n },\n };\n }\n}\n\nexport function hint(text: string): ContextFragment {\n return {\n name: 'hint',\n data: text,\n };\n}\n\nexport function fragment(\n name: string,\n ...children: ContextFragment[]\n): ContextFragment {\n return {\n name,\n data: children,\n };\n}\n\n/**\n * Create a role fragment for system prompt instructions.\n */\nexport function role(content: string): ContextFragment {\n return {\n name: 'role',\n data: content,\n };\n}\n\n/**\n * Create a user message fragment.\n * Message fragments are separated from regular fragments during resolve().\n *\n * @param content - The message content\n * @param options - Optional settings (id)\n *\n * @example\n * ```ts\n * context.set(user('Hello')); // Auto-generated ID\n * context.set(user('Hello', { id: 'msg-1' })); // Custom ID\n * ```\n */\nexport function user(content: string | UIMessage): ContextFragment {\n const message =\n typeof content === 'string'\n ? {\n id: generateId(),\n role: 'user',\n parts: [{ type: 'text', text: content }],\n }\n : content;\n return {\n id: message.id,\n name: 'user',\n data: 'content',\n type: 'message',\n persist: true,\n codec: {\n decode() {\n return message;\n },\n encode() {\n return message;\n },\n },\n };\n}\n\n/**\n * Create an assistant message fragment.\n * Message fragments are separated from regular fragments during resolve().\n *\n * @param message - The message content\n * @param options - Optional settings (id)\n *\n * @example\n * ```ts\n * context.set(assistant('Hi there!')); // Auto-generated ID\n * context.set(assistant('Hi there!', { id: 'resp-1' })); // Custom ID\n * ```\n */\nexport function assistant(message: UIMessage): ContextFragment {\n return {\n id: message.id,\n name: 'assistant',\n data: 'content',\n type: 'message',\n persist: true,\n codec: {\n decode() {\n return message;\n },\n encode() {\n return message;\n },\n },\n };\n}\nexport function message(content: string | UIMessage): ContextFragment {\n const message =\n typeof content === 'string'\n ? {\n id: generateId(),\n role: 'user',\n parts: [{ type: 'text', text: content }],\n }\n : content;\n return {\n id: message.id,\n name: 'message',\n data: 'content',\n type: 'message',\n persist: true,\n codec: {\n decode() {\n return message;\n },\n encode() {\n return message;\n },\n },\n };\n}\n\n/**\n * Create an assistant message fragment from text content.\n * Convenience wrapper that creates a UIMessage internally.\n *\n * @param content - The message text content\n * @param options - Optional settings (id)\n *\n * @example\n * ```ts\n * context.set(assistantText('Hi there!')); // Auto-generated ID\n * context.set(assistantText('Hi there!', { id: 'resp-1' })); // Custom ID\n * ```\n */\nexport function assistantText(\n content: string,\n options?: MessageOptions,\n): ContextFragment {\n const id = options?.id ?? crypto.randomUUID();\n return assistant({\n id,\n role: 'assistant',\n parts: [{ type: 'text', text: content }],\n });\n}\n", "import type { FragmentCodec } from './codec.ts';\n\n/**\n * Fragment type identifier.\n * - 'fragment': Regular context fragment (default)\n * - 'message': Conversation message (user/assistant)\n */\nexport type FragmentType = 'fragment' | 'message';\n\n/**\n * A context fragment containing a name and associated data.\n */\nexport interface ContextFragment {\n /**\n * Unique identifier for this fragment.\n * Auto-generated for user/assistant messages, optional for other fragments.\n */\n id?: string;\n name: string;\n data: FragmentData;\n /**\n * Fragment type for categorization.\n * Messages use 'message' type and are handled separately during resolve().\n */\n type?: FragmentType;\n /**\n * When true, this fragment will be persisted to the store on save().\n */\n persist?: boolean;\n /**\n * Codec for encoding/decoding this fragment.\n * Used by resolve() to convert to AI SDK format.\n */\n codec?: FragmentCodec;\n}\n\n/**\n * Fragment data can be a primitive, array, object, or nested fragment.\n */\nexport type FragmentData =\n | string\n | number\n | boolean\n | ContextFragment\n | FragmentData[]\n | { [key: string]: FragmentData };\n\n/**\n * Type guard to check if data is a ContextFragment.\n */\nexport function isFragment(data: unknown): data is ContextFragment {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'name' in data &&\n 'data' in data &&\n typeof (data as ContextFragment).name === 'string'\n );\n}\n\n/**\n * A plain object with string keys and FragmentData values.\n */\nexport type FragmentObject = Record<string, FragmentData>;\n\n/**\n * Type guard to check if data is a plain object (not array, not fragment, not primitive).\n */\nexport function isFragmentObject(data: unknown): data is FragmentObject {\n return (\n typeof data === 'object' &&\n data !== null &&\n !Array.isArray(data) &&\n !isFragment(data)\n );\n}\n\n/**\n * Type guard to check if a fragment is a message fragment.\n */\nexport function isMessageFragment(fragment: ContextFragment): boolean {\n return fragment.type === 'message';\n}\n", "import { encode } from 'gpt-tokenizer';\n\nimport type { ContextFragment } from './context.ts';\nimport type { Models } from './models.generated.ts';\nimport type { ContextRenderer } from './renderers/abstract.renderer.ts';\n\n/**\n * Cost information for a model (prices per 1M tokens)\n */\nexport interface ModelCost {\n input: number;\n output: number;\n cache_read?: number;\n cache_write?: number;\n reasoning?: number;\n}\n\n/**\n * Model information from models.dev\n */\nexport interface ModelInfo {\n id: string;\n name: string;\n family: string;\n cost: ModelCost;\n limit: {\n context: number;\n output: number;\n };\n provider: string;\n}\n\n/**\n * Estimate for a single fragment\n */\nexport interface FragmentEstimate {\n name: string;\n id?: string;\n tokens: number;\n cost: number;\n}\n\n/**\n * Estimate result returned by the estimate function\n */\nexport interface EstimateResult {\n model: string;\n provider: string;\n tokens: number;\n cost: number;\n limits: {\n context: number;\n output: number;\n exceedsContext: boolean;\n };\n fragments: FragmentEstimate[];\n}\n\n/**\n * Tokenizer interface for counting tokens\n */\nexport interface Tokenizer {\n encode(text: string): number[];\n count(text: string): number;\n}\n\n/**\n * Default tokenizer using gpt-tokenizer\n * Works reasonably well for most models (~5-10% variance)\n */\nexport const defaultTokenizer: Tokenizer = {\n encode(text: string): number[] {\n return encode(text);\n },\n count(text: string): number {\n return encode(text).length;\n },\n};\n\ntype ModelsDevResponse = Record<\n string,\n {\n id: string;\n name: string;\n models: Record<\n string,\n {\n id: string;\n name: string;\n family: string;\n cost: ModelCost;\n limit: { context: number; output: number };\n }\n >;\n }\n>;\n\n/**\n * Registry for AI model information from models.dev\n * Caches data and provides lookup by model ID\n */\nexport class ModelsRegistry {\n #cache: Map<string, ModelInfo> = new Map();\n #loaded = false;\n #tokenizers: Map<string, Tokenizer> = new Map();\n #defaultTokenizer: Tokenizer = defaultTokenizer;\n\n /**\n * Load models data from models.dev API\n */\n async load(): Promise<void> {\n if (this.#loaded) return;\n\n const response = await fetch('https://models.dev/api.json');\n if (!response.ok) {\n throw new Error(`Failed to fetch models: ${response.statusText}`);\n }\n\n const data = (await response.json()) as ModelsDevResponse;\n\n for (const [providerId, provider] of Object.entries(data)) {\n for (const [modelId, model] of Object.entries(provider.models)) {\n const info: ModelInfo = {\n id: model.id,\n name: model.name,\n family: model.family,\n cost: model.cost,\n limit: model.limit,\n provider: providerId,\n };\n\n // Store by full ID (provider:model)\n this.#cache.set(`${providerId}:${modelId}`, info);\n }\n }\n\n this.#loaded = true;\n }\n\n /**\n * Get model info by ID\n * @param modelId - Model ID (e.g., \"openai:gpt-4o\")\n */\n get(modelId: string): ModelInfo | undefined {\n return this.#cache.get(modelId);\n }\n\n /**\n * Check if a model exists in the registry\n */\n has(modelId: string): boolean {\n return this.#cache.has(modelId);\n }\n\n /**\n * List all available model IDs\n */\n list(): string[] {\n return [...this.#cache.keys()];\n }\n\n /**\n * Register a custom tokenizer for specific model families\n * @param family - Model family name (e.g., \"llama\", \"claude\")\n * @param tokenizer - Tokenizer implementation\n */\n registerTokenizer(family: string, tokenizer: Tokenizer): void {\n this.#tokenizers.set(family, tokenizer);\n }\n\n /**\n * Set the default tokenizer used when no family-specific tokenizer is registered\n */\n setDefaultTokenizer(tokenizer: Tokenizer): void {\n this.#defaultTokenizer = tokenizer;\n }\n\n /**\n * Get the appropriate tokenizer for a model\n */\n getTokenizer(modelId: string): Tokenizer {\n const model = this.get(modelId);\n if (model) {\n const familyTokenizer = this.#tokenizers.get(model.family);\n if (familyTokenizer) {\n return familyTokenizer;\n }\n }\n return this.#defaultTokenizer;\n }\n\n /**\n * Estimate token count and cost for given text and model\n * @param modelId - Model ID to use for pricing (e.g., \"openai:gpt-4o\")\n * @param input - Input text (prompt)\n */\n estimate(modelId: Models, input: string): EstimateResult {\n const model = this.get(modelId);\n if (!model) {\n throw new Error(\n `Model \"${modelId}\" not found. Call load() first or check model ID.`,\n );\n }\n\n const tokenizer = this.getTokenizer(modelId);\n const tokens = tokenizer.count(input);\n const cost = (tokens / 1_000_000) * model.cost.input;\n\n return {\n model: model.id,\n provider: model.provider,\n tokens,\n cost,\n limits: {\n context: model.limit.context,\n output: model.limit.output,\n exceedsContext: tokens > model.limit.context,\n },\n fragments: [],\n };\n }\n}\n\n// Singleton instance for convenience\nlet _registry: ModelsRegistry | null = null;\n\n/**\n * Get the shared ModelsRegistry instance\n */\nexport function getModelsRegistry(): ModelsRegistry {\n if (!_registry) {\n _registry = new ModelsRegistry();\n }\n return _registry;\n}\n\n/**\n * Convenience function to estimate cost for a model\n * Automatically loads the registry if not already loaded\n *\n * @param modelId - Model ID (e.g., \"openai:gpt-4o\", \"anthropic:claude-3-5-sonnet\")\n * @param renderer - Renderer to use for converting fragments to text\n * @param fragments - Context fragments to estimate\n */\nexport async function estimate(\n modelId: Models,\n renderer: ContextRenderer,\n ...fragments: ContextFragment[]\n): Promise<EstimateResult> {\n const registry = getModelsRegistry();\n await registry.load();\n\n // Calculate total (all fragments rendered together)\n const input = renderer.render(fragments);\n const model = registry.get(modelId);\n if (!model) {\n throw new Error(\n `Model \"${modelId}\" not found. Call load() first or check model ID.`,\n );\n }\n\n const tokenizer = registry.getTokenizer(modelId);\n const totalTokens = tokenizer.count(input);\n const totalCost = (totalTokens / 1_000_000) * model.cost.input;\n\n // Calculate per-fragment estimates\n const fragmentEstimates: FragmentEstimate[] = fragments.map((fragment) => {\n const rendered = renderer.render([fragment]);\n const tokens = tokenizer.count(rendered);\n const cost = (tokens / 1_000_000) * model.cost.input;\n return {\n id: fragment.id,\n name: fragment.name,\n tokens,\n cost,\n };\n });\n\n return {\n model: model.id,\n provider: model.provider,\n tokens: totalTokens,\n cost: totalCost,\n limits: {\n context: model.limit.context,\n output: model.limit.output,\n exceedsContext: totalTokens > model.limit.context,\n },\n fragments: fragmentEstimates,\n };\n}\n", "import pluralize from 'pluralize';\nimport { titlecase } from 'stringcase';\n\nimport {\n type ContextFragment,\n type FragmentData,\n type FragmentObject,\n isFragment,\n isFragmentObject,\n} from '../context.ts';\n\n/**\n * Render context passed through the template method.\n */\nexport interface RenderContext {\n depth: number;\n path: string[];\n}\n\n/**\n * Options for renderers.\n */\nexport interface RendererOptions {\n /**\n * When true, fragments with the same name are grouped under a pluralized parent tag.\n * e.g., multiple <hint> become <hints><hint>...</hint><hint>...</hint></hints>\n */\n groupFragments?: boolean;\n}\n\n/**\n * Base renderer implementing the Template Method pattern.\n * Subclasses implement the specific formatting hooks.\n */\nexport abstract class ContextRenderer {\n protected options: RendererOptions;\n\n constructor(options: RendererOptions = {}) {\n this.options = options;\n }\n\n abstract render(fragments: ContextFragment[]): string;\n\n /**\n * Check if data is a primitive (string, number, boolean).\n */\n protected isPrimitive(data: FragmentData): data is string | number | boolean {\n return (\n typeof data === 'string' ||\n typeof data === 'number' ||\n typeof data === 'boolean'\n );\n }\n\n /**\n * Group fragments by name for groupFragments option.\n */\n protected groupByName(\n fragments: ContextFragment[],\n ): Map<string, ContextFragment[]> {\n const groups = new Map<string, ContextFragment[]>();\n for (const fragment of fragments) {\n const existing = groups.get(fragment.name) ?? [];\n existing.push(fragment);\n groups.set(fragment.name, existing);\n }\n return groups;\n }\n\n /**\n * Template method - dispatches value to appropriate handler.\n */\n protected renderValue(\n key: string,\n value: unknown,\n ctx: RenderContext,\n ): string {\n if (value == null) {\n return '';\n }\n if (isFragment(value)) {\n return this.renderFragment(value, ctx);\n }\n if (Array.isArray(value)) {\n return this.renderArray(key, value, ctx);\n }\n if (isFragmentObject(value)) {\n return this.renderObject(key, value, ctx);\n }\n return this.renderPrimitive(key, String(value), ctx);\n }\n\n /**\n * Render a nested fragment - subclasses implement this.\n */\n protected abstract renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string;\n\n /**\n * Render all entries of an object.\n */\n protected renderEntries(data: FragmentObject, ctx: RenderContext): string[] {\n return Object.entries(data)\n .map(([key, value]) => this.renderValue(key, value, ctx))\n .filter(Boolean);\n }\n\n // Hooks - subclasses implement these\n protected abstract renderPrimitive(\n key: string,\n value: string,\n ctx: RenderContext,\n ): string;\n protected abstract renderArray(\n key: string,\n items: FragmentData[],\n ctx: RenderContext,\n ): string;\n protected abstract renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string;\n}\n\n/**\n * Renders context fragments as XML.\n */\nexport class XmlRenderer extends ContextRenderer {\n render(fragments: ContextFragment[]): string {\n return fragments\n .map((f) => this.#renderTopLevel(f))\n .filter(Boolean)\n .join('\\n');\n }\n\n #renderTopLevel(fragment: ContextFragment): string {\n if (this.isPrimitive(fragment.data)) {\n return this.#leafRoot(fragment.name, String(fragment.data));\n }\n if (Array.isArray(fragment.data)) {\n return this.#renderArray(fragment.name, fragment.data, 0);\n }\n if (isFragment(fragment.data)) {\n const child = this.renderFragment(fragment.data, { depth: 1, path: [] });\n return this.#wrap(fragment.name, [child]);\n }\n return this.#wrap(\n fragment.name,\n this.renderEntries(fragment.data, { depth: 1, path: [] }),\n );\n }\n\n #renderArray(name: string, items: FragmentData[], depth: number): string {\n const fragmentItems = items.filter(isFragment);\n const nonFragmentItems = items.filter((item) => !isFragment(item));\n\n const children: string[] = [];\n\n // Render non-fragment items\n for (const item of nonFragmentItems) {\n if (item != null) {\n children.push(\n this.#leaf(pluralize.singular(name), String(item), depth + 1),\n );\n }\n }\n\n // Render fragment items (possibly grouped)\n if (this.options.groupFragments && fragmentItems.length > 0) {\n const groups = this.groupByName(fragmentItems);\n for (const [groupName, groupFragments] of groups) {\n const groupChildren = groupFragments.map((frag) =>\n this.renderFragment(frag, { depth: depth + 2, path: [] }),\n );\n const pluralName = pluralize.plural(groupName);\n children.push(this.#wrapIndented(pluralName, groupChildren, depth + 1));\n }\n } else {\n for (const frag of fragmentItems) {\n children.push(\n this.renderFragment(frag, { depth: depth + 1, path: [] }),\n );\n }\n }\n\n return this.#wrap(name, children);\n }\n\n #leafRoot(tag: string, value: string): string {\n const safe = this.#escape(value);\n if (safe.includes('\\n')) {\n return `<${tag}>\\n${this.#indent(safe, 2)}\\n</${tag}>`;\n }\n return `<${tag}>${safe}</${tag}>`;\n }\n\n protected renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string {\n const { name, data } = fragment;\n if (this.isPrimitive(data)) {\n return this.#leaf(name, String(data), ctx.depth);\n }\n if (isFragment(data)) {\n const child = this.renderFragment(data, { ...ctx, depth: ctx.depth + 1 });\n return this.#wrapIndented(name, [child], ctx.depth);\n }\n if (Array.isArray(data)) {\n return this.#renderArrayIndented(name, data, ctx.depth);\n }\n const children = this.renderEntries(data, { ...ctx, depth: ctx.depth + 1 });\n return this.#wrapIndented(name, children, ctx.depth);\n }\n\n #renderArrayIndented(\n name: string,\n items: FragmentData[],\n depth: number,\n ): string {\n const fragmentItems = items.filter(isFragment);\n const nonFragmentItems = items.filter((item) => !isFragment(item));\n\n const children: string[] = [];\n\n // Render non-fragment items\n for (const item of nonFragmentItems) {\n if (item != null) {\n children.push(\n this.#leaf(pluralize.singular(name), String(item), depth + 1),\n );\n }\n }\n\n // Render fragment items (possibly grouped)\n if (this.options.groupFragments && fragmentItems.length > 0) {\n const groups = this.groupByName(fragmentItems);\n for (const [groupName, groupFragments] of groups) {\n const groupChildren = groupFragments.map((frag) =>\n this.renderFragment(frag, { depth: depth + 2, path: [] }),\n );\n const pluralName = pluralize.plural(groupName);\n children.push(this.#wrapIndented(pluralName, groupChildren, depth + 1));\n }\n } else {\n for (const frag of fragmentItems) {\n children.push(\n this.renderFragment(frag, { depth: depth + 1, path: [] }),\n );\n }\n }\n\n return this.#wrapIndented(name, children, depth);\n }\n\n protected renderPrimitive(\n key: string,\n value: string,\n ctx: RenderContext,\n ): string {\n return this.#leaf(key, value, ctx.depth);\n }\n\n protected renderArray(\n key: string,\n items: FragmentData[],\n ctx: RenderContext,\n ): string {\n if (!items.length) {\n return '';\n }\n const itemTag = pluralize.singular(key);\n const children = items\n .filter((item) => item != null)\n .map((item) => this.#leaf(itemTag, String(item), ctx.depth + 1));\n return this.#wrapIndented(key, children, ctx.depth);\n }\n\n protected renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string {\n const children = this.renderEntries(obj, { ...ctx, depth: ctx.depth + 1 });\n return this.#wrapIndented(key, children, ctx.depth);\n }\n\n #escape(value: string): string {\n if (value == null) {\n return '';\n }\n return value\n .replaceAll(/&/g, '&amp;')\n .replaceAll(/</g, '&lt;')\n .replaceAll(/>/g, '&gt;')\n .replaceAll(/\"/g, '&quot;')\n .replaceAll(/'/g, '&apos;');\n }\n\n #indent(text: string, spaces: number): string {\n if (!text.trim()) {\n return '';\n }\n const padding = ' '.repeat(spaces);\n return text\n .split('\\n')\n .map((line) => (line.length ? padding + line : padding))\n .join('\\n');\n }\n\n #leaf(tag: string, value: string, depth: number): string {\n const safe = this.#escape(value);\n const pad = ' '.repeat(depth);\n if (safe.includes('\\n')) {\n return `${pad}<${tag}>\\n${this.#indent(safe, (depth + 1) * 2)}\\n${pad}</${tag}>`;\n }\n return `${pad}<${tag}>${safe}</${tag}>`;\n }\n\n #wrap(tag: string, children: string[]): string {\n const content = children.filter(Boolean).join('\\n');\n if (!content) {\n return '';\n }\n return `<${tag}>\\n${content}\\n</${tag}>`;\n }\n\n #wrapIndented(tag: string, children: string[], depth: number): string {\n const content = children.filter(Boolean).join('\\n');\n if (!content) {\n return '';\n }\n const pad = ' '.repeat(depth);\n return `${pad}<${tag}>\\n${content}\\n${pad}</${tag}>`;\n }\n}\n\n/**\n * Renders context fragments as Markdown.\n */\nexport class MarkdownRenderer extends ContextRenderer {\n render(fragments: ContextFragment[]): string {\n return fragments\n .map((f) => {\n const title = `## ${titlecase(f.name)}`;\n if (this.isPrimitive(f.data)) {\n return `${title}\\n${String(f.data)}`;\n }\n if (Array.isArray(f.data)) {\n return `${title}\\n${this.#renderArray(f.data, 0)}`;\n }\n if (isFragment(f.data)) {\n return `${title}\\n${this.renderFragment(f.data, { depth: 0, path: [] })}`;\n }\n return `${title}\\n${this.renderEntries(f.data, { depth: 0, path: [] }).join('\\n')}`;\n })\n .join('\\n\\n');\n }\n\n #renderArray(items: FragmentData[], depth: number): string {\n const fragmentItems = items.filter(isFragment);\n const nonFragmentItems = items.filter((item) => !isFragment(item));\n\n const lines: string[] = [];\n\n // Render non-fragment items\n for (const item of nonFragmentItems) {\n if (item != null) {\n lines.push(`${this.#pad(depth)}- ${String(item)}`);\n }\n }\n\n // Render fragment items (possibly grouped)\n if (this.options.groupFragments && fragmentItems.length > 0) {\n const groups = this.groupByName(fragmentItems);\n for (const [groupName, groupFragments] of groups) {\n const pluralName = pluralize.plural(groupName);\n lines.push(`${this.#pad(depth)}- **${titlecase(pluralName)}**:`);\n for (const frag of groupFragments) {\n lines.push(this.renderFragment(frag, { depth: depth + 1, path: [] }));\n }\n }\n } else {\n for (const frag of fragmentItems) {\n lines.push(this.renderFragment(frag, { depth, path: [] }));\n }\n }\n\n return lines.join('\\n');\n }\n\n #pad(depth: number): string {\n return ' '.repeat(depth);\n }\n\n #leaf(key: string, value: string, depth: number): string {\n return `${this.#pad(depth)}- **${key}**: ${value}`;\n }\n\n #arrayItem(item: unknown, depth: number): string {\n if (isFragment(item)) {\n return this.renderFragment(item, { depth, path: [] });\n }\n if (isFragmentObject(item)) {\n return this.renderEntries(item, {\n depth,\n path: [],\n }).join('\\n');\n }\n return `${this.#pad(depth)}- ${String(item)}`;\n }\n\n protected renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string {\n const { name, data } = fragment;\n const header = `${this.#pad(ctx.depth)}- **${name}**:`;\n if (this.isPrimitive(data)) {\n return `${this.#pad(ctx.depth)}- **${name}**: ${String(data)}`;\n }\n if (isFragment(data)) {\n const child = this.renderFragment(data, { ...ctx, depth: ctx.depth + 1 });\n return [header, child].join('\\n');\n }\n if (Array.isArray(data)) {\n const children = data\n .filter((item) => item != null)\n .map((item) => this.#arrayItem(item, ctx.depth + 1));\n return [header, ...children].join('\\n');\n }\n const children = this.renderEntries(data, {\n ...ctx,\n depth: ctx.depth + 1,\n }).join('\\n');\n return [header, children].join('\\n');\n }\n\n protected renderPrimitive(\n key: string,\n value: string,\n ctx: RenderContext,\n ): string {\n return this.#leaf(key, value, ctx.depth);\n }\n\n protected renderArray(\n key: string,\n items: FragmentData[],\n ctx: RenderContext,\n ): string {\n const header = `${this.#pad(ctx.depth)}- **${key}**:`;\n const children = items\n .filter((item) => item != null)\n .map((item) => this.#arrayItem(item, ctx.depth + 1));\n return [header, ...children].join('\\n');\n }\n\n protected renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string {\n const header = `${this.#pad(ctx.depth)}- **${key}**:`;\n const children = this.renderEntries(obj, {\n ...ctx,\n depth: ctx.depth + 1,\n }).join('\\n');\n return [header, children].join('\\n');\n }\n}\n\n/**\n * Renders context fragments as TOML.\n */\nexport class TomlRenderer extends ContextRenderer {\n render(fragments: ContextFragment[]): string {\n return fragments\n .map((f) => {\n if (this.isPrimitive(f.data)) {\n return `${f.name} = ${this.#formatValue(f.data)}`;\n }\n if (Array.isArray(f.data)) {\n return this.#renderTopLevelArray(f.name, f.data);\n }\n if (isFragment(f.data)) {\n return [\n `[${f.name}]`,\n this.renderFragment(f.data, { depth: 0, path: [f.name] }),\n ].join('\\n');\n }\n const entries = this.#renderObjectEntries(f.data, [f.name]);\n return [`[${f.name}]`, ...entries].join('\\n');\n })\n .join('\\n\\n');\n }\n\n #renderTopLevelArray(name: string, items: FragmentData[]): string {\n const fragmentItems = items.filter(isFragment);\n const nonFragmentItems = items.filter(\n (item) => !isFragment(item) && item != null,\n );\n\n // If array contains fragments, render as sections\n if (fragmentItems.length > 0) {\n const parts: string[] = [`[${name}]`];\n for (const frag of fragmentItems) {\n parts.push(this.renderFragment(frag, { depth: 0, path: [name] }));\n }\n return parts.join('\\n');\n }\n\n // Otherwise render as inline array\n const values = nonFragmentItems.map((item) => this.#formatValue(item));\n return `${name} = [${values.join(', ')}]`;\n }\n\n /**\n * Override renderValue to preserve type information for TOML formatting.\n */\n protected override renderValue(\n key: string,\n value: unknown,\n ctx: RenderContext,\n ): string {\n if (value == null) {\n return '';\n }\n if (isFragment(value)) {\n return this.renderFragment(value, ctx);\n }\n if (Array.isArray(value)) {\n return this.renderArray(key, value, ctx);\n }\n if (isFragmentObject(value)) {\n return this.renderObject(key, value, ctx);\n }\n // Preserve original type for TOML formatting\n return `${key} = ${this.#formatValue(value)}`;\n }\n\n protected renderPrimitive(\n key: string,\n value: string,\n _ctx: RenderContext,\n ): string {\n return `${key} = ${this.#formatValue(value)}`;\n }\n\n protected renderArray(\n key: string,\n items: FragmentData[],\n _ctx: RenderContext,\n ): string {\n const values = items\n .filter((item) => item != null)\n .map((item) => this.#formatValue(item));\n return `${key} = [${values.join(', ')}]`;\n }\n\n protected renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string {\n const newPath = [...ctx.path, key];\n const entries = this.#renderObjectEntries(obj, newPath);\n return ['', `[${newPath.join('.')}]`, ...entries].join('\\n');\n }\n\n #renderObjectEntries(obj: FragmentObject, path: string[]): string[] {\n return Object.entries(obj)\n .map(([key, value]) => {\n if (value == null) {\n return '';\n }\n if (isFragmentObject(value)) {\n const newPath = [...path, key];\n const entries = this.#renderObjectEntries(value, newPath);\n return ['', `[${newPath.join('.')}]`, ...entries].join('\\n');\n }\n if (Array.isArray(value)) {\n const values = value\n .filter((item) => item != null)\n .map((item) => this.#formatValue(item));\n return `${key} = [${values.join(', ')}]`;\n }\n return `${key} = ${this.#formatValue(value)}`;\n })\n .filter(Boolean);\n }\n\n protected renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string {\n const { name, data } = fragment;\n const newPath = [...ctx.path, name];\n if (this.isPrimitive(data)) {\n return `${name} = ${this.#formatValue(data)}`;\n }\n if (isFragment(data)) {\n return [\n '',\n `[${newPath.join('.')}]`,\n this.renderFragment(data, { ...ctx, path: newPath }),\n ].join('\\n');\n }\n if (Array.isArray(data)) {\n const fragmentItems = data.filter(isFragment);\n const nonFragmentItems = data.filter(\n (item) => !isFragment(item) && item != null,\n );\n\n if (fragmentItems.length > 0) {\n const parts: string[] = ['', `[${newPath.join('.')}]`];\n for (const frag of fragmentItems) {\n parts.push(this.renderFragment(frag, { ...ctx, path: newPath }));\n }\n return parts.join('\\n');\n }\n\n const values = nonFragmentItems.map((item) => this.#formatValue(item));\n return `${name} = [${values.join(', ')}]`;\n }\n const entries = this.#renderObjectEntries(data, newPath);\n return ['', `[${newPath.join('.')}]`, ...entries].join('\\n');\n }\n\n #escape(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n }\n\n #formatValue(value: unknown): string {\n if (typeof value === 'string') {\n return `\"${this.#escape(value)}\"`;\n }\n if (typeof value === 'boolean' || typeof value === 'number') {\n return String(value);\n }\n if (typeof value === 'object' && value !== null) {\n return JSON.stringify(value);\n }\n return `\"${String(value)}\"`;\n }\n}\n\n/**\n * Renders context fragments as TOON (Token-Oriented Object Notation).\n * TOON is a compact, token-efficient format for LLM prompts that combines\n * YAML-like indentation with CSV-like tabular arrays.\n */\nexport class ToonRenderer extends ContextRenderer {\n render(fragments: ContextFragment[]): string {\n return fragments\n .map((f) => this.#renderTopLevel(f))\n .filter(Boolean)\n .join('\\n');\n }\n\n #renderTopLevel(fragment: ContextFragment): string {\n const { name, data } = fragment;\n if (this.isPrimitive(data)) {\n return `${name}: ${this.#formatValue(data)}`;\n }\n if (Array.isArray(data)) {\n return this.#renderArrayField(name, data, 0);\n }\n if (isFragment(data)) {\n const child = this.renderFragment(data, { depth: 1, path: [] });\n return `${name}:\\n${child}`;\n }\n if (isFragmentObject(data)) {\n const entries = this.#renderObjectEntries(data, 1);\n if (!entries) {\n return `${name}:`;\n }\n return `${name}:\\n${entries}`;\n }\n return `${name}:`;\n }\n\n #renderArrayField(key: string, items: FragmentData[], depth: number): string {\n const filtered = items.filter((item) => item != null);\n if (filtered.length === 0) {\n return `${this.#pad(depth)}${key}[0]:`;\n }\n\n // Check for ContextFragment items\n const fragmentItems = filtered.filter(isFragment);\n if (fragmentItems.length > 0) {\n return this.#renderMixedArray(key, filtered, depth);\n }\n\n // Check if all items are primitives\n if (filtered.every((item) => this.#isPrimitiveValue(item))) {\n return this.#renderPrimitiveArray(key, filtered, depth);\n }\n\n // Check if tabular (uniform objects with primitive values)\n if (this.#isTabularArray(filtered)) {\n return this.#renderTabularArray(key, filtered, depth);\n }\n\n // Mixed array\n return this.#renderMixedArray(key, filtered, depth);\n }\n\n #isPrimitiveValue(value: unknown): boolean {\n return (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n );\n }\n\n #isTabularArray(items: FragmentData[]): items is FragmentObject[] {\n if (items.length === 0) return false;\n\n // All items must be objects (not arrays, not primitives, not fragments)\n const objects = items.filter(isFragmentObject);\n if (objects.length !== items.length) return false;\n\n // Get keys from first object\n const firstKeys = Object.keys(objects[0]).sort().join(',');\n\n // All objects must have same keys\n for (const obj of objects) {\n if (Object.keys(obj).sort().join(',') !== firstKeys) {\n return false;\n }\n // All values must be primitives\n for (const value of Object.values(obj)) {\n if (!this.#isPrimitiveValue(value) && value !== null) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n #renderPrimitiveArray(\n key: string,\n items: FragmentData[],\n depth: number,\n ): string {\n const values = items.map((item) => this.#formatValue(item)).join(',');\n return `${this.#pad(depth)}${key}[${items.length}]: ${values}`;\n }\n\n #renderTabularArray(\n key: string,\n items: FragmentObject[],\n depth: number,\n ): string {\n if (items.length === 0) {\n return `${this.#pad(depth)}${key}[0]:`;\n }\n\n const fields = Object.keys(items[0]);\n const header = `${this.#pad(depth)}${key}[${items.length}]{${fields.join(',')}}:`;\n\n const rows = items.map((obj) => {\n const values = fields.map((f) => this.#formatValue(obj[f]));\n return `${this.#pad(depth + 1)}${values.join(',')}`;\n });\n\n return [header, ...rows].join('\\n');\n }\n\n #renderMixedArray(key: string, items: FragmentData[], depth: number): string {\n const header = `${this.#pad(depth)}${key}[${items.length}]:`;\n const lines = items.map((item) => this.#renderListItem(item, depth + 1));\n return [header, ...lines].join('\\n');\n }\n\n #renderListItem(item: FragmentData, depth: number): string {\n if (this.#isPrimitiveValue(item)) {\n return `${this.#pad(depth)}- ${this.#formatValue(item)}`;\n }\n if (isFragment(item)) {\n const rendered = this.renderFragment(item, {\n depth: depth + 1,\n path: [],\n });\n // For fragments, render key: value on same line as hyphen if primitive\n if (this.isPrimitive(item.data)) {\n return `${this.#pad(depth)}- ${item.name}: ${this.#formatValue(item.data)}`;\n }\n return `${this.#pad(depth)}- ${item.name}:\\n${rendered.split('\\n').slice(1).join('\\n')}`;\n }\n if (Array.isArray(item)) {\n // Nested array\n const content = this.#renderArrayField('', item, depth + 1);\n return `${this.#pad(depth)}-${content.trimStart()}`;\n }\n if (isFragmentObject(item)) {\n // Object in list\n const entries = this.#renderObjectEntries(item, depth + 1);\n if (!entries) {\n return `${this.#pad(depth)}-`;\n }\n // First line on same line as hyphen\n const lines = entries.split('\\n');\n const first = lines[0].trimStart();\n const rest = lines.slice(1).join('\\n');\n return rest\n ? `${this.#pad(depth)}- ${first}\\n${rest}`\n : `${this.#pad(depth)}- ${first}`;\n }\n return `${this.#pad(depth)}- ${this.#formatValue(item)}`;\n }\n\n #renderObjectEntries(obj: FragmentObject, depth: number): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(obj)) {\n if (value == null) continue;\n\n if (this.#isPrimitiveValue(value)) {\n lines.push(`${this.#pad(depth)}${key}: ${this.#formatValue(value)}`);\n } else if (Array.isArray(value)) {\n lines.push(this.#renderArrayField(key, value, depth));\n } else if (isFragmentObject(value)) {\n const nested = this.#renderObjectEntries(value, depth + 1);\n if (nested) {\n lines.push(`${this.#pad(depth)}${key}:\\n${nested}`);\n } else {\n lines.push(`${this.#pad(depth)}${key}:`);\n }\n }\n }\n return lines.join('\\n');\n }\n\n protected renderFragment(\n fragment: ContextFragment,\n ctx: RenderContext,\n ): string {\n const { name, data } = fragment;\n if (this.isPrimitive(data)) {\n return `${this.#pad(ctx.depth)}${name}: ${this.#formatValue(data)}`;\n }\n if (isFragment(data)) {\n const child = this.renderFragment(data, {\n ...ctx,\n depth: ctx.depth + 1,\n });\n return `${this.#pad(ctx.depth)}${name}:\\n${child}`;\n }\n if (Array.isArray(data)) {\n return this.#renderArrayField(name, data, ctx.depth);\n }\n if (isFragmentObject(data)) {\n const entries = this.#renderObjectEntries(data, ctx.depth + 1);\n if (!entries) {\n return `${this.#pad(ctx.depth)}${name}:`;\n }\n return `${this.#pad(ctx.depth)}${name}:\\n${entries}`;\n }\n return `${this.#pad(ctx.depth)}${name}:`;\n }\n\n protected renderPrimitive(\n key: string,\n value: string,\n ctx: RenderContext,\n ): string {\n return `${this.#pad(ctx.depth)}${key}: ${this.#formatValue(value)}`;\n }\n\n protected renderArray(\n key: string,\n items: FragmentData[],\n ctx: RenderContext,\n ): string {\n return this.#renderArrayField(key, items, ctx.depth);\n }\n\n protected renderObject(\n key: string,\n obj: FragmentObject,\n ctx: RenderContext,\n ): string {\n const entries = this.#renderObjectEntries(obj, ctx.depth + 1);\n if (!entries) {\n return `${this.#pad(ctx.depth)}${key}:`;\n }\n return `${this.#pad(ctx.depth)}${key}:\\n${entries}`;\n }\n\n #pad(depth: number): string {\n return ' '.repeat(depth);\n }\n\n #needsQuoting(value: string): boolean {\n if (value === '') return true;\n if (value !== value.trim()) return true;\n if (['true', 'false', 'null'].includes(value.toLowerCase())) return true;\n if (/^-?\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?$/i.test(value)) return true;\n if (/[:\\\\\"'[\\]{}|,\\t\\n\\r]/.test(value)) return true;\n if (value.startsWith('-')) return true;\n return false;\n }\n\n #escape(value: string): string {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n }\n\n #canonicalizeNumber(n: number): string {\n if (!Number.isFinite(n)) return 'null';\n if (Object.is(n, -0)) return '0';\n return String(n);\n }\n\n #formatValue(value: unknown): string {\n if (value === null) return 'null';\n if (typeof value === 'boolean') return String(value);\n if (typeof value === 'number') return this.#canonicalizeNumber(value);\n if (typeof value === 'string') {\n if (this.#needsQuoting(value)) {\n return `\"${this.#escape(value)}\"`;\n }\n return value;\n }\n // Fallback for objects/arrays in primitive context\n return `\"${this.#escape(JSON.stringify(value))}\"`;\n }\n}\n", "/**\n * Graph-based context store types and abstract interface.\n *\n * The storage model uses a DAG (Directed Acyclic Graph) for messages:\n * - Messages are immutable nodes with parentId forming the graph\n * - Branches are pointers to head (tip) messages\n * - Checkpoints are pointers to specific messages\n * - History is preserved through branching (rewind creates new branch)\n */\n\n// ============================================================================\n// Chat Types\n// ============================================================================\n\n/**\n * Data for creating/storing a chat.\n */\nexport interface ChatData {\n id: string;\n title?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Stored chat data returned from database (includes timestamps).\n */\nexport interface StoredChatData extends ChatData {\n createdAt: number;\n updatedAt: number;\n}\n\n/**\n * Information about a chat for listing.\n */\nexport interface ChatInfo {\n id: string;\n title?: string;\n messageCount: number;\n branchCount: number;\n createdAt: number;\n updatedAt: number;\n}\n\n// ============================================================================\n// Message Types (Graph Nodes)\n// ============================================================================\n\n/**\n * Data for creating/storing a message (graph node).\n */\nexport interface MessageData {\n id: string;\n chatId: string;\n parentId: string | null; // null for root messages\n name: string; // 'user', 'assistant', 'role', 'hint', etc.\n type?: string; // 'message', 'fragment'\n data: unknown; // JSON-serializable content\n createdAt: number;\n}\n\n/**\n * Message with computed properties for listing.\n */\nexport interface MessageInfo extends MessageData {\n hasChildren: boolean;\n}\n\n// ============================================================================\n// Branch Types\n// ============================================================================\n\n/**\n * Data for creating/storing a branch.\n * A branch is a pointer to a head message in the graph.\n */\nexport interface BranchData {\n id: string;\n chatId: string;\n name: string; // 'main', 'alt-1', etc.\n headMessageId: string | null; // null if branch is empty\n isActive: boolean;\n createdAt: number;\n}\n\n/**\n * Information about a branch for listing.\n */\nexport interface BranchInfo {\n id: string;\n name: string;\n headMessageId: string | null;\n isActive: boolean;\n messageCount: number; // count of messages in this branch's chain\n createdAt: number;\n}\n\n// ============================================================================\n// Checkpoint Types\n// ============================================================================\n\n/**\n * Data for creating/storing a checkpoint.\n * A checkpoint is a pointer to a specific message in the graph.\n */\nexport interface CheckpointData {\n id: string;\n chatId: string;\n name: string;\n messageId: string;\n createdAt: number;\n}\n\n/**\n * Information about a checkpoint for listing.\n */\nexport interface CheckpointInfo {\n id: string;\n name: string;\n messageId: string;\n createdAt: number;\n}\n\n// ============================================================================\n// Search Types\n// ============================================================================\n\n/**\n * Options for searching messages.\n */\nexport interface SearchOptions {\n /** Only search in specific roles (e.g., ['user', 'assistant']) */\n roles?: string[];\n /** Maximum results to return (default: 20) */\n limit?: number;\n}\n\n/**\n * Search result with relevance ranking.\n */\nexport interface SearchResult {\n /** The matched message */\n message: MessageData;\n /** BM25 relevance score (lower = more relevant) */\n rank: number;\n /** Highlighted snippet with matched terms */\n snippet?: string;\n}\n\n// ============================================================================\n// Graph Visualization Types\n// ============================================================================\n\n/**\n * A node in the visualization graph.\n */\nexport interface GraphNode {\n id: string;\n parentId: string | null;\n role: string; // 'user', 'assistant', etc.\n content: string; // Truncated preview of message content\n createdAt: number;\n}\n\n/**\n * A branch pointer for visualization.\n */\nexport interface GraphBranch {\n name: string;\n headMessageId: string | null;\n isActive: boolean;\n}\n\n/**\n * A checkpoint pointer for visualization.\n */\nexport interface GraphCheckpoint {\n name: string;\n messageId: string;\n}\n\n/**\n * Complete graph data for visualization.\n */\nexport interface GraphData {\n chatId: string;\n nodes: GraphNode[];\n branches: GraphBranch[];\n checkpoints: GraphCheckpoint[];\n}\n\n// ============================================================================\n// Abstract Store Interface\n// ============================================================================\n\n/**\n * Abstract base class for graph-based context storage.\n *\n * Implementations provide persistence for the message graph, branches,\n * and checkpoints. The graph model enables:\n * - Branching: rewind creates a new branch, original stays intact\n * - Checkpoints: pointers to specific messages for easy restore\n * - No data loss: soft delete only, all history preserved\n */\nexport abstract class ContextStore {\n // ==========================================================================\n // Chat Operations\n // ==========================================================================\n\n /**\n * Create a new chat.\n */\n abstract createChat(chat: ChatData): Promise<void>;\n\n /**\n * Create a chat if it doesn't exist, or return existing one.\n * Returns the stored chat data with timestamps.\n */\n abstract upsertChat(chat: ChatData): Promise<StoredChatData>;\n\n /**\n * Get a chat by ID.\n */\n abstract getChat(chatId: string): Promise<StoredChatData | undefined>;\n\n /**\n * Update chat metadata.\n * Note: updatedAt is automatically managed by database triggers.\n * Returns the updated chat data.\n */\n abstract updateChat(\n chatId: string,\n updates: Partial<Pick<ChatData, 'title' | 'metadata'>>,\n ): Promise<StoredChatData>;\n\n /**\n * List all chats, sorted by updatedAt descending.\n */\n abstract listChats(): Promise<ChatInfo[]>;\n\n // ==========================================================================\n // Message Operations (Graph Nodes)\n // ==========================================================================\n\n /**\n * Add a message to the graph.\n */\n abstract addMessage(message: MessageData): Promise<void>;\n\n /**\n * Get a message by ID.\n */\n abstract getMessage(messageId: string): Promise<MessageData | undefined>;\n\n /**\n * Walk up the parent chain from a head message, returning messages in\n * chronological order (root first).\n */\n abstract getMessageChain(headId: string): Promise<MessageData[]>;\n\n /**\n * Check if a message has children (is a fork point).\n */\n abstract hasChildren(messageId: string): Promise<boolean>;\n\n // ==========================================================================\n // Branch Operations\n // ==========================================================================\n\n /**\n * Create a new branch.\n */\n abstract createBranch(branch: BranchData): Promise<void>;\n\n /**\n * Get a branch by chat ID and name.\n */\n abstract getBranch(\n chatId: string,\n name: string,\n ): Promise<BranchData | undefined>;\n\n /**\n * Get the active branch for a chat.\n */\n abstract getActiveBranch(chatId: string): Promise<BranchData | undefined>;\n\n /**\n * Set a branch as active (and deactivate others).\n */\n abstract setActiveBranch(chatId: string, branchId: string): Promise<void>;\n\n /**\n * Update a branch's head message.\n */\n abstract updateBranchHead(\n branchId: string,\n messageId: string | null,\n ): Promise<void>;\n\n /**\n * List all branches for a chat.\n */\n abstract listBranches(chatId: string): Promise<BranchInfo[]>;\n\n // ==========================================================================\n // Checkpoint Operations\n // ==========================================================================\n\n /**\n * Create a checkpoint.\n */\n abstract createCheckpoint(checkpoint: CheckpointData): Promise<void>;\n\n /**\n * Get a checkpoint by chat ID and name.\n */\n abstract getCheckpoint(\n chatId: string,\n name: string,\n ): Promise<CheckpointData | undefined>;\n\n /**\n * List all checkpoints for a chat.\n */\n abstract listCheckpoints(chatId: string): Promise<CheckpointInfo[]>;\n\n /**\n * Delete a checkpoint.\n */\n abstract deleteCheckpoint(chatId: string, name: string): Promise<void>;\n\n // ==========================================================================\n // Search Operations\n // ==========================================================================\n\n /**\n * Search messages using full-text search.\n *\n * @param chatId - The chat to search in\n * @param query - FTS5 query string (supports AND, OR, NOT, phrases, prefix*)\n * @param options - Search options\n * @returns Search results ordered by relevance (lower rank = more relevant)\n */\n abstract searchMessages(\n chatId: string,\n query: string,\n options?: SearchOptions,\n ): Promise<SearchResult[]>;\n\n // ==========================================================================\n // Visualization Operations\n // ==========================================================================\n\n /**\n * Get the complete graph data for a chat.\n * Returns all messages, branches, and checkpoints.\n */\n abstract getGraph(chatId: string): Promise<GraphData>;\n}\n", "import { DatabaseSync, type SQLInputValue } from 'node:sqlite';\n\nimport type {\n BranchData,\n BranchInfo,\n ChatData,\n ChatInfo,\n CheckpointData,\n CheckpointInfo,\n GraphBranch,\n GraphCheckpoint,\n GraphData,\n GraphNode,\n MessageData,\n SearchOptions,\n SearchResult,\n StoredChatData,\n} from './store.ts';\nimport { ContextStore } from './store.ts';\n\nconst STORE_DDL = `\n-- Chats table\n-- createdAt/updatedAt: DEFAULT for insert, inline SET for updates\nCREATE TABLE IF NOT EXISTS chats (\n id TEXT PRIMARY KEY,\n title TEXT,\n metadata TEXT,\n createdAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n updatedAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000)\n);\n\nCREATE INDEX IF NOT EXISTS idx_chats_updatedAt ON chats(updatedAt);\n\n-- Messages table (nodes in the DAG)\nCREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n parentId TEXT,\n name TEXT NOT NULL,\n type TEXT,\n data TEXT NOT NULL,\n createdAt INTEGER NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (parentId) REFERENCES messages(id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_messages_chatId ON messages(chatId);\nCREATE INDEX IF NOT EXISTS idx_messages_parentId ON messages(parentId);\n\n-- Branches table (pointers to head messages)\nCREATE TABLE IF NOT EXISTS branches (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n name TEXT NOT NULL,\n headMessageId TEXT,\n isActive INTEGER NOT NULL DEFAULT 0,\n createdAt INTEGER NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (headMessageId) REFERENCES messages(id),\n UNIQUE(chatId, name)\n);\n\nCREATE INDEX IF NOT EXISTS idx_branches_chatId ON branches(chatId);\n\n-- Checkpoints table (pointers to message nodes)\nCREATE TABLE IF NOT EXISTS checkpoints (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n name TEXT NOT NULL,\n messageId TEXT NOT NULL,\n createdAt INTEGER NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (messageId) REFERENCES messages(id),\n UNIQUE(chatId, name)\n);\n\nCREATE INDEX IF NOT EXISTS idx_checkpoints_chatId ON checkpoints(chatId);\n\n-- FTS5 virtual table for full-text search\n-- messageId/chatId/name are UNINDEXED (stored but not searchable, used for filtering/joining)\n-- Only 'content' is indexed for full-text search\nCREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(\n messageId UNINDEXED,\n chatId UNINDEXED,\n name UNINDEXED,\n content,\n tokenize='porter unicode61'\n);\n`;\n\n/**\n * SQLite-based context store using graph model.\n *\n * Uses node:sqlite's synchronous DatabaseSync for persistence.\n * Messages are stored as nodes in a DAG with parentId links.\n */\nexport class SqliteContextStore extends ContextStore {\n #db: DatabaseSync;\n\n constructor(path: string) {\n super();\n this.#db = new DatabaseSync(path);\n this.#db.exec('PRAGMA foreign_keys = ON');\n this.#db.exec(STORE_DDL);\n }\n\n // ==========================================================================\n // Chat Operations\n // ==========================================================================\n\n async createChat(chat: ChatData): Promise<void> {\n // createdAt and updatedAt are auto-set by SQLite DEFAULT\n this.#db\n .prepare(\n `INSERT INTO chats (id, title, metadata)\n VALUES (?, ?, ?)`,\n )\n .run(\n chat.id,\n chat.title ?? null,\n chat.metadata ? JSON.stringify(chat.metadata) : null,\n );\n }\n\n async upsertChat(chat: ChatData): Promise<StoredChatData> {\n // Insert if not exists, no-op update if exists (to trigger RETURNING)\n const row = this.#db\n .prepare(\n `INSERT INTO chats (id, title, metadata)\n VALUES (?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET id = excluded.id\n RETURNING *`,\n )\n .get(\n chat.id,\n chat.title ?? null,\n chat.metadata ? JSON.stringify(chat.metadata) : null,\n ) as {\n id: string;\n title: string | null;\n metadata: string | null;\n createdAt: number;\n updatedAt: number;\n };\n\n return {\n id: row.id,\n title: row.title ?? undefined,\n metadata: row.metadata ? JSON.parse(row.metadata) : undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n async getChat(chatId: string): Promise<StoredChatData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM chats WHERE id = ?')\n .get(chatId) as\n | {\n id: string;\n title: string | null;\n metadata: string | null;\n createdAt: number;\n updatedAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n title: row.title ?? undefined,\n metadata: row.metadata ? JSON.parse(row.metadata) : undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n async updateChat(\n chatId: string,\n updates: Partial<Pick<ChatData, 'title' | 'metadata'>>,\n ): Promise<StoredChatData> {\n const setClauses: string[] = [\"updatedAt = strftime('%s', 'now') * 1000\"];\n const params: SQLInputValue[] = [];\n\n if (updates.title !== undefined) {\n setClauses.push('title = ?');\n params.push(updates.title ?? null);\n }\n if (updates.metadata !== undefined) {\n setClauses.push('metadata = ?');\n params.push(JSON.stringify(updates.metadata));\n }\n\n params.push(chatId);\n const row = this.#db\n .prepare(\n `UPDATE chats SET ${setClauses.join(', ')} WHERE id = ? RETURNING *`,\n )\n .get(...params) as {\n id: string;\n title: string | null;\n metadata: string | null;\n createdAt: number;\n updatedAt: number;\n };\n\n return {\n id: row.id,\n title: row.title ?? undefined,\n metadata: row.metadata ? JSON.parse(row.metadata) : undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n async listChats(): Promise<ChatInfo[]> {\n const rows = this.#db\n .prepare(\n `SELECT\n c.id,\n c.title,\n c.createdAt,\n c.updatedAt,\n COUNT(DISTINCT m.id) as messageCount,\n COUNT(DISTINCT b.id) as branchCount\n FROM chats c\n LEFT JOIN messages m ON m.chatId = c.id\n LEFT JOIN branches b ON b.chatId = c.id\n GROUP BY c.id\n ORDER BY c.updatedAt DESC`,\n )\n .all() as {\n id: string;\n title: string | null;\n createdAt: number;\n updatedAt: number;\n messageCount: number;\n branchCount: number;\n }[];\n\n return rows.map((row) => ({\n id: row.id,\n title: row.title ?? undefined,\n messageCount: row.messageCount,\n branchCount: row.branchCount,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n }));\n }\n\n // ==========================================================================\n // Message Operations (Graph Nodes)\n // ==========================================================================\n\n async addMessage(message: MessageData): Promise<void> {\n // Upsert the message\n this.#db\n .prepare(\n `INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n parentId = excluded.parentId,\n name = excluded.name,\n type = excluded.type,\n data = excluded.data`,\n )\n .run(\n message.id,\n message.chatId,\n message.parentId,\n message.name,\n message.type ?? null,\n JSON.stringify(message.data),\n message.createdAt,\n );\n\n // Index in FTS for search\n const content =\n typeof message.data === 'string'\n ? message.data\n : JSON.stringify(message.data);\n\n // Delete existing FTS entry if any (for upsert), then insert new one\n this.#db\n .prepare(`DELETE FROM messages_fts WHERE messageId = ?`)\n .run(message.id);\n this.#db\n .prepare(\n `INSERT INTO messages_fts(messageId, chatId, name, content)\n VALUES (?, ?, ?, ?)`,\n )\n .run(message.id, message.chatId, message.name, content);\n }\n\n async getMessage(messageId: string): Promise<MessageData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM messages WHERE id = ?')\n .get(messageId) as\n | {\n id: string;\n chatId: string;\n parentId: string | null;\n name: string;\n type: string | null;\n data: string;\n createdAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n chatId: row.chatId,\n parentId: row.parentId,\n name: row.name,\n type: row.type ?? undefined,\n data: JSON.parse(row.data),\n createdAt: row.createdAt,\n };\n }\n\n async getMessageChain(headId: string): Promise<MessageData[]> {\n // Walk up the parent chain using recursive CTE with depth tracking\n // The CTE walks from head (newest) to root (oldest), so we track depth\n // and order by depth DESC to get chronological order (root first)\n const rows = this.#db\n .prepare(\n `WITH RECURSIVE chain AS (\n SELECT *, 0 as depth FROM messages WHERE id = ?\n UNION ALL\n SELECT m.*, c.depth + 1 FROM messages m\n INNER JOIN chain c ON m.id = c.parentId\n )\n SELECT * FROM chain\n ORDER BY depth DESC`,\n )\n .all(headId) as {\n id: string;\n chatId: string;\n parentId: string | null;\n name: string;\n type: string | null;\n data: string;\n createdAt: number;\n depth: number;\n }[];\n\n return rows.map((row) => ({\n id: row.id,\n chatId: row.chatId,\n parentId: row.parentId,\n name: row.name,\n type: row.type ?? undefined,\n data: JSON.parse(row.data),\n createdAt: row.createdAt,\n }));\n }\n\n async hasChildren(messageId: string): Promise<boolean> {\n const row = this.#db\n .prepare(\n 'SELECT EXISTS(SELECT 1 FROM messages WHERE parentId = ?) as hasChildren',\n )\n .get(messageId) as { hasChildren: number };\n\n return row.hasChildren === 1;\n }\n\n // ==========================================================================\n // Branch Operations\n // ==========================================================================\n\n async createBranch(branch: BranchData): Promise<void> {\n this.#db\n .prepare(\n `INSERT INTO branches (id, chatId, name, headMessageId, isActive, createdAt)\n VALUES (?, ?, ?, ?, ?, ?)`,\n )\n .run(\n branch.id,\n branch.chatId,\n branch.name,\n branch.headMessageId,\n branch.isActive ? 1 : 0,\n branch.createdAt,\n );\n }\n\n async getBranch(\n chatId: string,\n name: string,\n ): Promise<BranchData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM branches WHERE chatId = ? AND name = ?')\n .get(chatId, name) as\n | {\n id: string;\n chatId: string;\n name: string;\n headMessageId: string | null;\n isActive: number;\n createdAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n chatId: row.chatId,\n name: row.name,\n headMessageId: row.headMessageId,\n isActive: row.isActive === 1,\n createdAt: row.createdAt,\n };\n }\n\n async getActiveBranch(chatId: string): Promise<BranchData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM branches WHERE chatId = ? AND isActive = 1')\n .get(chatId) as\n | {\n id: string;\n chatId: string;\n name: string;\n headMessageId: string | null;\n isActive: number;\n createdAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n chatId: row.chatId,\n name: row.name,\n headMessageId: row.headMessageId,\n isActive: true,\n createdAt: row.createdAt,\n };\n }\n\n async setActiveBranch(chatId: string, branchId: string): Promise<void> {\n // Deactivate all branches for this chat\n this.#db\n .prepare('UPDATE branches SET isActive = 0 WHERE chatId = ?')\n .run(chatId);\n\n // Activate the specified branch\n this.#db\n .prepare('UPDATE branches SET isActive = 1 WHERE id = ?')\n .run(branchId);\n }\n\n async updateBranchHead(\n branchId: string,\n messageId: string | null,\n ): Promise<void> {\n this.#db\n .prepare('UPDATE branches SET headMessageId = ? WHERE id = ?')\n .run(messageId, branchId);\n }\n\n async listBranches(chatId: string): Promise<BranchInfo[]> {\n // Get branches with message count by walking the chain\n const branches = this.#db\n .prepare(\n `SELECT\n b.id,\n b.name,\n b.headMessageId,\n b.isActive,\n b.createdAt\n FROM branches b\n WHERE b.chatId = ?\n ORDER BY b.createdAt ASC`,\n )\n .all(chatId) as {\n id: string;\n name: string;\n headMessageId: string | null;\n isActive: number;\n createdAt: number;\n }[];\n\n // For each branch, count messages in the chain\n const result: BranchInfo[] = [];\n for (const branch of branches) {\n let messageCount = 0;\n if (branch.headMessageId) {\n const countRow = this.#db\n .prepare(\n `WITH RECURSIVE chain AS (\n SELECT id, parentId FROM messages WHERE id = ?\n UNION ALL\n SELECT m.id, m.parentId FROM messages m\n INNER JOIN chain c ON m.id = c.parentId\n )\n SELECT COUNT(*) as count FROM chain`,\n )\n .get(branch.headMessageId) as { count: number };\n messageCount = countRow.count;\n }\n\n result.push({\n id: branch.id,\n name: branch.name,\n headMessageId: branch.headMessageId,\n isActive: branch.isActive === 1,\n messageCount,\n createdAt: branch.createdAt,\n });\n }\n\n return result;\n }\n\n // ==========================================================================\n // Checkpoint Operations\n // ==========================================================================\n\n async createCheckpoint(checkpoint: CheckpointData): Promise<void> {\n this.#db\n .prepare(\n `INSERT INTO checkpoints (id, chatId, name, messageId, createdAt)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(chatId, name) DO UPDATE SET\n messageId = excluded.messageId,\n createdAt = excluded.createdAt`,\n )\n .run(\n checkpoint.id,\n checkpoint.chatId,\n checkpoint.name,\n checkpoint.messageId,\n checkpoint.createdAt,\n );\n }\n\n async getCheckpoint(\n chatId: string,\n name: string,\n ): Promise<CheckpointData | undefined> {\n const row = this.#db\n .prepare('SELECT * FROM checkpoints WHERE chatId = ? AND name = ?')\n .get(chatId, name) as\n | {\n id: string;\n chatId: string;\n name: string;\n messageId: string;\n createdAt: number;\n }\n | undefined;\n\n if (!row) {\n return undefined;\n }\n\n return {\n id: row.id,\n chatId: row.chatId,\n name: row.name,\n messageId: row.messageId,\n createdAt: row.createdAt,\n };\n }\n\n async listCheckpoints(chatId: string): Promise<CheckpointInfo[]> {\n const rows = this.#db\n .prepare(\n `SELECT id, name, messageId, createdAt\n FROM checkpoints\n WHERE chatId = ?\n ORDER BY createdAt DESC`,\n )\n .all(chatId) as {\n id: string;\n name: string;\n messageId: string;\n createdAt: number;\n }[];\n\n return rows.map((row) => ({\n id: row.id,\n name: row.name,\n messageId: row.messageId,\n createdAt: row.createdAt,\n }));\n }\n\n async deleteCheckpoint(chatId: string, name: string): Promise<void> {\n this.#db\n .prepare('DELETE FROM checkpoints WHERE chatId = ? AND name = ?')\n .run(chatId, name);\n }\n\n // ==========================================================================\n // Search Operations\n // ==========================================================================\n\n async searchMessages(\n chatId: string,\n query: string,\n options?: SearchOptions,\n ): Promise<SearchResult[]> {\n const limit = options?.limit ?? 20;\n const roles = options?.roles;\n\n // Build the query dynamically based on options\n let sql = `\n SELECT\n m.id,\n m.chatId,\n m.parentId,\n m.name,\n m.type,\n m.data,\n m.createdAt,\n fts.rank,\n snippet(messages_fts, 3, '<mark>', '</mark>', '...', 32) as snippet\n FROM messages_fts fts\n JOIN messages m ON m.id = fts.messageId\n WHERE messages_fts MATCH ?\n AND fts.chatId = ?\n `;\n\n const params: SQLInputValue[] = [query, chatId];\n\n if (roles && roles.length > 0) {\n const placeholders = roles.map(() => '?').join(', ');\n sql += ` AND fts.name IN (${placeholders})`;\n params.push(...roles);\n }\n\n sql += ' ORDER BY fts.rank LIMIT ?';\n params.push(limit);\n\n const rows = this.#db.prepare(sql).all(...params) as {\n id: string;\n chatId: string;\n parentId: string | null;\n name: string;\n type: string | null;\n data: string;\n createdAt: number;\n rank: number;\n snippet: string;\n }[];\n\n return rows.map((row) => ({\n message: {\n id: row.id,\n chatId: row.chatId,\n parentId: row.parentId,\n name: row.name,\n type: row.type ?? undefined,\n data: JSON.parse(row.data),\n createdAt: row.createdAt,\n },\n rank: row.rank,\n snippet: row.snippet,\n }));\n }\n\n // ==========================================================================\n // Visualization Operations\n // ==========================================================================\n\n async getGraph(chatId: string): Promise<GraphData> {\n // Get all messages for complete graph\n const messageRows = this.#db\n .prepare(\n `SELECT id, parentId, name, data, createdAt\n FROM messages\n WHERE chatId = ?\n ORDER BY createdAt ASC`,\n )\n .all(chatId) as {\n id: string;\n parentId: string | null;\n name: string;\n data: string;\n createdAt: number;\n }[];\n\n const nodes: GraphNode[] = messageRows.map((row) => {\n const data = JSON.parse(row.data);\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n id: row.id,\n parentId: row.parentId,\n role: row.name,\n content: content.length > 50 ? content.slice(0, 50) + '...' : content,\n createdAt: row.createdAt,\n };\n });\n\n // Get all branches\n const branchRows = this.#db\n .prepare(\n `SELECT name, headMessageId, isActive\n FROM branches\n WHERE chatId = ?\n ORDER BY createdAt ASC`,\n )\n .all(chatId) as {\n name: string;\n headMessageId: string | null;\n isActive: number;\n }[];\n\n const branches: GraphBranch[] = branchRows.map((row) => ({\n name: row.name,\n headMessageId: row.headMessageId,\n isActive: row.isActive === 1,\n }));\n\n // Get all checkpoints\n const checkpointRows = this.#db\n .prepare(\n `SELECT name, messageId\n FROM checkpoints\n WHERE chatId = ?\n ORDER BY createdAt ASC`,\n )\n .all(chatId) as {\n name: string;\n messageId: string;\n }[];\n\n const checkpoints: GraphCheckpoint[] = checkpointRows.map((row) => ({\n name: row.name,\n messageId: row.messageId,\n }));\n\n return {\n chatId,\n nodes,\n branches,\n checkpoints,\n };\n }\n}\n", "import { SqliteContextStore } from './sqlite.store.ts';\n\n/**\n * In-memory context store.\n *\n * Uses SQLite's :memory: database for non-persistent storage.\n * Useful for testing and short-lived sessions.\n */\nexport class InMemoryContextStore extends SqliteContextStore {\n constructor() {\n super(':memory:');\n }\n}\n", "import type { GraphData, GraphNode } from './store/store.ts';\n\n/**\n * Render a graph as ASCII art.\n *\n * @param data - The graph data to visualize\n * @returns ASCII art representation of the graph\n *\n * @example\n * ```ts\n * const graph = await store.getGraph('my-chat');\n * console.log(visualizeGraph(graph));\n * ```\n */\nexport function visualizeGraph(data: GraphData): string {\n if (data.nodes.length === 0) {\n return `[chat: ${data.chatId}]\\n\\n(empty)`;\n }\n\n // Build lookup maps\n const childrenByParentId = new Map<string | null, GraphNode[]>();\n const branchHeads = new Map<string, string[]>(); // messageId -> branch names\n const checkpointsByMessageId = new Map<string, string[]>(); // messageId -> checkpoint names\n\n for (const node of data.nodes) {\n const children = childrenByParentId.get(node.parentId) ?? [];\n children.push(node);\n childrenByParentId.set(node.parentId, children);\n }\n\n for (const branch of data.branches) {\n if (branch.headMessageId) {\n const heads = branchHeads.get(branch.headMessageId) ?? [];\n heads.push(branch.isActive ? `${branch.name} *` : branch.name);\n branchHeads.set(branch.headMessageId, heads);\n }\n }\n\n for (const checkpoint of data.checkpoints) {\n const cps = checkpointsByMessageId.get(checkpoint.messageId) ?? [];\n cps.push(checkpoint.name);\n checkpointsByMessageId.set(checkpoint.messageId, cps);\n }\n\n // Find root nodes (parentId === null)\n const roots = childrenByParentId.get(null) ?? [];\n\n const lines: string[] = [`[chat: ${data.chatId}]`, ''];\n\n // Recursively render the tree\n function renderNode(\n node: GraphNode,\n prefix: string,\n isLast: boolean,\n isRoot: boolean,\n ): void {\n const connector = isRoot ? '' : isLast ? '\u2514\u2500\u2500 ' : '\u251C\u2500\u2500 ';\n const contentPreview = node.content.replace(/\\n/g, ' ');\n\n let line = `${prefix}${connector}${node.id.slice(0, 8)} (${node.role}): \"${contentPreview}\"`;\n\n // Add branch markers\n const branches = branchHeads.get(node.id);\n if (branches) {\n line += ` <- [${branches.join(', ')}]`;\n }\n\n // Add checkpoint markers\n const checkpoints = checkpointsByMessageId.get(node.id);\n if (checkpoints) {\n line += ` {${checkpoints.join(', ')}}`;\n }\n\n lines.push(line);\n\n // Render children\n const children = childrenByParentId.get(node.id) ?? [];\n const childPrefix = isRoot ? '' : prefix + (isLast ? ' ' : '\u2502 ');\n\n for (let i = 0; i < children.length; i++) {\n renderNode(children[i], childPrefix, i === children.length - 1, false);\n }\n }\n\n // Render each root\n for (let i = 0; i < roots.length; i++) {\n renderNode(roots[i], '', i === roots.length - 1, true);\n }\n\n // Add legend\n lines.push('');\n lines.push('Legend: * = active branch, {...} = checkpoint');\n\n return lines.join('\\n');\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["fragment", "fragment", "fragment", "children", "message", "fragment", "message"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepagents/context",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -38,7 +38,7 @@
38
38
  "ai": "^5.0.100",
39
39
  "chalk": "^5.6.0",
40
40
  "zod": "^3.25.76 || ^4.0.0",
41
- "@deepagents/agent": "0.9.0",
41
+ "@deepagents/agent": "0.10.0",
42
42
  "@ai-sdk/groq": "2.0.32"
43
43
  },
44
44
  "devDependencies": {