@duetso/agent 0.2.5 → 0.3.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 (122) hide show
  1. package/README.md +15 -12
  2. package/dist/package.json +8 -3
  3. package/dist/src/cli/help.d.ts.map +1 -1
  4. package/dist/src/cli/help.js +41 -27
  5. package/dist/src/cli/help.js.map +1 -1
  6. package/dist/src/cli/memory-add.d.ts +18 -13
  7. package/dist/src/cli/memory-add.d.ts.map +1 -1
  8. package/dist/src/cli/memory-add.js +91 -32
  9. package/dist/src/cli/memory-add.js.map +1 -1
  10. package/dist/src/cli/memory-recall.d.ts.map +1 -1
  11. package/dist/src/cli/memory-recall.js +3 -0
  12. package/dist/src/cli/memory-recall.js.map +1 -1
  13. package/dist/src/cli/memory-sources.d.ts +20 -0
  14. package/dist/src/cli/memory-sources.d.ts.map +1 -0
  15. package/dist/src/cli/memory-sources.js +40 -0
  16. package/dist/src/cli/memory-sources.js.map +1 -0
  17. package/dist/src/cli/route.d.ts +2 -0
  18. package/dist/src/cli/route.d.ts.map +1 -1
  19. package/dist/src/cli/route.js +8 -8
  20. package/dist/src/cli/route.js.map +1 -1
  21. package/dist/src/cli/rpc.d.ts +3 -2
  22. package/dist/src/cli/rpc.d.ts.map +1 -1
  23. package/dist/src/cli/rpc.js +3 -2
  24. package/dist/src/cli/rpc.js.map +1 -1
  25. package/dist/src/cli/run.d.ts +1 -0
  26. package/dist/src/cli/run.d.ts.map +1 -1
  27. package/dist/src/cli/run.js +1 -0
  28. package/dist/src/cli/run.js.map +1 -1
  29. package/dist/src/cli/train.d.ts +31 -7
  30. package/dist/src/cli/train.d.ts.map +1 -1
  31. package/dist/src/cli/train.js +233 -79
  32. package/dist/src/cli/train.js.map +1 -1
  33. package/dist/src/memory/context-pack.d.ts +5 -0
  34. package/dist/src/memory/context-pack.d.ts.map +1 -1
  35. package/dist/src/memory/context-pack.js +6 -0
  36. package/dist/src/memory/context-pack.js.map +1 -1
  37. package/dist/src/memory/id.d.ts +3 -0
  38. package/dist/src/memory/id.d.ts.map +1 -0
  39. package/dist/src/memory/id.js +6 -0
  40. package/dist/src/memory/id.js.map +1 -0
  41. package/dist/src/memory/observational-prompts.d.ts +2 -0
  42. package/dist/src/memory/observational-prompts.d.ts.map +1 -1
  43. package/dist/src/memory/observational-prompts.js +4 -2
  44. package/dist/src/memory/observational-prompts.js.map +1 -1
  45. package/dist/src/memory/observational.d.ts +22 -0
  46. package/dist/src/memory/observational.d.ts.map +1 -1
  47. package/dist/src/memory/observational.js +65 -22
  48. package/dist/src/memory/observational.js.map +1 -1
  49. package/dist/src/memory/paths.d.ts +9 -0
  50. package/dist/src/memory/paths.d.ts.map +1 -0
  51. package/dist/src/memory/paths.js +11 -0
  52. package/dist/src/memory/paths.js.map +1 -0
  53. package/dist/src/memory/storage.d.ts.map +1 -1
  54. package/dist/src/memory/storage.js +1 -4
  55. package/dist/src/memory/storage.js.map +1 -1
  56. package/dist/src/memory/store/discovery.d.ts +7 -0
  57. package/dist/src/memory/store/discovery.d.ts.map +1 -0
  58. package/dist/src/memory/store/discovery.js +34 -0
  59. package/dist/src/memory/store/discovery.js.map +1 -0
  60. package/dist/src/memory/store/file.d.ts +52 -0
  61. package/dist/src/memory/store/file.d.ts.map +1 -0
  62. package/dist/src/memory/store/file.js +287 -0
  63. package/dist/src/memory/store/file.js.map +1 -0
  64. package/dist/src/memory/store/index.d.ts +5 -0
  65. package/dist/src/memory/store/index.d.ts.map +1 -0
  66. package/dist/src/memory/store/index.js +5 -0
  67. package/dist/src/memory/store/index.js.map +1 -0
  68. package/dist/src/memory/store/pack.d.ts +25 -0
  69. package/dist/src/memory/store/pack.d.ts.map +1 -0
  70. package/dist/src/memory/store/pack.js +71 -0
  71. package/dist/src/memory/store/pack.js.map +1 -0
  72. package/dist/src/memory/store/sources.d.ts +55 -0
  73. package/dist/src/memory/store/sources.d.ts.map +1 -0
  74. package/dist/src/memory/store/sources.js +85 -0
  75. package/dist/src/memory/store/sources.js.map +1 -0
  76. package/dist/src/memory/store/store.d.ts +46 -0
  77. package/dist/src/memory/store/store.d.ts.map +1 -0
  78. package/dist/src/memory/store/store.js +171 -0
  79. package/dist/src/memory/store/store.js.map +1 -0
  80. package/dist/src/memory/store.d.ts +19 -16
  81. package/dist/src/memory/store.d.ts.map +1 -1
  82. package/dist/src/memory/store.js +14 -11
  83. package/dist/src/memory/store.js.map +1 -1
  84. package/dist/src/memory-store.js +554 -0
  85. package/dist/src/model-routing/advisor-context.d.ts +31 -5
  86. package/dist/src/model-routing/advisor-context.d.ts.map +1 -1
  87. package/dist/src/model-routing/advisor-context.js +87 -10
  88. package/dist/src/model-routing/advisor-context.js.map +1 -1
  89. package/dist/src/model-routing/advisor-lifecycle.d.ts +14 -5
  90. package/dist/src/model-routing/advisor-lifecycle.d.ts.map +1 -1
  91. package/dist/src/model-routing/advisor-lifecycle.js +24 -7
  92. package/dist/src/model-routing/advisor-lifecycle.js.map +1 -1
  93. package/dist/src/model-routing/prompts.d.ts.map +1 -1
  94. package/dist/src/model-routing/prompts.js +18 -10
  95. package/dist/src/model-routing/prompts.js.map +1 -1
  96. package/dist/src/session/session-manager.d.ts +1 -4
  97. package/dist/src/session/session-manager.d.ts.map +1 -1
  98. package/dist/src/session/session-manager.js +2 -5
  99. package/dist/src/session/session-manager.js.map +1 -1
  100. package/dist/src/session/session.d.ts +2 -2
  101. package/dist/src/session/session.js +2 -2
  102. package/dist/src/train/archive.d.ts.map +1 -1
  103. package/dist/src/train/archive.js +5 -0
  104. package/dist/src/train/archive.js.map +1 -1
  105. package/dist/src/train/types.d.ts +8 -7
  106. package/dist/src/train/types.d.ts.map +1 -1
  107. package/dist/src/turn-runner/tools.d.ts +3 -3
  108. package/dist/src/turn-runner/tools.d.ts.map +1 -1
  109. package/dist/src/turn-runner/tools.js +1 -1
  110. package/dist/src/turn-runner/tools.js.map +1 -1
  111. package/dist/src/turn-runner/turn-runner.d.ts +15 -2
  112. package/dist/src/turn-runner/turn-runner.d.ts.map +1 -1
  113. package/dist/src/turn-runner/turn-runner.js +102 -15
  114. package/dist/src/turn-runner/turn-runner.js.map +1 -1
  115. package/dist/src/turn-runner/wire-shaping.d.ts +3 -1
  116. package/dist/src/turn-runner/wire-shaping.d.ts.map +1 -1
  117. package/dist/src/turn-runner/wire-shaping.js +5 -1
  118. package/dist/src/turn-runner/wire-shaping.js.map +1 -1
  119. package/dist/src/types/config.d.ts +7 -0
  120. package/dist/src/types/config.d.ts.map +1 -1
  121. package/dist/src/types/protocol.d.ts +2 -2
  122. package/package.json +8 -3
