@duetso/agent 0.1.189 → 0.1.191

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 (53) hide show
  1. package/README.md +27 -0
  2. package/dist/package.json +2 -2
  3. package/dist/src/cli/help.d.ts +1 -0
  4. package/dist/src/cli/help.d.ts.map +1 -1
  5. package/dist/src/cli/help.js +43 -0
  6. package/dist/src/cli/help.js.map +1 -1
  7. package/dist/src/cli/memory-db.d.ts +6 -1
  8. package/dist/src/cli/memory-db.d.ts.map +1 -1
  9. package/dist/src/cli/memory-db.js +8 -1
  10. package/dist/src/cli/memory-db.js.map +1 -1
  11. package/dist/src/cli/memory-reflect.js +1 -1
  12. package/dist/src/cli/memory-reflect.js.map +1 -1
  13. package/dist/src/cli/train.d.ts +23 -0
  14. package/dist/src/cli/train.d.ts.map +1 -0
  15. package/dist/src/cli/train.js +356 -0
  16. package/dist/src/cli/train.js.map +1 -0
  17. package/dist/src/cli.d.ts +1 -0
  18. package/dist/src/cli.d.ts.map +1 -1
  19. package/dist/src/cli.js +6 -0
  20. package/dist/src/cli.js.map +1 -1
  21. package/dist/src/memory/context-pack.d.ts.map +1 -1
  22. package/dist/src/memory/context-pack.js +1 -0
  23. package/dist/src/memory/context-pack.js.map +1 -1
  24. package/dist/src/memory/embedding-worker.d.ts +26 -6
  25. package/dist/src/memory/embedding-worker.d.ts.map +1 -1
  26. package/dist/src/memory/embedding-worker.js +138 -61
  27. package/dist/src/memory/embedding-worker.js.map +1 -1
  28. package/dist/src/memory/loader.d.ts +4 -1
  29. package/dist/src/memory/loader.d.ts.map +1 -1
  30. package/dist/src/memory/loader.js +7 -3
  31. package/dist/src/memory/loader.js.map +1 -1
  32. package/dist/src/memory/observational.d.ts +3 -0
  33. package/dist/src/memory/observational.d.ts.map +1 -1
  34. package/dist/src/memory/observational.js +16 -0
  35. package/dist/src/memory/observational.js.map +1 -1
  36. package/dist/src/memory/session.d.ts +16 -0
  37. package/dist/src/memory/session.d.ts.map +1 -1
  38. package/dist/src/memory/session.js +24 -0
  39. package/dist/src/memory/session.js.map +1 -1
  40. package/dist/src/memory/storage.d.ts.map +1 -1
  41. package/dist/src/memory/storage.js +23 -8
  42. package/dist/src/memory/storage.js.map +1 -1
  43. package/dist/src/train/archive.d.ts +20 -0
  44. package/dist/src/train/archive.d.ts.map +1 -0
  45. package/dist/src/train/archive.js +84 -0
  46. package/dist/src/train/archive.js.map +1 -0
  47. package/dist/src/train/types.d.ts +30 -0
  48. package/dist/src/train/types.d.ts.map +1 -0
  49. package/dist/src/train/types.js +2 -0
  50. package/dist/src/train/types.js.map +1 -0
  51. package/dist/src/types/memory.d.ts +25 -9
  52. package/dist/src/types/memory.d.ts.map +1 -1
  53. package/package.json +2 -2
package/README.md CHANGED
@@ -353,6 +353,33 @@ The interactive TUI accepts image attachments (PNG, JPEG, GIF, WebP):
353
353
 
354
354
  </details>
355
355
 
