@deepagents/text2sql 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/index.js +263 -81
  2. package/dist/index.js.map +4 -4
  3. package/dist/lib/adapters/groundings/index.js +167 -11
  4. package/dist/lib/adapters/groundings/index.js.map +4 -4
  5. package/dist/lib/adapters/mysql/index.js +167 -11
  6. package/dist/lib/adapters/mysql/index.js.map +4 -4
  7. package/dist/lib/adapters/postgres/index.js +167 -11
  8. package/dist/lib/adapters/postgres/index.js.map +4 -4
  9. package/dist/lib/adapters/spreadsheet/index.js +2 -0
  10. package/dist/lib/adapters/spreadsheet/index.js.map +3 -3
  11. package/dist/lib/adapters/sqlite/index.js +167 -11
  12. package/dist/lib/adapters/sqlite/index.js.map +4 -4
  13. package/dist/lib/adapters/sqlserver/column-stats.sqlserver.grounding.d.ts.map +1 -1
  14. package/dist/lib/adapters/sqlserver/index.js +168 -14
  15. package/dist/lib/adapters/sqlserver/index.js.map +4 -4
  16. package/dist/lib/agents/result-tools.d.ts +12 -3
  17. package/dist/lib/agents/result-tools.d.ts.map +1 -1
  18. package/dist/lib/agents/sql.agent.d.ts +1 -1
  19. package/dist/lib/agents/sql.agent.d.ts.map +1 -1
  20. package/dist/lib/instructions.d.ts.map +1 -1
  21. package/dist/lib/sql.d.ts +4 -15
  22. package/dist/lib/sql.d.ts.map +1 -1
  23. package/dist/lib/synthesis/index.js +176 -10
  24. package/dist/lib/synthesis/index.js.map +4 -4
  25. package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts +3 -3
  26. package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -1
  27. package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts +1 -1
  28. package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts.map +1 -1
  29. package/package.json +4 -4
@@ -1,3 +1,4 @@
1
+ import type { SkillPathMapping } from '@deepagents/context';
1
2
  import type { Adapter } from '../adapters/adapter.ts';
2
3
  /**
3
4
  * Options for creating result tools.
@@ -9,6 +10,8 @@ export interface ResultToolsOptions {
9
10
  chatId: string;
10
11
  /** Message ID for turn-level artifact isolation */
11
12
  messageId: string;
13
+ /** Skill mounts mapping host paths to sandbox paths */
14
+ skillMounts?: SkillPathMapping[];
12
15
  }
13
16
  /**
14
17
  * Creates bash tool with integrated sql command.
@@ -16,9 +19,15 @@ export interface ResultToolsOptions {
16
19
  * The agent sees only one tool: `bash`
17
20
  * SQL is executed via: sql run "SELECT ..."
18
21
  *
19
- * Dual-level artifact storage:
20
- * - `/results/` → `./artifacts/{chatId}/{messageId}/results/` (current turn, write)
21
- * - `/artifacts/` → `./artifacts/{chatId}/` (all turns, browse previous)
22
+ * Artifact storage:
23
+ * - `/results/` → `./artifacts/{chatId}/{messageId}/results/` (current turn, isolated)
24
+ * - `/artifacts/` → `./artifacts/{chatId}/` (shared across turns)
25
+ *
26
+ * SQL results are written to both locations:
27
+ * 1. Isolated: `/results/{uuid}.json` for per-turn organization
28
+ * 2. Shared: `/artifacts/{uuid}.json` for cross-turn access
29
+ *
30
+ * The returned path is `/artifacts/{uuid}.json` which works in any turn.
22
31
  *
23
32
  * @param options - Configuration options
24
33
  * @param options.adapter - Database adapter for SQL execution
@@ -1 +1 @@
1
- {"version":3,"file":"result-tools.d.ts","sourceRoot":"","sources":["../../../src/lib/agents/result-tools.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AA4KtD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB;;;;;GAkDlE"}
1
+ {"version":3,"file":"result-tools.d.ts","sourceRoot":"","sources":["../../../src/lib/agents/result-tools.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAsKtD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB;;;;;GA0DlE"}
@@ -11,7 +11,7 @@ export interface ToSqlOptions {
11
11
  /** Instructions/teachings to include */