package/README.md CHANGED
@@ -56,7 +56,7 @@ Two things that don't get a section of their own below, but that follow from the
56
56
 
57
57
  ### Memory, woven in
58
58
 
59
- Memory and compaction are the same primitive: observational memory _is_ how context survives between turns. The runner observes its own transcript, reflects when observations grow, and writes durable rows to PGlite — text observations for messages and images alike, so screenshots and UI captures stay recallable on later turns without re-attaching bytes. Each turn's prompt prefix is a frozen two-layer pack (long-term cross-session memory + this session's compaction summary), rebuilt only at compaction events so the provider's prompt cache survives turn-over-turn. Anything that didn't make the pack stays reachable through `recall_memory` — hybrid retrieval over pgvector cosine similarity and tsvector keyword search, fused via Reciprocal Rank Fusion, with optional paraphrased query expansion. Embeddings run in a background worker so foreground turns never block.
59
+ Memory and compaction are the same primitive: observational memory _is_ how context survives between turns. The runner observes its own transcript, reflects when observations grow, and writes durable rows to PGlite — text observations for messages and images alike, so screenshots and UI captures stay recallable on later turns without re-attaching bytes. Each turn's prompt prefix is frozen between deliberate refresh points: curated memory files load from the project ancestry at session start or explicit skills reload, while long-term and current-session observations rebuild at compaction events. That separation keeps trained knowledge deterministic, prevents it from displacing observational memory, and preserves the provider's prompt cache turn-over-turn. Database observations outside the frozen prefix stay reachable through `recall_memory` — hybrid retrieval over pgvector cosine similarity and tsvector keyword search, fused via Reciprocal Rank Fusion, with optional paraphrased query expansion. Embeddings run in a background worker so foreground turns never block.
60
60
 
61
61
  ### Relays: keep the agent working until the job is done
62
62
 
@@ -245,6 +245,9 @@ bun run test # runs the test suite inside Docker
245
245
 
246
246
  Use `bun run test` and `bun run eval`, not raw `bun test`, as the source of truth. File-writing tests and evals run in Docker so focused host runs cannot create `.duet`, PGlite databases, or home-directory skill fixtures in the checkout.
247
247
 
248
+ Paid evaluation infrastructure and its separate verification commands live in
249
+ the [SWE-bench benchmark](benchmarks/swebench/README.md).
250
+
248
251
  The pre-commit hook runs `format`, `check-types`, and `lint`.
249
252
 
250
253
  </details>
@@ -385,16 +388,16 @@ All three share one **canonical memory JSON object** (`--json`), so a consumer p
385
388
 
386
389
  - Timestamps are ISO 8601 strings (e.g. `2026-07-06T00:00:00.000Z`); date-only fields (`observedDate`, `referencedDate`) stay `YYYY-MM-DD`.
387
390
  - `source` is a flat string — one of `user | agent | system | api | import` (`system` is the training-origin value).
388
- - `sessionId` is the session that authored the row: writable on `add` via `--session <id>`, filterable on `memory`/`recall` via `--session`, and echoed on output (absent on legacy rows).
389
- - Two ranking scores are always named explicitly, never a generic `score`: `packScore` (recency × priority × kind bias, present everywhere) and `relevanceScore` (query-relevance, RRF-fused — present only in `memory recall` results).
391
+ - `sessionId` is the session that authored an observational row: writable on DB-backed `add`, filterable on `memory`/`recall`, and echoed on DB output (absent on legacy rows and file memories).
392
+ - Observational JSON names both ranking axes explicitly: `packScore` (recency × priority × kind bias) and `relevanceScore` (query relevance, present only in `memory recall`). File-store JSON reports its slug and store path instead because those records are inherited context, not ranked recall rows.
390
393
 