356
+ <details>
357
+ <summary><b>Train a folder of docs into durable memory</b></summary>
358
+
359
+ `duet train <folder>` launches a sub-agent inside the folder, lets it read whatever is there with its native tools (markdown, CSVs, PDFs, spreadsheets, screenshots, source — anything the agent can open), and produces two artifacts:
360
+
361
+ - **One high-priority manual (user-curated) row** in `~/.duet/memory.db`, tagged `train` and `train:<slug>`. Fresh `duet` sessions load it into their initial memory pack with a ranking boost (via `manualBias`), and writing it as a `manual` row means `duet memory reflect` never compacts it away.
362
+ - **`~/.duet/train/<memory-id>/`** — a hidden archive: a copy of every source file plus a `manifest.json`. Provenance only; the DB row is the source of truth. Deleting the memory via `duet memory` removes the archive too.
363
+
364
+ ```bash
365
+ duet train ./snowflake-notes # writes to ~/.duet/memory.db
366
+ duet train ./snowflake-notes --slug snow # custom slug (default: folder basename)
367
+ duet train ./snowflake-notes --model opus-4.8
368
+ duet train ./snowflake-notes --db /tmp/scratch.db # write to a throwaway DB instead
369
+ ```
370
+
371
+ Re-running `train` on the same slug **replaces** the prior row and its archive — there is at most one `train:<slug>` observation at a time.
372
+
373
+ Three things to know:
374
+
375
+ - **The current session won't see the new memory.** Memory loads at session start. Start a fresh `duet` session to test recall.
376
+ - **Synthesis needs an API key.** `DUET_API_KEY` (recommended), or any of the provider keys covered above.
377
+ - **The corpus folder's `.env` is loaded** (so a project folder can supply its own provider credentials). Check folders you didn't author before training them.
378
+
379
+ The CLI also prints the observation content to stdout, so it's pipeable: `duet train ./docs | tee notes.txt`.
380
+
381
+ </details>
382
+
356
383
  <details>
357
384
  <summary><b>CLI Login</b></summary>
358
385
 
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duetso/agent",
3
- "version": "0.1.189",
3
+ "version": "0.1.191",
4
4
  "description": "An opinionated full-stack agent turn runner with native memories, interrupts, and multi-agent orchestration",
5
5
  "keywords": [
6
6
  "agent",
@@ -43,7 +43,7 @@
43
43
  "check-types": "tsc --noEmit",
44
44
  "cli": "bun src/cli.ts",
45
45
  "dev": "tsc --watch",
46
- "eval": "docker run --rm -v \"$PWD:/src:ro\" -w /work -e HOME=/tmp/home -e DUET_TEST_IN_DOCKER=1 oven/bun:1.3.11 sh -lc 'cp -R /src/. /work && bun install --frozen-lockfile && bun test ./evals/*.eval.ts'",
46
+ "eval": "docker run --rm -v \"$PWD:/src:ro\" -w /work -e HOME=/tmp/home -e DUET_TEST_IN_DOCKER=1 -e DUET_API_KEY -e ANTHROPIC_API_KEY -e OPENAI_API_KEY -e EVAL_MODEL -e JUDGE_MODEL -e COVERAGE_THRESHOLD oven/bun:1.3.11 sh -lc 'cp -R /src/. /work && bun install --frozen-lockfile && bun test ./evals/*.eval.ts'",
47
47
  "format": "oxfmt --write --no-error-on-unmatched-pattern",
48
48
  "format:check": "oxfmt --check --no-error-on-unmatched-pattern",
49
49
  "lint": "oxlint src/",
@@ -11,6 +11,7 @@ export declare function printEnvHelp(): void;
11
11
  export declare function printSkillsHelp(): void;
12
12
  export declare function printMemoryHelp(): void;
13
13
  export declare function printMemoryReflectHelp(): void;
14
+ export declare function printTrainHelp(): void;
14
15
  export declare function printSendFeedbackHelp(): void;
15
16
  export declare function printUpgradeHelp(packageName: string): void;
16
17
  //# sourceMappingURL=help.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/help.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAoFtD;AAED,wBAAgB,cAAc,IAAI,IAAI,CA0BrC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAsBnC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAqBtC;AAED,wBAAgB,eAAe,IAAI,IAAI,CA2BtC;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAuC7C;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAiB5C;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAe1D"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/help.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAqFtD;AAED,wBAAgB,cAAc,IAAI,IAAI,CA0BrC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAsBnC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAqBtC;AAED,wBAAgB,eAAe,IAAI,IAAI,CA2BtC;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAuC7C;AAED,wBAAgB,cAAc,IAAI,IAAI,CAyCrC;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAiB5C;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAe1D"}
@@ -87,6 +87,7 @@ EXAMPLES
87
87
  duet login
88
88
  duet env
89
89
  duet memory
90
+ duet train ./docs/my-project
90
91
  duet send-feedback "the TUI flickers when..."
91
92
  duet upgrade
92
93
  `);
@@ -231,6 +232,48 @@ OPTIONS
231
232
  -h, --help Show this help
232
233
  `);
233
234
  }