12
12
  instructions: ContextFragment[];
13
13
  /** Optional model override */
14
- model?: AgentModel;
14
+ model: AgentModel;
15
15
  /** Maximum retry attempts on validation failure (default: 3) */
16
16
  maxRetries?: number;
17
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sql.agent.d.ts","sourceRoot":"","sources":["../../../src/lib/agents/sql.agent.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAEL,KAAK,eAAe,EAMrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,eAAe,EAAE,eAAe,EAAE,CAAC;IACnC,wCAAwC;IACxC,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,8BAA8B;IAC9B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAiBD,QAAA,MAAM,MAAM,eAA+B,CAAC;AAC5C;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;gBACH,OAAO,EAAE,MAAM;IAK3B,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB;CAG/D;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;IAI3B,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB;CAGjE;AAED,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAgFvE"}
1
+ {"version":3,"file":"sql.agent.d.ts","sourceRoot":"","sources":["../../../src/lib/agents/sql.agent.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAEL,KAAK,eAAe,EAKrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,eAAe,EAAE,eAAe,EAAE,CAAC;IACnC,wCAAwC;IACxC,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,8BAA8B;IAC9B,KAAK,EAAE,UAAU,CAAC;IAClB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAiBD,QAAA,MAAM,MAAM,eAA+B,CAAC;AAC5C;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;gBACH,OAAO,EAAE,MAAM;IAK3B,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB;CAG/D;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;IAI3B,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB;CAGjE;AAED,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAuFvE"}
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../src/lib/instructions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EAarB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CACzB;AA0ID,wBAAgB,UAAU,CAAC,OAAO,GAAE,gBAAqB,GAAG,eAAe,EAAE,CAuQ5E"}
1
+ {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../src/lib/instructions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EAarB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CACzB;AAgJD,wBAAgB,UAAU,CAAC,OAAO,GAAE,gBAAqB,GAAG,eAAe,EAAE,CA+R5E"}
package/dist/lib/sql.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type UIMessage } from 'ai';
2
2
  import { type AgentModel } from '@deepagents/agent';
3
- import { type ContextFragment, type ContextStore } from '@deepagents/context';
3
+ import { ContextEngine, type ContextFragment } from '@deepagents/context';
4
4
  import type { Adapter } from './adapters/adapter.ts';
5
5
  import { type RenderingTools } from './agents/text2sql.agent.ts';
6
6
  import { type TeachingsOptions } from './instructions.ts';
@@ -9,10 +9,9 @@ export declare class Text2Sql {
9
9
  #private;
10
10
  constructor(config: {
11
11
  adapter: Adapter;
12
- store: ContextStore;
12
+ context: (...fragments: ContextFragment[]) => ContextEngine;
13
13
  version: string;
14
14
  tools?: RenderingTools;
15
- instructions?: ContextFragment[];
16
15
  model: AgentModel;
17
16
  /**
18
17
  * Configure teachings behavior
@@ -46,17 +45,7 @@ export declare class Text2Sql {
46
45
  * );
47
46
  */
48
47
  toPairs<T extends PairProducer>(factory: (adapter: Adapter) => T): Promise<ExtractedPair[]>;
49
- chat(messages: UIMessage[], params: {
50
- chatId: string;
51
- userId: string;
52
- }): Promise<import("ai").AsyncIterableStream<import("ai").InferUIMessageChunk<UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>>>>;
53
- /**
54
- * Developer chat interface - power-user mode for SQL generation.
55
- * Uses db_query tool for direct SQL execution (LLM writes SQL).
56
- */
57
- developer(messages: UIMessage[], params: {
58
- chatId: string;
59
- userId: string;
60
- }): Promise<import("ai").AsyncIterableStream<import("ai").InferUIMessageChunk<UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>>>>;
48
+ chat(messages: UIMessage[]): Promise<import("ai").AsyncIterableStream<import("ai").InferUIMessageChunk<UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>>>>;
49
+ developer(messages: UIMessage[]): Promise<import("ai").AsyncIterableStream<import("ai").InferUIMessageChunk<UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>>>>;
61
50
  }
62
51
  //# sourceMappingURL=sql.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../../src/lib/sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EAEf,MAAM,IAAI,CAAC;AAEZ,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,YAAY,EASlB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAIrD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,KAAK,gBAAgB,EAAc,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE7E,qBAAa,QAAQ;;gBAUP,MAAM,EAAE;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,YAAY,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,cAAc,CAAC;QACvB,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;QACjC,KAAK,EAAE,UAAU,CAAC;QAClB;;;WAGG;QACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;KACrC;IAgBY,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAclD;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAUhD;;;;;;;;;;;;;;;;;;OAkBG;IACU,OAAO,CAAC,CAAC,SAAS,YAAY,EACzC,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,CAAC,GAC/B,OAAO,CAAC,aAAa,EAAE,CAAC;IA6Bd,IAAI,CACf,QAAQ,EAAE,SAAS,EAAE,EACrB,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB;IA2EH;;;OAGG;IACU,SAAS,CACpB,QAAQ,EAAE,SAAS,EAAE,EACrB,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB;CA0DJ"}
1
+ {"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../../src/lib/sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EAEf,MAAM,IAAI,CAAC;AAEZ,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACL,aAAa,EACb,KAAK,eAAe,EAOrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAIrD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,KAAK,gBAAgB,EAAc,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE7E,qBAAa,QAAQ;;gBAUP,MAAM,EAAE;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,CAAC,GAAG,SAAS,EAAE,eAAe,EAAE,KAAK,aAAa,CAAC;QAC5D,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,cAAc,CAAC;QACvB,KAAK,EAAE,UAAU,CAAC;QAClB;;;WAGG;QACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;KACrC;IAaY,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAYlD;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAUhD;;;;;;;;;;;;;;;;;;OAkBG;IACU,OAAO,CAAC,CAAC,SAAS,YAAY,EACzC,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,CAAC,GAC/B,OAAO,CAAC,aAAa,EAAE,CAAC;IA6Bd,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE;IAwD1B,SAAS,CAAC,QAAQ,EAAE,SAAS,EAAE;CAqD7C"}
@@ -175,6 +175,7 @@ import dedent from "dedent";
175
175
  import z from "zod";
176
176
 
177
177
  // packages/context/dist/index.js
178
+ import { mergeWith } from "lodash-es";
178
179
  import { encode } from "gpt-tokenizer";
179
180
  import { generateId } from "ai";
180
181
  import pluralize from "pluralize";
@@ -361,6 +362,23 @@ function user(content) {
361
362
  }
362
363
  };
363
364
  }
365
+ function assistant(message2) {
366
+ return {
367
+ id: message2.id,
368
+ name: "assistant",
369
+ data: "content",
370
+ type: "message",
371
+ persist: true,
372
+ codec: {
373
+ decode() {
374
+ return message2;
375
+ },
376
+ encode() {
377
+ return message2;
378
+ }
379
+ }
380
+ };
381
+ }
364
382
  function message(content) {
365
383
  const message2 = typeof content === "string" ? {
366
384
  id: generateId(),
@@ -369,7 +387,7 @@ function message(content) {
369
387
  } : content;
370
388
  return {
371
389
  id: message2.id,
372
- name: "message",
390
+ name: message2.role,
373
391
  data: "content",
374
392
  type: "message",
375
393
  persist: true,
@@ -383,6 +401,18 @@ function message(content) {
383
401
  }
384
402
  };
385
403
  }
404
+ function assistantText(content, options) {
405
+ const id = options?.id ?? crypto.randomUUID();
406
+ return assistant({
407
+ id,
408
+ role: "assistant",
409
+ parts: [{ type: "text", text: content }]
410
+ });
411
+ }
412
+ var LAZY_ID = Symbol("lazy-id");
413
+ function isLazyFragment(fragment2) {
414
+ return LAZY_ID in fragment2;
415
+ }
386
416
  var ContextRenderer = class {
387
417
  options;
388
418
  constructor(options = {}) {
@@ -709,6 +739,8 @@ var ContextEngine = class {
709
739
  #branch = null;
710
740
  #chatData = null;
711
741
  #initialized = false;
742
+ /** Initial metadata to merge on first initialization */
743
+ #initialMetadata;
712
744
  constructor(options) {
713
745
  if (!options.chatId) {
714
746
  throw new Error("chatId is required");
@@ -720,6 +752,7 @@ var ContextEngine = class {
720
752
  this.#chatId = options.chatId;
721
753
  this.#userId = options.userId;
722
754
  this.#branchName = "main";
755
+ this.#initialMetadata = options.metadata;
723
756
  }
724
757
  /**
725
758
  * Initialize the chat and branch if they don't exist.
@@ -732,6 +765,15 @@ var ContextEngine = class {
732
765
  id: this.#chatId,
733
766
  userId: this.#userId
734
767
  });
768
+ if (this.#initialMetadata) {
769
+ this.#chatData = await this.#store.updateChat(this.#chatId, {
770
+ metadata: {
771
+ ...this.#chatData.metadata,
772
+ ...this.#initialMetadata
773
+ }
774
+ });
775
+ this.#initialMetadata = void 0;
776
+ }
735
777
  this.#branch = await this.#store.getActiveBranch(this.#chatId);
736
778
  this.#initialized = true;
737
779
  }
@@ -879,6 +921,12 @@ var ContextEngine = class {
879
921
  if (this.#pendingMessages.length === 0) {
880
922
  return;
881
923
  }
924
+ for (let i = 0; i < this.#pendingMessages.length; i++) {
925
+ const fragment2 = this.#pendingMessages[i];
926
+ if (isLazyFragment(fragment2)) {
927
+ this.#pendingMessages[i] = await this.#resolveLazyFragment(fragment2);
928
+ }
929
+ }
882
930
  let parentId = this.#branch.headMessageId;
883
931
  const now = Date.now();
884
932
  for (const fragment2 of this.#pendingMessages) {
@@ -898,6 +946,39 @@ var ContextEngine = class {
898
946
  this.#branch.headMessageId = parentId;
899
947
  this.#pendingMessages = [];
900
948
  }
949
+ /**
950
+ * Resolve a lazy fragment by finding the appropriate ID.
951
+ */
952
+ async #resolveLazyFragment(fragment2) {
953
+ const lazy = fragment2[LAZY_ID];
954
+ if (lazy.type === "last-assistant") {
955
+ const lastId = await this.#getLastAssistantId();
956
+ return assistantText(lazy.content, { id: lastId ?? crypto.randomUUID() });
957
+ }
958
+ throw new Error(`Unknown lazy fragment type: ${lazy.type}`);
959
+ }
960
+ /**
961
+ * Find the most recent assistant message ID (pending or persisted).
962
+ */
963
+ async #getLastAssistantId() {
964
+ for (let i = this.#pendingMessages.length - 1; i >= 0; i--) {
965
+ const msg = this.#pendingMessages[i];
966
+ if (msg.name === "assistant" && !isLazyFragment(msg)) {
967
+ return msg.id;
968
+ }
969
+ }
970
+ if (this.#branch?.headMessageId) {
971
+ const chain = await this.#store.getMessageChain(
972
+ this.#branch.headMessageId
973
+ );
974
+ for (let i = chain.length - 1; i >= 0; i--) {
975
+ if (chain[i].name === "assistant") {
976
+ return chain[i].id;
977
+ }
978
+ }
979
+ }
980
+ return void 0;
981
+ }
901
982
  /**
902
983
  * Estimate token count and cost for the full context.
903
984
  *
@@ -1166,6 +1247,36 @@ var ContextEngine = class {
1166
1247
  }
1167
1248
  this.#chatData = await this.#store.updateChat(this.#chatId, storeUpdates);
1168
1249
  }
1250
+ /**
1251
+ * Track token usage for the current chat.
1252
+ * Accumulates usage metrics in chat.metadata.usage.
1253
+ *
1254
+ * @param usage - Token usage from AI SDK (LanguageModelUsage)
1255
+ *
1256
+ * @example
1257
+ * ```ts
1258
+ * // In onFinish callback
1259
+ * const usage = await result.totalUsage;
1260
+ * await context.trackUsage(usage);
1261
+ * ```
1262
+ */
1263
+ async trackUsage(usage) {
1264
+ await this.#ensureInitialized();
1265
+ const freshChatData = await this.#store.getChat(this.#chatId);
1266
+ const currentUsage = freshChatData?.metadata?.usage ?? {};
1267
+ const updatedUsage = mergeWith(
1268
+ {},
1269
+ currentUsage,
1270
+ usage,
1271
+ (a, b) => typeof a === "number" || typeof b === "number" ? (a ?? 0) + (b ?? 0) : void 0
1272
+ );
1273
+ this.#chatData = await this.#store.updateChat(this.#chatId, {
1274
+ metadata: {
1275
+ ...freshChatData?.metadata,
1276
+ usage: updatedUsage
1277
+ }
1278
+ });
1279
+ }
1169
1280
  /**
1170
1281
  * Consolidate context fragments (no-op for now).
1171
1282
  *
@@ -1177,6 +1288,35 @@ var ContextEngine = class {
1177
1288
  consolidate() {
1178
1289
  return void 0;
1179
1290
  }
1291
+ /**
1292
+ * Extract skill path mappings from available_skills fragments.
1293
+ * Returns array of { host, sandbox } for mounting in sandbox filesystem.
1294
+ *
1295
+ * Reads the original `paths` configuration stored in fragment metadata
1296
+ * by the skills() fragment helper.
1297
+ *
1298
+ * @example
1299
+ * ```ts
1300
+ * const context = new ContextEngine({ store, chatId, userId })
1301
+ * .set(skills({ paths: [{ host: './skills', sandbox: '/skills' }] }));
1302
+ *
1303
+ * const mounts = context.getSkillMounts();
1304
+ * // [{ host: './skills', sandbox: '/skills' }]
1305
+ * ```
1306
+ */
1307
+ getSkillMounts() {
1308
+ const mounts = [];
1309
+ for (const fragment2 of this.#fragments) {
1310
+ if (fragment2.name === "available_skills" && fragment2.metadata && Array.isArray(fragment2.metadata.paths)) {
1311
+ for (const mapping of fragment2.metadata.paths) {
1312
+ if (typeof mapping === "object" && mapping !== null && typeof mapping.host === "string" && typeof mapping.sandbox === "string") {
1313
+ mounts.push({ host: mapping.host, sandbox: mapping.sandbox });
1314
+ }
1315
+ }
1316
+ }
1317
+ }
1318
+ return mounts;
1319
+ }
1180
1320
  /**
1181
1321
  * Inspect the full context state for debugging.
1182
1322
  * Returns a JSON-serializable object with context information.
@@ -1512,12 +1652,20 @@ var SqliteContextStore = class extends ContextStore {
1512
1652
  }
1513
1653
  async listChats(options) {
1514
1654
  const params = [];
1515
- let whereClause = "";
1655
+ const whereClauses = [];
1516
1656
  let limitClause = "";
1517
1657
  if (options?.userId) {
1518
- whereClause = "WHERE c.userId = ?";
1658
+ whereClauses.push("c.userId = ?");
1519
1659
  params.push(options.userId);
1520
1660
  }
1661
+ if (options?.metadata) {
1662
+ whereClauses.push(`json_extract(c.metadata, '$.' || ?) = ?`);
1663
+ params.push(options.metadata.key);
1664
+ params.push(
1665
+ typeof options.metadata.value === "boolean" ? options.metadata.value ? 1 : 0 : options.metadata.value
1666
+ );
1667
+ }
1668
+ const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
1521
1669
  if (options?.limit !== void 0) {
1522
1670
  limitClause = " LIMIT ?";
1523
1671
  params.push(options.limit);
@@ -1531,6 +1679,7 @@ var SqliteContextStore = class extends ContextStore {
1531
1679
  c.id,
1532
1680
  c.userId,
1533
1681
  c.title,
1682
+ c.metadata,
1534
1683
  c.createdAt,
1535
1684
  c.updatedAt,
1536
1685
  COUNT(DISTINCT m.id) as messageCount,
@@ -1546,6 +1695,7 @@ var SqliteContextStore = class extends ContextStore {
1546
1695
  id: row.id,
1547
1696
  userId: row.userId,
1548
1697
  title: row.title ?? void 0,
1698
+ metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
1549
1699
  messageCount: row.messageCount,
1550
1700
  branchCount: row.branchCount,
1551
1701
  createdAt: row.createdAt,
@@ -1577,9 +1727,16 @@ var SqliteContextStore = class extends ContextStore {
1577
1727
  async addMessage(message2) {
1578
1728
  this.#db.prepare(
1579
1729
  `INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)
1580
- VALUES (?, ?, ?, ?, ?, ?, ?)
1730
+ VALUES (
1731
+ ?1,
1732
+ ?2,
1733
+ CASE WHEN ?3 = ?1 THEN (SELECT parentId FROM messages WHERE id = ?1) ELSE ?3 END,
1734
+ ?4,
1735
+ ?5,
1736
+ ?6,
1737
+ ?7
1738
+ )
1581
1739
  ON CONFLICT(id) DO UPDATE SET
1582
- parentId = excluded.parentId,
1583
1740
  name = excluded.name,
1584
1741
  type = excluded.type,
1585
1742
  data = excluded.data`
@@ -2106,9 +2263,9 @@ var BaseContextualExtractor = class extends PairProducer {
2106
2263
  conversationContext: snapshot
2107
2264
  });
2108
2265
  }
2109
- const assistantText = getMessageText(message2);
2110
- if (assistantText) {
2111
- this.context.push(`Assistant: ${assistantText}`);
2266
+ const assistantText2 = getMessageText(message2);
2267
+ if (assistantText2) {
2268
+ this.context.push(`Assistant: ${assistantText2}`);
2112
2269
  }
2113
2270
  }
2114
2271
  /**
@@ -2598,7 +2755,9 @@ import {
2598
2755
  NoContentGeneratedError,
2599
2756
  NoObjectGeneratedError,
2600
2757
  NoOutputGeneratedError,
2601
- TypeValidationError
2758
+ TypeValidationError,
2759
+ defaultSettingsMiddleware,
2760
+ wrapLanguageModel
2602
2761
  } from "ai";
2603
2762
  import { Console } from "node:console";
2604
2763
  import { createWriteStream } from "node:fs";
@@ -2610,6 +2769,7 @@ var logger = new Console({
2610
2769
  stderr: createWriteStream("./sql-agent-error.log", { flags: "a" }),
2611
2770
  inspectOptions: { depth: null }
2612
2771
  });
2772
+ var RETRY_TEMPERATURES = [0, 0.2, 0.3];
2613
2773
  function extractSql(output) {
2614
2774
  const match = output.match(/```sql\n?([\s\S]*?)```/);
2615
2775
  return match ? match[1].trim() : output.trim();
@@ -2663,8 +2823,14 @@ async function toSql(options) {
2663
2823
  } else {
2664
2824
  context.set(user(options.input));
2665
2825
  }
2826
+ const temperature = RETRY_TEMPERATURES[attemptNumber - 1] ?? RETRY_TEMPERATURES[RETRY_TEMPERATURES.length - 1];
2827
+ const baseModel = options.model ?? groq6("openai/gpt-oss-20b");
2828
+ const model = wrapLanguageModel({
2829
+ model: baseModel,
2830
+ middleware: defaultSettingsMiddleware({ settings: { temperature } })
2831
+ });
2666
2832
  const sqlOutput = structuredOutput({
2667
- model: options.model ?? groq6("openai/gpt-oss-20b"),
2833
+ model,
2668
2834
  context,
2669
2835
  schema: z5.union([
2670
2836
  z5.object({