391
394
  Command-specific notes:
392
395
 
393
396
  - **`duet memory` (query):** `--json` emits a bare array ordered by pack score; `--source` and `--session` narrow the set alongside `--type`, `--priority`, `--from`, and `--to`.
394
397
  - **`duet memory recall`:** query text comes from `--query <q>` or positional args. `--scope session|global` requires `--session <id>` to compare against; `all` (default) ignores it. `--json` emits a bare array ordered best-first, each row carrying both `packScore` and `relevanceScore`.
395
- - **`duet memory add`:** added rows are always `note` kind. `--source` defaults to `user`; `--session <id>` stamps the row (omit to leave it global). Content comes from positional args or stdin, and empty input is a usage error. `--json` emits one canonical object (`packScore` and `lastUsedAt` present, `relevanceScore` absent).
398
+ - **`duet memory add`:** added memories are always `note` kind. Flagless writes go to the nearest ancestor `.agents/memories`; pass `--db` to retain observational-row ranking, embedding, and session attribution. Content comes from positional args or stdin, and empty input is a usage error.
396
399
 
397
- Every memory command accepts `--db <absolute-path>` (default `~/.duet/memory.db`) and `--wait <seconds>` (lock-wait budget, default 30; `0` fails immediately). Exit codes are stable for scripting: `0` success, `64` usage or validation error (unknown flag, bad value, empty input), `75` memory-DB lock-wait budget exhausted, and `1` for anything else.
400
+ DB-backed memory commands accept `--db <absolute-path>` and `--wait <seconds>`. `memory add` also accepts a single `--store`; `memory recall` deliberately rejects stores because file memories are already loaded into agent context. Exit codes are stable for scripting: `0` success, `64` usage or validation error, `75` memory-DB lock-wait budget exhausted, and `1` for anything else.
398
401
 
399
402
  </details>
400
403
 
@@ -403,21 +406,21 @@ Every memory command accepts `--db <absolute-path>` (default `~/.duet/memory.db`
403
406
 
404
407
  `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:
405
408
 
406
- - **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.
407
- - **`~/.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.
409
+ - **One inherited markdown memory** in the nearest ancestor `.agents/memories` store. Explicit `--store` selects a different file store; explicit `--db` retains the legacy high-priority manual-row behavior.
410
+ - **`~/.duet/train/<memory-id>/`** — a hidden archive containing source copies and private provenance. Shareable memory frontmatter references the archive id but never embeds the absolute source folder.
408
411
 
409
412
  ```bash
410
- duet train ./snowflake-notes # writes to ~/.duet/memory.db
413
+ duet train ./snowflake-notes # writes to the nearest .agents/memories
411
414
  duet train ./snowflake-notes --slug snow # custom slug (default: folder basename)
412
415
  duet train ./snowflake-notes --model opus-4.8
413
416
  duet train ./snowflake-notes --db /tmp/scratch.db # write to a throwaway DB instead
414
417
  ```
415
418
 
416
- 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.
419
+ Re-running `train` on the same slug **replaces** the prior entry and its archive in the selected backend.
417
420
 
418
421
  Three things to know:
419
422
 
420
- - **The current session won't see the new memory.** Memory loads at session start. Start a fresh `duet` session to test recall.
423
+ - **The current session won't watch the new memory file.** It appears in a fresh `duet` session, or after a programmatic `reloadSkills()` refreshes disk-backed context.
421
424
  - **Synthesis needs an API key.** `DUET_API_KEY` (recommended), or any of the provider keys covered above.
422
425
  - **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.
423
426
 
@@ -539,7 +542,7 @@ The parent runner transcript stays linear across the lifecycle. State-machine co
539
542
 
540
543
  `TurnRunner` owns memory at runtime. It holds a `MemoryStore` in process, hydrates durable observations from PGlite before the first turn, and subscribes to memory-store events to write future observation changes. After each pi-agent run, the runner observes the latest unobserved transcript suffix, reflects oversized observation logs, emits memory events with generated observation payloads, and waits for durable writes before continuing. Raw conversation messages stay in `TurnState.agent.messages`; memory persistence stores only derived observations/reflections.
541
544
 
542
- The rendered memory section above the message tail is a _frozen_ two-layer pack long-term cross-session memory ranked into an 8k-token budget and the current session's chronological compaction summary. The pack is rebuilt only at compaction events (initial load, reflector completion, wire-shaping eviction) so observations the observer writes mid-session do not invalidate the prompt cache. The model can still pull specific facts on demand through the default `recall_memory` tool, which runs hybrid vector + keyword search over the same database with optional query expansion.
545
+ The rendered memory section above the message tail is a frozen pack with two independent sources. Curated memory files discovered from the working directory's project ancestry are pinned first and refreshed only at session start or explicit skills reload. Database-backed memory follows as ranked cross-session observations and the current session's chronological compaction summary; those layers rebuild only at compaction events so ordinary observer writes do not invalidate the prompt cache. File memory never enters database ranking, reflection, usage-bump, or recall paths. The model can still pull non-pinned database facts on demand through the default `recall_memory` tool, which runs hybrid vector + keyword search with optional query expansion.
543
546
 
544
547
  ```typescript
545
548
  import { TurnRunner } from "@duetso/agent";
@@ -550,7 +553,7 @@ const turnRunner = new TurnRunner({
550
553
  });
551
554
  ```
552
555
 
553
- By default, both `duet` (TUI/run) and `duet --rpc` store durable observations in `~/.duet/memory.db`. Override the path with `--db <path>` (the flag is accepted in both modes and is ignored when `--incognito` is also set), or run with `--incognito` (or `-i`) to set `memoryDbPath: false`, which disables observational memory and compaction for that session. `duet --rpc` bypasses `SessionManager`, so it has no session of its own; pass `duet --rpc --session <id>` to attribute every observation written during the RPC process to a caller-owned session (one RPC process is one logical session). Omit it to leave those writes unattributed. Programmatic callers can pass `memoryDbPath: false` or provide a custom `memoryDbPath`. The CLI's `SessionManager` is a convenience layer that stores session snapshots under `~/.duet/sessions`, but the runner owns memory hydration, pi-turn observation/reflection, compaction, and observation persistence.
556
+ By default, both `duet` (TUI/run) and `duet --rpc` store durable observations in `~/.duet/memory.db`. Override the path with `--db <path>` (the flag is accepted in both modes and is ignored when `--incognito` is also set), or run with `--incognito` (or `-i`) to disable both observational database memory and curated file memory for that session. `duet --rpc` bypasses `SessionManager`, so it has no session of its own; pass `duet --rpc --session <id>` to attribute every observation written during the RPC process to a caller-owned session (one RPC process is one logical session). Omit it to leave those writes unattributed. Programmatic callers can control the two sources independently with `memoryDbPath` and `memoryStores`. The CLI's `SessionManager` is a convenience layer that stores session snapshots under `~/.duet/sessions`, but the runner owns memory hydration, pi-turn observation/reflection, compaction, and observation persistence.
554
557
 
555
558
  > [!WARNING]
556
559
  > We strongly recommend running with a `memoryDbPath` (the default). Compaction is implemented as part of the observational memory pipeline: raw transcript content is replaced by observations/reflections that the observer and reflector write to the durable store. Without a database, the runner skips that pipeline entirely — there is no compaction, the transcript grows unbounded against the raw model context window, and long sessions will eventually hit a provider context-length error. `memoryDbPath: false` is appropriate for short-lived scripts, tests, and incognito runs that stay well under the model window.
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duetso/agent",
3
- "version": "0.2.5",
3
+ "version": "0.3.0",
4
4
  "description": "An opinionated full-stack agent turn runner with native memories, interrupts, and multi-agent orchestration",
5
5
  "keywords": [
6
6
  "agent",
@@ -32,6 +32,10 @@
32
32
  "types": "./dist/src/index.d.ts",
33
33
  "import": "./dist/src/index.js"
34
34
  },
35
+ "./memory-store": {
36
+ "types": "./dist/src/memory/store/index.d.ts",
37
+ "import": "./dist/src/memory-store.js"
38
+ },
35
39
  "./package.json": "./package.json"
36
40
  },