235
+ export function printTrainHelp() {
236
+ console.log(`
237
+ duet train — Ingest a project corpus into one durable memory observation
238
+
239
+ USAGE
240
+ duet train <folder> [--slug <name>] [--model <name>] [--db <path>] [--wait <seconds>]
241
+
242
+ DESCRIPTION
243
+ Launches a duet agent with the corpus folder as its working directory.
244
+ The agent reads the corpus using its native file-reading tools (any
245
+ format the duet agent normally reads — markdown, plain text, CSVs, PDFs,
246
+ spreadsheets, source code) and writes a single handoff file at the
247
+ corpus root:
248
+
249
+ .duet-train.json — structured handoff with headline + observation.
250
+
251
+ 'train' then persists the synthesis into ~/.duet/memory.db as a manual
252
+ (user-curated) row (tagged 'train' and 'train:<slug>'), archives the
253
+ corpus under ~/.duet/train/<memory-id>/, removes the handoff file, and
254
+ prints the observation content to stdout so what you see is what landed
255
+ in memory.
256
+
257
+ Subsequent runs against the same slug replace the prior row in place,
258
+ so the memory pool does not bloat. Writing the row as a manual row
259
+ earns it a ranking boost in the memory pack (via manualBias) and exempts
260
+ it from 'duet memory reflect' compaction; deleting it via 'duet memory'
261
+ also removes its archive. Note: train loads the corpus folder's .env (for provider
262
+ credentials), so check folders you did not author before training.
263
+
264
+ OPTIONS
265
+ --slug <name> Override the corpus slug (default: sanitized folder basename)
266
+ --model <name> Model used by the synthesis sub-agent (default: same resolution as 'duet run')
267
+ --db <path> Memory database path (default: ~/.duet/memory.db)
268
+ --wait <seconds> Seconds to wait for the cross-process open-lock
269
+ (default: 30; 0 fails immediately)
270
+ -h, --help Show this help
271
+
272
+ EXAMPLES
273
+ duet train ./docs/my-project
274
+ duet train ./research --slug acme-research --model sonnet-4.6
275
+ `);
276
+ }
234
277
  export function printSendFeedbackHelp() {
235
278
  console.log(`
236
279
  duet send-feedback — Send free-form markdown feedback to the Duet team
@@ -1 +1 @@
1
- {"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AAEjD,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;gDAmBkC,WAAW;;;;;;;;;;;;;gHAaqD,+BAA+B;;;;;oFAK3D,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6CxG,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;wEAW0D,qBAAqB;;;;;;;;;;;;;CAa5F,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;yDAa2C,qBAAqB;;;;;;IAM1E,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;CAChC,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;CAmBb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;CAyBb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;CAeb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,OAAO,CAAC,GAAG,CAAC;oCACsB,WAAW;;;;;;;;;;;;CAY9C,CAAC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AAEjD,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;gDAmBkC,WAAW;;;;;;;;;;;;;gHAaqD,+BAA+B;;;;;oFAK3D,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CxG,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;wEAW0D,qBAAqB;;;;;;;;;;;;;CAa5F,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;yDAa2C,qBAAqB;;;;;;IAM1E,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;CAChC,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;CAmBb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;CAyBb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;CAeb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,OAAO,CAAC,GAAG,CAAC;oCACsB,WAAW;;;;;;;;;;;;CAY9C,CAAC,CAAC;AACH,CAAC"}
@@ -52,7 +52,12 @@ export declare class MemoryDb {
52
52
  }): Promise<Observation[]>;
53
53
  /** Replace just the `content` of an observation, preserving everything else. */
54
54
  updateContent(id: string, content: string): Promise<void>;
55
- /** Permanently remove an observation. There is no undo. */
55
+ /**
56
+ * Permanently remove an observation. There is no undo. Rows written by
57
+ * `duet train` keep a corpus archive under `~/.duet/train/<id>/` that
58
+ * shares the row's lifecycle, so it is removed too (a no-op for every
59
+ * other row — there is simply no directory to delete).
60
+ */
56
61
  delete(id: string): Promise<void>;
57
62
  close(): Promise<void>;
58
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"memory-db.d.ts","sourceRoot":"","sources":["../../../src/cli/memory-db.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAK3F;AAED;;;;GAIG;AACH,qBAAa,QAAQ;IACC,OAAO,CAAC,QAAQ,CAAC,EAAE;IAAvC,OAAO;IAEP;;;;;;;;;OASG;WACU,IAAI,CACf,IAAI,EAAE,MAAM,EACZ,EAAE,YAA+C,EAAE,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO,GAClF,OAAO,CAAC,QAAQ,CAAC;IAiBpB,yDAAyD;IACnD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAO9B;;;;;;;;;;;;OAYG;IACG,UAAU,CAAC,EACf,KAAK,EACL,MAAM,EACN,GAAgB,GACjB,EAAE;QACD,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IA6B1B,gFAAgF;IAC1E,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,2DAA2D;IACrD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
1
+ {"version":3,"file":"memory-db.d.ts","sourceRoot":"","sources":["../../../src/cli/memory-db.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAK3F;AAED;;;;GAIG;AACH,qBAAa,QAAQ;IACC,OAAO,CAAC,QAAQ,CAAC,EAAE;IAAvC,OAAO;IAEP;;;;;;;;;OASG;WACU,IAAI,CACf,IAAI,EAAE,MAAM,EACZ,EAAE,YAA+C,EAAE,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO,GAClF,OAAO,CAAC,QAAQ,CAAC;IAiBpB,yDAAyD;IACnD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAO9B;;;;;;;;;;;;OAYG;IACG,UAAU,CAAC,EACf,KAAK,EACL,MAAM,EACN,GAAgB,GACjB,EAAE;QACD,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IA6B1B,gFAAgF;IAC1E,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D;;;;;OAKG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
@@ -2,6 +2,7 @@ import { observationScore, PRIORITY_WEIGHT } from "../memory/loader.js";
2
2
  import { runMigrations } from "../memory/migrations.js";
3
3
  import { DEFAULT_RECENCY_HALF_LIFE_MS, DEFAULT_REFLECTION_BIAS } from "../memory/observational.js";
4
4
  import { DEFAULT_OPEN_LOCK_WAIT_BUDGET_MS, openPGliteWaitingForLock } from "../memory/pglite.js";
5
+ import { removeArchive } from "../train/archive.js";
5
6
  /** Rows fetched per page by the ranked, lazily-paginated TUI list. */
6
7
  export const MEMORY_PAGE_SIZE = 25;
7
8
  /**
@@ -96,9 +97,15 @@ export class MemoryDb {
96
97
  async updateContent(id, content) {
97
98
  await this.db.query(`UPDATE observations SET content = $1 WHERE id = $2`, [content, id]);
98
99
  }
99
- /** Permanently remove an observation. There is no undo. */
100
+ /**
101
+ * Permanently remove an observation. There is no undo. Rows written by
102
+ * `duet train` keep a corpus archive under `~/.duet/train/<id>/` that
103
+ * shares the row's lifecycle, so it is removed too (a no-op for every
104
+ * other row — there is simply no directory to delete).
105
+ */
100
106
  async delete(id) {
101
107
  await this.db.query(`DELETE FROM observations WHERE id = $1`, [id]);
108
+ await removeArchive(id);
102
109
  }
103
110
  async close() {
104
111
  await this.db.close();
@@ -1 +1 @@
1
- {"version":3,"file":"memory-db.js","sourceRoot":"","sources":["../../../src/cli/memory-db.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory-db.js","sourceRoot":"","sources":["../../../src/cli/memory-db.ts"],"names":[],"mappings":"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"}
@@ -25,7 +25,7 @@ export async function runMemoryReflectCommand(args, io = { stdout: process.stdou
25
25
  await runMigrations(db);
26
26
  },
27
27
  },
28
- ...(options.waitBudgetMs !== undefined ? { waitBudgetMs: options.waitBudgetMs } : {}),
28
+ ...(options.waitBudgetMs !== undefined ? { lockWaitBudgetMs: options.waitBudgetMs } : {}),
29
29
  idleCloseMs: 60_000,
30
30
  });
31
31
  const removeShutdownHandlers = installShutdownHandlers(() => session.dispose());
@@ -1 +1 @@
1
- {"version":3,"file":"memory-reflect.js","sourceRoot":"","sources":["../../../src/cli/memory-reflect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory-reflect.js","sourceRoot":"","sources":["../../../src/cli/memory-reflect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface TrainCommandOptions {
2
+ folder: string;
3
+ slug: string;
4
+ /** Undefined means "resolve at run time via resolveCliModel". */
5
+ model: string | undefined;
6
+ dbPath: string;
7
+ waitBudgetMs?: number;
8
+ }
9
+ interface TrainCommandIO {
10
+ stdout: NodeJS.WritableStream;
11
+ stderr: NodeJS.WritableStream;
12
+ }
13
+ export declare function parseTrainArgs(args: string[]): TrainCommandOptions | undefined;
14
+ /**
15
+ * Run `duet train <folder>` — launch a sub-agent that reads the corpus
16
+ * and writes a structured handoff file (.duet-train.json), persist the
17
+ * synthesized observation into durable memory (replacing any prior
18
+ * `train:<slug>` row), archive the corpus under `~/.duet/train/<memoryId>/`,
19
+ * and verify both side effects landed.
20
+ */
21
+ export declare function runTrainCommand(args: string[], io?: TrainCommandIO): Promise<void>;
22
+ export {};
23
+ //# sourceMappingURL=train.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"train.d.ts","sourceRoot":"","sources":["../../../src/cli/train.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;CAC/B;AAcD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,mBAAmB,GAAG,SAAS,CA0D9E;AA8ID;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,cAAmE,GACtE,OAAO,CAAC,IAAI,CAAC,CAyJf"}
@@ -0,0 +1,356 @@
1
+ import { readFile, rm, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import dedent from "dedent";
4
+ import { runMigrations } from "../memory/migrations.js";
5
+ import { MemoryLockTimeoutError } from "../memory/pglite.js";
6
+ import { MemorySession } from "../memory/session.js";
7
+ import { appendObservation } from "../memory/storage.js";
8
+ import { resolveCliModel } from "../model-resolution/resolver.js";
9
+ import { DEFAULT_MEMORY_DB_PATH, SessionManager } from "../session/session-manager.js";
10
+ import { collectArchiveFiles, removeArchive, writeArchive } from "../train/archive.js";
11
+ import { printTrainHelp } from "./help.js";
12
+ import { fail, loadCliEnvFiles, resolveUserPath } from "./shared.js";
13
+ import { installShutdownHandlers } from "./shutdown.js";
14
+ /**
15
+ * Lowercase a base name and collapse anything that isn't a-z/0-9 into
16
+ * single dashes so the slug can serve as a tag (`train:<slug>`) and a
17
+ * folder name without quoting.
18
+ */
19
+ function sanitizeSlug(name) {
20
+ return name
21
+ .toLowerCase()
22
+ .replace(/[^a-z0-9-]+/g, "-")
23
+ .replace(/^-+|-+$/g, "");
24
+ }
25
+ export function parseTrainArgs(args) {
26
+ let folder;
27
+ let slugOverride;
28
+ // Default model is resolved at run time via `resolveCliModel`, mirroring
29
+ // `duet run`'s actor model selection. Env var `DUET_MODEL` is honored by
30
+ // the resolver itself; we keep `--model` as the user's explicit override.
31
+ let model;
32
+ let dbPath = DEFAULT_MEMORY_DB_PATH;
33
+ let waitBudgetMs;
34
+ for (let i = 0; i < args.length; i++) {
35
+ const arg = args[i];
36
+ switch (arg) {
37
+ case "--slug":
38
+ if (!args[i + 1] || args[i + 1]?.startsWith("-"))
39
+ fail(`Missing value for ${arg}`);
40
+ slugOverride = args[++i];
41
+ break;
42
+ case "--model":
43
+ if (!args[i + 1] || args[i + 1]?.startsWith("-"))
44
+ fail(`Missing value for ${arg}`);
45
+ model = args[++i];
46
+ break;
47
+ case "--db":
48
+ if (!args[i + 1] || args[i + 1]?.startsWith("-"))
49
+ fail(`Missing value for ${arg}`);
50
+ dbPath = resolveUserPath(args[++i]);
51
+ break;
52
+ case "--wait": {
53
+ const raw = args[++i];
54
+ const seconds = Number(raw);
55
+ if (!Number.isFinite(seconds) || seconds < 0) {
56
+ fail(`Invalid --wait value: ${raw} (expected non-negative number of seconds)`);
57
+ }
58
+ waitBudgetMs = Math.round(seconds * 1000);
59
+ break;
60
+ }
61
+ case "--help":
62
+ case "-h":
63
+ printTrainHelp();
64
+ return undefined;
65
+ default:
66
+ if (arg.startsWith("-"))
67
+ fail(`Unknown train option: ${arg}`);
68
+ if (folder !== undefined)
69
+ fail(`Unexpected extra argument: ${arg}`);
70
+ folder = arg;
71
+ }
72
+ }
73
+ if (!folder)
74
+ fail("duet train requires a <folder> argument");
75
+ const resolved = path.resolve(folder);
76
+ const slug = sanitizeSlug(slugOverride ?? path.basename(resolved));
77
+ if (slug.length === 0) {
78
+ fail(`Could not derive a slug from "${folder}"; pass --slug <name>`);
79
+ }
80
+ return {
81
+ folder: resolved,
82
+ slug,
83
+ model,
84
+ dbPath,
85
+ ...(waitBudgetMs !== undefined ? { waitBudgetMs } : {}),
86
+ };
87
+ }
88
+ /**
89
+ * Verbatim system prompt for the synthesis sub-agent. The agent's cwd is
90
+ * the corpus folder, so file-reading tools resolve relative paths against
91
+ * it directly.
92
+ */
93
+ const TRAIN_SYSTEM_PROMPT = dedent `
94
+ You are synthesizing a project corpus into a single durable memory
95
+ observation.
96
+
97
+ The working directory IS the corpus. Read every file that looks
98
+ substantive — markdown, plain text, CSVs, PDFs, spreadsheets, images,
99
+ source code. Skip lockfiles, build artifacts, node_modules, .git, and
100
+ other obvious noise. Use your file-reading tools (read, ls, grep) to
101
+ explore until you understand what this corpus is about.
102
+
103
+ Extract EXHAUSTIVELY, not as a summary. A weaker reader of this corpus
104
+ tends to keep the headline claim and silently drop the specifics fused
105
+ to it — that is the failure to avoid. As you read, preserve EVERY
106
+ load-bearing concrete fact:
107
+ - Every number, quantity, percentage, version, and date — including
108
+ the second and third value in any enumeration (if a fact says
109
+ "X across A, B, and C", keep A, B, AND C, never just A).
110
+ - Every named feature, product, option, tool, attribute, and API —
111
+ by its exact name, not a generic paraphrase.
112
+ - Every member of a list, and the qualifier attached to each member
113
+ (if every option "supports both X and Y", state that for the set).
114
+ - Exact syntax, identifiers, code values, and config snippets as
115
+ written (e.g. a property name and its literal example value).
116
+ Never collapse an enumeration to its first item and never generalize a
117
+ specific into a category. When in doubt, include the detail.
118
+
119
+ When you have read enough to write an accurate synthesis, produce
120
+ EXACTLY one file at the cwd root and nothing else:
121
+
122
+ \`.duet-train.json\` — a JSON object with exactly two string fields:
123
+ {
124
+ "headline": "<short title for this corpus, under 120 characters, no trailing punctuation>",
125
+ "observationContent": "<dense, concrete, durable, high-priority knowledge an agent would need to act on this material. Use as much length as it takes to retain every load-bearing fact above — completeness beats brevity — but keep it a single standalone memory entry of tight prose, not a document dump. No preamble, no 'this corpus contains' framing.>"
126
+ }
127
+
128
+ Do NOT write \`AGENTS.md\` or any other file. The JSON handoff is the
129
+ only deliverable. Neither field may be empty. After writing the file,
130
+ stop. You do not need to say anything else.
131
+ `;
132
+ /**
133
+ * Launch the duet agent inside the corpus folder and let it produce a
134
+ * `.duet-train.json` handoff file. Returns the parsed synthesis result.
135
+ * The handoff file is removed before launch (so a leftover from a failed
136
+ * run can't be mistaken for fresh output) and after a successful read
137
+ * (so it doesn't leak into the corpus or the archive).
138
+ */
139
+ async function runAgentSynthesis(options, io) {
140
+ const handoffPath = path.join(options.folder, ".duet-train.json");
141
+ await rm(handoffPath, { force: true });
142
+ const config = {
143
+ cwd: options.folder,
144
+ model: options.model,
145
+ // Don't write to the durable memory DB during synthesis; the train
146
+ // command owns the single observation row that lands at the end.
147
+ memoryDbPath: false,
148
+ // Synthesis must not be steered by the corpus's own AGENTS.md (if
149
+ // present) — the agent reads files as data, not as instructions.
150
+ systemPromptFiles: [],
151
+ // Avoid local user-skill drift influencing what the sub-agent does.
152
+ skillDiscovery: { includeDefaults: false },
153
+ systemInstructions: TRAIN_SYSTEM_PROMPT,
154
+ mode: "agent",
155
+ };
156
+ const manager = new SessionManager(config);
157
+ // Quietly surface what the sub-agent is doing so a long synthesis run
158
+ // doesn't look frozen. We only relay tool calls (the visible work) and
159
+ // any system-level messages; assistant text and reasoning are skipped.
160
+ const unsubscribe = manager.subscribe(({ event }) => {
161
+ if (event.type === "step") {
162
+ const step = event.step;
163
+ if (step.type === "tool_call" && step.status === "running") {
164
+ io.stderr.write(`[agent] ${step.toolName}\n`);
165
+ }
166
+ else if (step.type === "system") {
167
+ io.stderr.write(`[agent] ${step.message}\n`);
168
+ }
169
+ }
170
+ else if (event.type === "system") {
171
+ io.stderr.write(`[agent] ${event.message}\n`);
172
+ }
173
+ });
174
+ try {
175
+ const session = manager.create({
176
+ prompt: `Synthesize the corpus in this directory. Slug: ${options.slug}.`,
177
+ });
178
+ const terminal = await session.waitForTerminal();
179
+ if (terminal.type !== "complete") {
180
+ throw new Error(`train: agent terminated with type=${terminal.type}; expected "complete"`);
181
+ }
182
+ }
183
+ finally {
184
+ unsubscribe();
185
+ await manager.dispose();
186
+ }
187
+ const raw = await readFile(handoffPath, "utf8").catch(() => {
188
+ throw new Error(`train: agent did not produce ${handoffPath}. Re-run with --model <stronger model> if the model is too small.`);
189
+ });
190
+ await rm(handoffPath, { force: true });
191
+ let parsed;
192
+ try {
193
+ parsed = JSON.parse(raw);
194
+ }
195
+ catch (err) {
196
+ throw new Error(`train: .duet-train.json was not valid JSON: ${err.message}`);
197
+ }
198
+ if (!parsed || typeof parsed !== "object") {
199
+ throw new Error(`train: .duet-train.json must be a JSON object, got ${typeof parsed}`);
200
+ }
201
+ const { headline, observationContent } = parsed;
202
+ if (typeof headline !== "string" || headline.trim().length === 0) {
203
+ throw new Error(`train: .duet-train.json missing non-empty string "headline"`);
204
+ }
205
+ if (typeof observationContent !== "string" || observationContent.trim().length === 0) {
206
+ throw new Error(`train: .duet-train.json missing non-empty string "observationContent"`);
207
+ }
208
+ return {
209
+ headline: headline.trim(),
210
+ observationContent: observationContent.trim(),
211
+ };
212
+ }
213
+ /**
214
+ * Run `duet train <folder>` — launch a sub-agent that reads the corpus
215
+ * and writes a structured handoff file (.duet-train.json), persist the
216
+ * synthesized observation into durable memory (replacing any prior
217
+ * `train:<slug>` row), archive the corpus under `~/.duet/train/<memoryId>/`,
218
+ * and verify both side effects landed.
219
+ */
220
+ export async function runTrainCommand(args, io = { stdout: process.stdout, stderr: process.stderr }) {
221
+ const options = parseTrainArgs(args);
222
+ if (!options)
223
+ return;
224
+ // Post-parse failures throw instead of calling `fail()`: the CLI entry
225
+ // (`runCli`) prints them identically, while in-process callers (the
226
+ // eval harness, the model sweep) can catch them and run their cleanup.
227
+ const folderStat = await stat(options.folder).catch(() => undefined);
228
+ if (!folderStat || !folderStat.isDirectory()) {
229
+ throw new Error(`Folder not found or not a directory: ${options.folder}`);
230
+ }
231
+ // Resolve the model the same way `duet run` does so shorthands and
232
+ // provider routing behave identically. Env files in the corpus folder
233
+ // can supply provider credentials; load them before resolution.
234
+ const dotenvKeys = loadCliEnvFiles(options.folder);
235
+ const modelResolution = resolveCliModel(options.model, dotenvKeys);
236
+ const resolvedModel = modelResolution.modelName;
237
+ const session = new MemorySession({
238
+ path: options.dbPath,
239
+ openOptions: {
240
+ init: async (db) => {
241
+ await runMigrations(db);
242
+ },
243
+ },
244
+ ...(options.waitBudgetMs !== undefined ? { lockWaitBudgetMs: options.waitBudgetMs } : {}),
245
+ idleCloseMs: 60_000,
246
+ });
247
+ const removeShutdownHandlers = installShutdownHandlers(() => session.dispose());
248
+ try {
249
+ await session.withDb(async () => { });
250
+ io.stderr.write(`[synthesize] model=${resolvedModel}\n`);
251
+ const synthesis = await runAgentSynthesis({ folder: options.folder, slug: options.slug, model: resolvedModel }, io);
252
+ // Insert the new row BEFORE deleting priors: if the process dies
253
+ // between the two steps the worst case is a duplicate `train:<slug>`
254
+ // row (cleaned up by the next train run), never zero rows. The row is
255
+ // written as `kind: "manual"` so the loader's manualBias ranks it at
256
+ // the top of the global pack (a manual row with no sessionId never
257
+ // matches a live session, so it lands in the global pack via the
258
+ // loader's NULL-session handling), and `duet memory reflect`'s prune
259
+ // preserves it by kind regardless of age.
260
+ const trainTag = `train:${options.slug}`;
261
+ const observedDate = new Date().toISOString().slice(0, 10);
262
+ const observation = await appendObservation(session, {
263
+ kind: "manual",
264
+ priority: "high",
265
+ source: { kind: "system" },
266
+ content: synthesis.observationContent,
267
+ tags: ["train", trainTag],
268
+ observedDate,
269
+ });
270
+ if (!observation) {
271
+ throw new Error(`Could not write training memory to ${options.dbPath} (lock contention).`);
272
+ }
273
+ // SELECT + DELETE share one `withDb` so the replace step is atomic
274
+ // against peer writers and lock failure surfaces in one place.
275
+ // Invariant after this block: exactly one `train:<slug>` row — the
276
+ // one written above.
277
+ const priorIds = await session.withDb(async (db) => {
278
+ const result = await db.query("SELECT id, tags_json FROM observations");
279
+ const ids = [];
280
+ for (const row of result.rows) {
281
+ if (row.id === observation.id)
282
+ continue;
283
+ let tags;
284
+ try {
285
+ tags = JSON.parse(row.tags_json);
286
+ }
287
+ catch {
288
+ continue;
289
+ }
290
+ if (Array.isArray(tags) && tags.includes(trainTag)) {
291
+ ids.push(row.id);
292
+ }
293
+ }
294
+ for (const id of ids) {
295
+ await db.query("DELETE FROM observations WHERE id = $1", [id]);
296
+ }
297
+ return ids;
298
+ });
299
+ if (priorIds === undefined) {
300
+ throw new Error(`Could not remove prior training rows from ${options.dbPath} (lock contention); ` +
301
+ `the new row ${observation.id} was written. Re-run train to clean up the duplicate.`);
302
+ }
303
+ for (const id of priorIds) {
304
+ await removeArchive(id);
305
+ }
306
+ const replacedSuffix = priorIds.length > 0 ? ` (replaced ${priorIds.length} prior row(s))` : "";
307
+ io.stderr.write(`[persist] memory id=${observation.id}${replacedSuffix}\n`);
308
+ // `runAgentSynthesis` already removed `.duet-train.json`; the
309
+ // walker's skip list is defense in depth.
310
+ const archivedFiles = await collectArchiveFiles(options.folder);
311
+ const manifest = {
312
+ memoryId: observation.id,
313
+ slug: options.slug,
314
+ createdAt: observation.createdAt,
315
+ sourceFolder: options.folder,
316
+ model: resolvedModel,
317
+ headline: synthesis.headline,
318
+ files: archivedFiles.map((file) => ({
319
+ relPath: file.relPath,
320
+ bytes: file.bytes,
321
+ sha256: file.sha256,
322
+ })),
323
+ };
324
+ const archivePath = await writeArchive({
325
+ memoryId: observation.id,
326
+ files: archivedFiles,
327
+ manifest,
328
+ });
329
+ const verifyRows = await session.withDb(async (db) => db.query("SELECT content FROM observations WHERE id = $1", [
330
+ observation.id,
331
+ ]));
332
+ if (verifyRows === undefined) {
333
+ throw new Error(`Could not verify training memory at ${options.dbPath} (lock contention).`);
334
+ }
335
+ if (verifyRows.rows[0]?.content !== synthesis.observationContent) {
336
+ throw new Error(`Verification failed: observation ${observation.id} did not round-trip through the DB.`);
337
+ }
338
+ io.stdout.write(`Trained "${synthesis.headline}"\n`);
339
+ io.stdout.write(` memory id : ${observation.id}\n`);
340
+ io.stdout.write(` archive : ${archivePath}\n`);
341
+ io.stdout.write(` files : ${archivedFiles.length} file(s)\n`);
342
+ io.stdout.write(` model : ${resolvedModel}\n`);
343
+ io.stdout.write(`\n${synthesis.observationContent}\n`);
344
+ }
345
+ catch (error) {
346
+ if (error instanceof MemoryLockTimeoutError) {
347
+ throw new Error(`Memory database at ${error.dataDir} is still locked by duet pid ${error.holderPid} after ${error.budgetMs / 1000}s. Stop that process (or pass --wait <seconds> to wait longer) and retry.`);
348
+ }
349
+ throw error;
350
+ }
351
+ finally {
352
+ removeShutdownHandlers();
353
+ await session.dispose();
354
+ }
355
+ }
356
+ //# sourceMappingURL=train.js.map