37
41
  "publishConfig": {
@@ -39,11 +43,11 @@
39
43
  },
40
44
  "scripts": {
41
45
  "setup": "bash scripts/setup-docker.sh",
42
- "build": "tsc",
46
+ "build": "tsc && bun build src/memory/store/index.ts --target node --format esm --outfile dist/src/memory-store.js",
43
47
  "check-types": "tsc --noEmit",
44
48
  "cli": "bun src/cli.ts",
45
49
  "dev": "tsc --watch",
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'",
50
+ "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 EVAL_ADVISOR_THINKING -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
51
  "format": "oxfmt --write --no-error-on-unmatched-pattern",
48
52
  "format:check": "oxfmt --check --no-error-on-unmatched-pattern",
49
53
  "lint": "oxlint src/",
@@ -51,6 +55,7 @@
51
55
  "test": "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 'apt-get update -qq && apt-get install -y -qq git >/dev/null && cp -R /src/. /work && bun install --frozen-lockfile && bun test ./test/*.test.ts'",
52
56
  "test:swebench": "bash benchmarks/swebench/test.sh",
53
57
  "example": "bun examples/basic.ts",
58
+ "example:memory-store": "bun examples/memory-store.ts",
54
59
  "example:state-machine": "bun examples/state-machine.ts",
55
60
  "example:tui-playground": "bun examples/tui-playground.ts",
56
61
  "prepare": "husky",
@@ -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,CA6FtD;AAED,wBAAgB,cAAc,IAAI,IAAI,CAqBrC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAsBnC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAqBtC;AAED,wBAAgB,eAAe,IAAI,IAAI,CA4DtC;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CA8BzC;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAwC5C;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAuC7C;AAED,wBAAgB,cAAc,IAAI,IAAI,CAsCrC;AAED,wBAAgB,cAAc,IAAI,IAAI,CAgErC;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,CA6FtD;AAED,wBAAgB,cAAc,IAAI,IAAI,CAqBrC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAsBnC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAqBtC;AAED,wBAAgB,eAAe,IAAI,IAAI,CA4DtC;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAgCzC;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CA0C5C;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAuC7C;AAED,wBAAgB,cAAc,IAAI,IAAI,CAsCrC;AAED,wBAAgB,cAAc,IAAI,IAAI,CA0ErC;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAiB5C;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAe1D"}
@@ -233,14 +233,14 @@ export function printMemoryAddHelp() {
233
233
  duet memory add — Write a single user-added note memory
234
234
 
235
235
  USAGE
236
- duet memory add [options] <content>
237
- echo "<content>" | duet memory add [options]
236
+ duet memory add [options] [--store <folder> | --db <file>] <content>
237
+ echo "<content>" | duet memory add [options] [--store <folder> | --db <file>]
238
238
 
239
239
  DESCRIPTION
240
- Stores a note memory into the same ~/.duet/memory.db the runner reads, so
241
- it surfaces in the next session. Notes get a small ranking bump above
242
- reflections (far below a 'duet train' corpus) and stay eligible for
243
- 'duet memory reflect' compaction, folding like any observation once aged.
240
+ Stores a note in exactly one backend. With no backend flag, the note is
241
+ written to the nearest ancestor .agents/memories directory (created on
242
+ demand). --store writes a markdown memory file; --db retains the legacy
243
+ observational-row behavior. Passing more than one backend is a usage error.
244
244
 
245
245
  Content comes from the positional arguments, or from stdin when none are
246
246
  given so longer memories can be piped in.
@@ -251,9 +251,11 @@ OPTIONS
251
251
  --session <id> Stamp the row's authoring session; omit to leave it
252
252
  global/unattributed
253
253
  --tag <tag> Attach a label; repeat to add several
254
- --db <path> Memory database path (default: ~/.duet/memory.db)
255
- --json Emit the stored memory as one canonical JSON object
256
- (with packScore) instead of the confirmation line
254
+ --store <folder> Memory-file directory to write
255
+ --db <file> PGlite file to write instead of a memory store
256
+ --json Emit the stored memory as JSON instead of the
257
+ confirmation line (DB rows include packScore;
258
+ file rows include slug + store provenance)
257
259
  --wait <seconds> Seconds to wait for the cross-process open-lock
258
260
  (default: 30; 0 fails immediately)
259
261
  -h, --help Show this help
@@ -295,6 +297,8 @@ OPTIONS
295
297
  --json Emit a bare JSON array of canonical memory objects
296
298
  (best-first) with packScore + relevanceScore
297
299
  --db <path> Memory database path (default: ~/.duet/memory.db)
300
+ This command is DB-only; --store is rejected because
301
+ store memories are already loaded into agent context
298
302
  --wait <seconds> Seconds to wait for the cross-process open-lock
299
303
  (default: 30; 0 fails immediately)
300
304
  -h, --help Show this help
@@ -384,11 +388,13 @@ export function printTrainHelp() {
384
388
  duet train — Ingest a project corpus into one durable memory observation
385
389
 
386
390
  USAGE
387
- duet train <folder> [--slug <name>] [--model <name>] [--db <path>] [--wait <seconds>]
388
- duet train list [--db <path>] [--json] [--wait <seconds>]
389
- duet train show <slug> [--db <path>] [--json] [--wait <seconds>]
390
- duet train update <slug> --content-file <path> [--db <path>] [--json] [--wait <seconds>]
391
- duet train delete <slug> [--db <path>] [--json] [--wait <seconds>]
391
+ duet train <folder> [--slug <name>] [--model <name>]
392
+ [--store <folder> | --db <file>] [--wait <seconds>]
393
+ duet train list [--store <folder>]... [--db <file>]... [--json] [--wait <seconds>]
394
+ duet train show <slug> [--store <folder>]... [--db <file>]... [--json] [--wait <seconds>]
395
+ duet train update <slug> --content-file <path>
396
+ [--store <folder>]... [--db <file>]... [--json] [--wait <seconds>]
397
+ duet train delete <slug> [--store <folder>]... [--db <file>]... [--json] [--wait <seconds>]
392
398
 
393
399
  DESCRIPTION
394
400
  Launches a duet agent with the corpus folder as its working directory.
@@ -399,15 +405,23 @@ DESCRIPTION
399
405
 
400
406
  .duet-train.json — structured handoff with headline + observation.
401
407
 
402
- 'train' then persists the synthesis into ~/.duet/memory.db as a manual
403
- (user-curated) row (tagged 'train' and 'train:<slug>'), archives the
404
- corpus under ~/.duet/train/<memory-id>/, removes the handoff file, and
405
- prints the observation content to stdout so what you see is what landed
406
- in memory.
408
+ 'train' then persists the synthesis into exactly one backend and archives
409
+ the corpus under ~/.duet/train/<memory-id>/. With no backend flag it writes
410
+ a markdown file under the nearest ancestor .agents/memories directory,
411
+ creating that directory when needed. --db retains the legacy manual-row
412
+ behavior. Passing more than one backend to create is a usage error.
413
+
414
+ Reads accept repeatable --store and --db flags. Any explicit backend flags
415
+ replace discovery; stores are consulted in flag order before DBs. Without
416
+ flags, reads union inherited stores from cwd toward the filesystem root,
417
+ then ~/.duet/memory.db. Duplicate slugs resolve to the first source, while
418
+ surviving entries are listed newest-first. show/update/delete use that same
419
+ first-source precedence.
407
420
 
408
421
  The management subcommands all key on the user-facing <slug> (resolved
409
422
  to the underlying row internally):
410
- list — every training (one row per slug), joined to its archive
423
+ list — every visible store entry or DB training (one row per slug),
424
+ joined to its archive
411
425
  manifest to show slug, headline, model, file count, date,
412
426
  and memory id.
413
427
  show — the same metadata plus the full synthesized observation text
@@ -419,17 +433,17 @@ DESCRIPTION
419
433
  delete — permanently remove the row and its corpus archive.
420
434
  Pass --json to any of them for machine-readable output.
421
435
 
422
- Subsequent runs against the same slug replace the prior row in place,
423
- so the memory pool does not bloat. Writing the row as a manual row
424
- earns it a ranking boost in the memory pack (via manualBias) and exempts
425
- it from 'duet memory reflect' compaction; deleting it via 'duet memory'
426
- also removes its archive. Note: train loads the corpus folder's .env (for provider
427
- credentials), so check folders you did not author before training.
436
+ Subsequent runs against the same slug replace the prior target entry, so
437
+ the memory pool does not bloat. On --db, the legacy manual row keeps its
438
+ ranking boost and reflection exemption. Note: train loads the corpus
439
+ folder's .env (for provider credentials), so check folders you did not
440
+ author before training.
428
441
 
429
442
  OPTIONS
430
443
  --slug <name> Override the corpus slug (default: sanitized folder basename)
431
444
  --model <name> Model used by the synthesis sub-agent (default: same resolution as 'duet run')
432
- --db <path> Memory database path (default: ~/.duet/memory.db)
445
+ --store <folder> Memory-file directory; repeat on read/manage commands
446
+ --db <file> PGlite path; repeat on read/manage commands
433
447
  --wait <seconds> Seconds to wait for the cross-process open-lock
434
448
  (default: 30; 0 fails immediately)
435
449
  -h, --help Show this help
@@ -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;;;;;;;;;;;;;;;;;;;;;;;gDAuBkC,WAAW;;;;;;;;;;;;;gHAaqD,+BAA+B;;;;;oFAK3D,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkDxG,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;wEAY0D,qBAAqB;;;;;;;CAO5F,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Db,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4Bb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCb,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8Db,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;;;;;;;;;;;;;;;;;;;;;;;gDAuBkC,WAAW;;;;;;;;;;;;;gHAaqD,+BAA+B;;;;;oFAK3D,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkDxG,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;wEAY0D,qBAAqB;;;;;;;CAO5F,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Db,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8Bb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwCb,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwEb,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,7 +1,11 @@
1
1
  import { type EmbedFn } from "../memory/embedding.js";
2
+ import { type MemorySourceFlags } from "../memory/store/sources.js";
2
3
  import type { ObservationPriority, ObservationSource } from "../types/memory.js";
3
4
  type SourceKind = ObservationSource["kind"];
4
5
  interface AddCommandOptions {
6
+ /** Explicit backend flags; empty means flagless store discovery. */
7
+ sourceFlags: MemorySourceFlags;
8
+ /** Compatibility projection for callers that inspect a single selected DB. */
5
9
  dbPath: string;
6
10
  /** Positional content joined with spaces; empty when the caller pipes via stdin instead. */
7
11
  content: string;
@@ -11,7 +15,7 @@ interface AddCommandOptions {
11
15
  tags: string[];
12
16
  /** Session that authored the row; omitted leaves the row global/unattributed. */
13
17
  sessionId?: string;
14
- /** Emit one canonical memory JSON object instead of the human line. */
18
+ /** Emit the selected backend's JSON record instead of the human line. */
15
19
  json: boolean;
16
20
  waitBudgetMs?: number;
17
21
  }
@@ -20,6 +24,8 @@ interface AddCommandIO {
20
24
  stdin: NodeJS.ReadableStream & {
21
25
  isTTY?: boolean;
22
26
  };
27
+ /** Working directory used for relative paths and flagless source discovery. */
28
+ cwd?: string;
23
29
  /**
24
30
  * Embedding client for the synchronous insert-time embed. Defaults to
25
31
  * the Duet endpoint client; tests inject a stub (or a throwing one) to
@@ -28,21 +34,20 @@ interface AddCommandIO {
28
34
  embed?: EmbedFn;
29
35
  }
30
36
  /**
31
- * Run `duet memory add` — write a single user-added note row into the same
32
- * `~/.duet/memory.db` the runner reads from, so it surfaces in the next
33
- * session. Stored as `kind: "note"` with no `sessionId`, so it lands in the
34
- * cross-session global pack with a small `noteBias` bump (above reflections,
35
- * far below a `duet train` corpus) and stays eligible for `duet memory
36
- * reflect` compaction, folding like any other observation once aged.
37
+ * Run `duet memory add` — write one curated note to a memory-file store or
38
+ * the legacy observational DB. Flagless writes create the nearest agent's
39
+ * `.agents/memories` directory. DB notes retain their ranking, reflection,
40
+ * session-attribution, and synchronous-embedding behavior; file notes retain
41
+ * priority/source/tags in frontmatter and are loaded through store context.
37
42
  *
38
43
  * Content comes from the positional arguments, or from stdin when none are
39
44
  * given so callers can pipe longer text (`echo "…" | duet memory add`).
40
45
  *
41
- * The embedding is written synchronously alongside the row (no backfill
42
- * worker runs in this one-shot process), so `duet memory recall` and the
43
- * next session's `recall_memory` reach it semantically right away. When
44
- * embeddings are unavailable the add still succeeds and the next runner's
45
- * backfill pass embeds the row.
46
+ * For DB targets, the embedding is written synchronously alongside the row
47
+ * (no backfill worker runs in this one-shot process), so `duet memory recall`
48
+ * and the next session's `recall_memory` reach it semantically right away.
49
+ * When embeddings are unavailable the add still succeeds and the next
50
+ * runner's backfill pass embeds the row.
46
51
  */
47
52
  export declare function runMemoryAddCommand(args: string[], io?: AddCommandIO): Promise<void>;
48
53
  /**
@@ -50,6 +55,6 @@ export declare function runMemoryAddCommand(args: string[], io?: AddCommandIO):
50
55
  * when `--help` was handled. Pure (no I/O) so it can be unit-tested; stdin
51
56
  * fallback for empty content happens later in {@link resolveContent}.
52
57
  */
53
- export declare function parseMemoryAddArgs(args: string[]): AddCommandOptions | undefined;
58
+ export declare function parseMemoryAddArgs(args: string[], cwd?: string): AddCommandOptions | undefined;
54
59
  export {};
55
60
  //# sourceMappingURL=memory-add.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-add.d.ts","sourceRoot":"","sources":["../../../src/cli/memory-add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAG7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAOjF,KAAK,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE5C,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,yEAAyE;IACzE,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC,cAAc,GAAG;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACnD;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,YAA+D,GAClE,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,iBAAiB,GAAG,SAAS,CA+DhF"}
1
+ {"version":3,"file":"memory-add.d.ts","sourceRoot":"","sources":["../../../src/cli/memory-add.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyB,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAG7E,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAGpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAYjF,KAAK,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE5C,UAAU,iBAAiB;IACzB,oEAAoE;IACpE,WAAW,EAAE,iBAAiB,CAAC;IAC/B,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,yEAAyE;IACzE,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC,cAAc,GAAG;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACnD,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,YAA+D,GAClE,OAAO,CAAC,IAAI,CAAC,CAkDf;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,GAAE,MAAsB,GAC1B,iBAAiB,GAAG,SAAS,CAiE/B"}
@@ -1,35 +1,48 @@
1
+ import { randomBytes } from "node:crypto";
1
2
  import { createEmbeddingClient } from "../memory/embedding.js";
3
+ import { createMemoryId } from "../memory/id.js";
4
+ import { listStore, writeEntry } from "../memory/store/store.js";
5
+ import { resolveSources } from "../memory/store/sources.js";
2
6
  import { appendObservation } from "../memory/storage.js";
3
7
  import { DEFAULT_MEMORY_DB_PATH } from "../session/session-manager.js";
4
8
  import { printMemoryAddHelp } from "./help.js";
5
9
  import { toMemoryJson } from "./memory-json.js";
6
10
  import { scoreObservation, withMemorySession } from "./memory-db.js";
7
11
  import { PRIORITIES, parseEnum, SOURCES } from "./memory-query.js";
8
- import { fail, resolveUserPath, usageError } from "./shared.js";
12
+ import { lexMemorySourceFlags, requireSingleExplicitWriteTarget, requireWriteTarget, } from "./memory-sources.js";
13
+ import { fail, usageError } from "./shared.js";
9
14
  /**
10
- * Run `duet memory add` — write a single user-added note row into the same
11
- * `~/.duet/memory.db` the runner reads from, so it surfaces in the next
12
- * session. Stored as `kind: "note"` with no `sessionId`, so it lands in the
13
- * cross-session global pack with a small `noteBias` bump (above reflections,
14
- * far below a `duet train` corpus) and stays eligible for `duet memory
15
- * reflect` compaction, folding like any other observation once aged.
15
+ * Run `duet memory add` — write one curated note to a memory-file store or
16
+ * the legacy observational DB. Flagless writes create the nearest agent's
17
+ * `.agents/memories` directory. DB notes retain their ranking, reflection,
18
+ * session-attribution, and synchronous-embedding behavior; file notes retain
19
+ * priority/source/tags in frontmatter and are loaded through store context.
16
20
  *
17
21
  * Content comes from the positional arguments, or from stdin when none are
18
22
  * given so callers can pipe longer text (`echo "…" | duet memory add`).
19
23
  *
20
- * The embedding is written synchronously alongside the row (no backfill
21
- * worker runs in this one-shot process), so `duet memory recall` and the
22
- * next session's `recall_memory` reach it semantically right away. When
23
- * embeddings are unavailable the add still succeeds and the next runner's
24
- * backfill pass embeds the row.
24
+ * For DB targets, the embedding is written synchronously alongside the row
25
+ * (no backfill worker runs in this one-shot process), so `duet memory recall`
26
+ * and the next session's `recall_memory` reach it semantically right away.
27
+ * When embeddings are unavailable the add still succeeds and the next
28
+ * runner's backfill pass embeds the row.
25
29
  */
26
30
  export async function runMemoryAddCommand(args, io = { stdout: process.stdout, stdin: process.stdin }) {
27
- const options = parseMemoryAddArgs(args);
31
+ const cwd = io.cwd ?? process.cwd();
32
+ const options = parseMemoryAddArgs(args, cwd);
28
33
  if (!options)
29
34
  return;
30
35
  const content = await resolveContent(options.content, io);
36
+ const sources = await resolveSources(options.sourceFlags, cwd);
37
+ const writeTarget = requireWriteTarget(sources);
38
+ if (writeTarget.kind === "store") {
39
+ if (options.sessionId)
40
+ usageError("--session is only supported with --db <file>.");
41
+ await writeStoreNote(writeTarget.path, content, options, io);
42
+ return;
43
+ }
31
44
  const embed = io.embed ?? createEmbeddingClient();
32
- const observation = await withMemorySession(options.dbPath, (session) => appendObservation(session, {
45
+ const observation = await withMemorySession(writeTarget.path, (session) => appendObservation(session, {
33
46
  kind: "note",
34
47
  priority: options.priority,
35
48
  source: { kind: options.source },
@@ -39,7 +52,7 @@ export async function runMemoryAddCommand(args, io = { stdout: process.stdout, s
39
52
  ...(options.sessionId !== undefined ? { sessionId: options.sessionId } : {}),
40
53
  }, { embed }), { waitBudgetMs: options.waitBudgetMs });
41
54
  if (!observation) {
42
- fail(`Could not write memory to ${options.dbPath} (lock contention).`);
55
+ fail(`Could not write memory to ${writeTarget.path} (lock contention).`);
43
56
  }
44
57
  if (options.json) {
45
58
  // Score with a single `now`; on insert `lastUsedAt == createdAt`, so the
@@ -57,8 +70,9 @@ export async function runMemoryAddCommand(args, io = { stdout: process.stdout, s
57
70
  * when `--help` was handled. Pure (no I/O) so it can be unit-tested; stdin
58
71
  * fallback for empty content happens later in {@link resolveContent}.
59
72
  */
60
- export function parseMemoryAddArgs(args) {
61
- let dbPath = DEFAULT_MEMORY_DB_PATH;
73
+ export function parseMemoryAddArgs(args, cwd = process.cwd()) {
74
+ const sourceArgs = lexMemorySourceFlags(args, cwd);
75
+ requireSingleExplicitWriteTarget(sourceArgs.flags);
62
76
  let priority = "medium";
63
77
  let source = "user";
64
78
  let sessionId;
@@ -66,35 +80,32 @@ export function parseMemoryAddArgs(args) {
66
80
  const tags = [];
67
81
  let waitBudgetMs;
68
82
  const contentParts = [];
69
- for (let i = 0; i < args.length; i++) {
70
- const arg = args[i];
83
+ for (let i = 0; i < sourceArgs.args.length; i++) {
84
+ const arg = sourceArgs.args[i];
71
85
  switch (arg) {
72
- case "--db":
73
- if (!args[i + 1] || args[i + 1]?.startsWith("-"))
74
- usageError(`Missing value for ${arg}`);
75
- dbPath = resolveUserPath(args[++i]);
76
- break;
77
86
  case "--priority":
78
- priority = parseEnum(args[++i], PRIORITIES, arg);
87
+ priority = parseEnum(sourceArgs.args[++i], PRIORITIES, arg);
79
88
  break;
80
89
  case "--source":
81
- source = parseEnum(args[++i], SOURCES, arg);
90
+ source = parseEnum(sourceArgs.args[++i], SOURCES, arg);
82
91
  break;
83
92
  case "--session":
84
- if (!args[i + 1] || args[i + 1]?.startsWith("-"))
93
+ if (!sourceArgs.args[i + 1] || sourceArgs.args[i + 1]?.startsWith("-")) {
85
94
  usageError(`Missing value for ${arg}`);
86
- sessionId = args[++i];
95
+ }
96
+ sessionId = sourceArgs.args[++i];
87
97
  break;
88
98
  case "--json":
89
99
  json = true;
90
100
  break;
91
101
  case "--tag":
92
- if (!args[i + 1] || args[i + 1]?.startsWith("-"))
102
+ if (!sourceArgs.args[i + 1] || sourceArgs.args[i + 1]?.startsWith("-")) {
93
103
  usageError(`Missing value for ${arg}`);
94
- tags.push(args[++i]);
104
+ }
105
+ tags.push(sourceArgs.args[++i]);
95
106
  break;
96
107
  case "--wait": {
97
- const raw = args[++i];
108
+ const raw = sourceArgs.args[++i];
98
109
  const seconds = Number(raw);
99
110
  if (!raw || !Number.isFinite(seconds) || seconds < 0) {
100
111
  usageError(`Invalid --wait value: ${raw} (expected non-negative number of seconds)`);
@@ -113,7 +124,8 @@ export function parseMemoryAddArgs(args) {
113
124
  }
114
125
  }
115
126
  return {
116
- dbPath,
127
+ sourceFlags: sourceArgs.flags,
128
+ dbPath: sourceArgs.flags.dbs[0] ?? DEFAULT_MEMORY_DB_PATH,
117
129
  content: contentParts.join(" ").trim(),
118
130
  priority,
119
131
  source,
@@ -147,4 +159,51 @@ async function readStream(stream) {
147
159
  }
148
160
  return Buffer.concat(chunks).toString("utf8");
149
161
  }
162
+ async function writeStoreNote(storeDir, content, options, io) {
163
+ const slug = await createNoteSlug(storeDir, content);
164
+ const id = createMemoryId();
165
+ const createdAt = Date.now();
166
+ const stored = await writeEntry(storeDir, {
167
+ slug,
168
+ version: 1,
169
+ id,
170
+ kind: "note",
171
+ createdAt,
172
+ priority: options.priority,
173
+ source: options.source,
174
+ tags: options.tags,
175
+ content,
176
+ });
177
+ if (options.json) {
178
+ io.stdout.write(`${JSON.stringify({
179
+ slug: stored.slug,
180
+ id: stored.id,
181
+ kind: stored.kind,
182
+ createdAt: new Date(stored.createdAt).toISOString(),
183
+ content: stored.content,
184
+ priority: options.priority,
185
+ source: options.source,
186
+ tags: options.tags,
187
+ store: stored.storeDir,
188
+ }, null, 2)}\n`);
189
+ return;
190
+ }
191
+ const tagSuffix = options.tags.length > 0 ? ` [${options.tags.join(", ")}]` : "";
192
+ io.stdout.write(`Added ${options.priority}-priority memory ${stored.id} as ${stored.slug} (${new Date(createdAt)
193
+ .toISOString()
194
+ .slice(0, 10)})${tagSuffix}\n`);
195
+ }
196
+ async function createNoteSlug(storeDir, content) {
197
+ const words = content
198
+ .toLowerCase()
199
+ .match(/[a-z0-9]+/g)
200
+ ?.slice(0, 5) ?? [];
201
+ const stem = (words.join("-") || "note").slice(0, 48).replace(/-+$/g, "") || "note";
202
+ const existing = new Set((await listStore(storeDir)).map((entry) => entry.slug));
203
+ while (true) {
204
+ const slug = `${stem}-${randomBytes(3).toString("hex")}`;
205
+ if (!existing.has(slug))
206
+ return slug;
207
+ }
208
+ }
150
209
  //# sourceMappingURL=memory-add.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-add.js","sourceRoot":"","sources":["../../../src/cli/memory-add.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory-add.js","sourceRoot":"","sources":["../../../src/cli/memory-add.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"memory-recall.d.ts","sourceRoot":"","sources":["../../../src/cli/memory-recall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAMtD,UAAU,oBAAoB;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,CAAC;IACnB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,MAAM,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,eAA4C,GAC/C,OAAO,CAAC,IAAI,CAAC,CAiDf;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,oBAAoB,GAAG,SAAS,CAuGtF;AAOD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,MAAM,CA4CrE"}
1
+ {"version":3,"file":"memory-recall.d.ts","sourceRoot":"","sources":["../../../src/cli/memory-recall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAMtD,UAAU,oBAAoB;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,CAAC;IACnB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,MAAM,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,eAA4C,GAC/C,OAAO,CAAC,IAAI,CAAC,CAiDf;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,oBAAoB,GAAG,SAAS,CA4GtF;AAOD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,MAAM,CA4CrE"}
@@ -75,6 +75,9 @@ export function parseMemoryRecallArgs(args) {
75
75
  for (let i = 0; i < args.length; i++) {
76
76
  const arg = args[i];
77
77
  switch (arg) {
78
+ case "--store":
79
+ usageError("duet memory recall does not support --store; use --db <file>. " +
80
+ "Store memories are loaded into context automatically.");
78
81
  case "--db":
79
82
  if (!args[i + 1] || args[i + 1]?.startsWith("-"))
80
83
  usageError(`Missing value for ${arg}`);