memo-grafter 0.2.7 → 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 (205) hide show
  1. package/README.md +26 -0
  2. package/USER_GUIDE.md +262 -17
  3. package/dist/MemoGrafter.d.ts +11 -5
  4. package/dist/MemoGrafter.d.ts.map +1 -1
  5. package/dist/MemoGrafter.js +64 -4
  6. package/dist/MemoGrafter.js.map +1 -1
  7. package/dist/MemoGrafterAgent.d.ts +8 -1
  8. package/dist/MemoGrafterAgent.d.ts.map +1 -1
  9. package/dist/MemoGrafterAgent.js +31 -2
  10. package/dist/MemoGrafterAgent.js.map +1 -1
  11. package/dist/adapters/AnthropicAdapter.d.ts +1 -1
  12. package/dist/adapters/AnthropicAdapter.d.ts.map +1 -1
  13. package/dist/adapters/GeminiAdapter.d.ts +1 -1
  14. package/dist/adapters/GeminiAdapter.d.ts.map +1 -1
  15. package/dist/adapters/OpenAIAdapter.d.ts +1 -1
  16. package/dist/adapters/OpenAIAdapter.d.ts.map +1 -1
  17. package/dist/adapters/types.d.ts +1 -1
  18. package/dist/adapters/types.d.ts.map +1 -1
  19. package/dist/agents/MemoGrafterAgent.d.ts +45 -0
  20. package/dist/agents/MemoGrafterAgent.d.ts.map +1 -0
  21. package/dist/agents/MemoGrafterAgent.js +278 -0
  22. package/dist/agents/MemoGrafterAgent.js.map +1 -0
  23. package/dist/agents/fleet/ConductorAgent.d.ts +15 -0
  24. package/dist/agents/fleet/ConductorAgent.d.ts.map +1 -0
  25. package/dist/agents/fleet/ConductorAgent.js +41 -0
  26. package/dist/agents/fleet/ConductorAgent.js.map +1 -0
  27. package/dist/agents/fleet/FleetStore.d.ts +12 -0
  28. package/dist/agents/fleet/FleetStore.d.ts.map +1 -0
  29. package/dist/agents/fleet/FleetStore.js +30 -0
  30. package/dist/agents/fleet/FleetStore.js.map +1 -0
  31. package/dist/agents/fleet/MemoGrafterFleet.d.ts +27 -0
  32. package/dist/agents/fleet/MemoGrafterFleet.d.ts.map +1 -0
  33. package/dist/agents/fleet/MemoGrafterFleet.js +87 -0
  34. package/dist/agents/fleet/MemoGrafterFleet.js.map +1 -0
  35. package/dist/agents/fleet/WorkerAgent.d.ts +36 -0
  36. package/dist/agents/fleet/WorkerAgent.d.ts.map +1 -0
  37. package/dist/agents/fleet/WorkerAgent.js +140 -0
  38. package/dist/agents/fleet/WorkerAgent.js.map +1 -0
  39. package/dist/agents/fleet/types.d.ts +58 -0
  40. package/dist/agents/fleet/types.d.ts.map +1 -0
  41. package/dist/agents/fleet/types.js +2 -0
  42. package/dist/agents/fleet/types.js.map +1 -0
  43. package/dist/cli/commands/init.d.ts +8 -0
  44. package/dist/cli/commands/init.d.ts.map +1 -0
  45. package/dist/cli/commands/init.js +124 -0
  46. package/dist/cli/commands/init.js.map +1 -0
  47. package/dist/cli/commands/migrate.d.ts +6 -0
  48. package/dist/cli/commands/migrate.d.ts.map +1 -0
  49. package/dist/cli/commands/migrate.js +34 -0
  50. package/dist/cli/commands/migrate.js.map +1 -0
  51. package/dist/cli/index.d.ts +3 -0
  52. package/dist/cli/index.d.ts.map +1 -0
  53. package/dist/cli/index.js +39 -0
  54. package/dist/cli/index.js.map +1 -0
  55. package/dist/cli/utils/config.d.ts +11 -0
  56. package/dist/cli/utils/config.d.ts.map +1 -0
  57. package/dist/cli/utils/config.js +92 -0
  58. package/dist/cli/utils/config.js.map +1 -0
  59. package/dist/cli/utils/logger.d.ts +7 -0
  60. package/dist/cli/utils/logger.d.ts.map +1 -0
  61. package/dist/cli/utils/logger.js +15 -0
  62. package/dist/cli/utils/logger.js.map +1 -0
  63. package/dist/core/MemoGrafter.d.ts +46 -0
  64. package/dist/core/MemoGrafter.d.ts.map +1 -0
  65. package/dist/core/MemoGrafter.js +236 -0
  66. package/dist/core/MemoGrafter.js.map +1 -0
  67. package/dist/core/types.d.ts +319 -0
  68. package/dist/core/types.d.ts.map +1 -0
  69. package/dist/core/types.js +2 -0
  70. package/dist/core/types.js.map +1 -0
  71. package/dist/crawler/DecayScoringPass.d.ts.map +1 -1
  72. package/dist/crawler/DecayScoringPass.js +6 -0
  73. package/dist/crawler/DecayScoringPass.js.map +1 -1
  74. package/dist/crawler/memoryMaintenance.d.ts +1 -0
  75. package/dist/crawler/memoryMaintenance.d.ts.map +1 -1
  76. package/dist/crawler/memoryMaintenance.js +2 -1
  77. package/dist/crawler/memoryMaintenance.js.map +1 -1
  78. package/dist/crawler/types.d.ts +1 -0
  79. package/dist/crawler/types.d.ts.map +1 -1
  80. package/dist/fleet/MemoGrafterFleet.d.ts +9 -2
  81. package/dist/fleet/MemoGrafterFleet.d.ts.map +1 -1
  82. package/dist/fleet/MemoGrafterFleet.js +39 -1
  83. package/dist/fleet/MemoGrafterFleet.js.map +1 -1
  84. package/dist/fleet/WorkerAgent.d.ts +9 -4
  85. package/dist/fleet/WorkerAgent.d.ts.map +1 -1
  86. package/dist/fleet/WorkerAgent.js +45 -3
  87. package/dist/fleet/WorkerAgent.js.map +1 -1
  88. package/dist/fleet/types.d.ts +21 -2
  89. package/dist/fleet/types.d.ts.map +1 -1
  90. package/dist/index.d.ts +13 -12
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +9 -9
  93. package/dist/index.js.map +1 -1
  94. package/dist/ingestion/IngestQueue.d.ts +17 -0
  95. package/dist/ingestion/IngestQueue.d.ts.map +1 -0
  96. package/dist/ingestion/IngestQueue.js +123 -0
  97. package/dist/ingestion/IngestQueue.js.map +1 -0
  98. package/dist/ingestion/conversation/IngestPipeline.d.ts +41 -0
  99. package/dist/ingestion/conversation/IngestPipeline.d.ts.map +1 -0
  100. package/dist/ingestion/conversation/IngestPipeline.js +189 -0
  101. package/dist/ingestion/conversation/IngestPipeline.js.map +1 -0
  102. package/dist/ingestion/conversation/SegmentProcessor.d.ts +20 -0
  103. package/dist/ingestion/conversation/SegmentProcessor.d.ts.map +1 -0
  104. package/dist/ingestion/conversation/SegmentProcessor.js +110 -0
  105. package/dist/ingestion/conversation/SegmentProcessor.js.map +1 -0
  106. package/dist/ingestion/conversation/TopicDriftDetector.d.ts +40 -0
  107. package/dist/ingestion/conversation/TopicDriftDetector.d.ts.map +1 -0
  108. package/dist/ingestion/conversation/TopicDriftDetector.js +222 -0
  109. package/dist/ingestion/conversation/TopicDriftDetector.js.map +1 -0
  110. package/dist/maintenance/ConflictDetectionPass.d.ts +6 -0
  111. package/dist/maintenance/ConflictDetectionPass.d.ts.map +1 -0
  112. package/dist/maintenance/ConflictDetectionPass.js +46 -0
  113. package/dist/maintenance/ConflictDetectionPass.js.map +1 -0
  114. package/dist/maintenance/DecayScoringPass.d.ts +17 -0
  115. package/dist/maintenance/DecayScoringPass.d.ts.map +1 -0
  116. package/dist/maintenance/DecayScoringPass.js +79 -0
  117. package/dist/maintenance/DecayScoringPass.js.map +1 -0
  118. package/dist/maintenance/MemoGrafterCrawler.d.ts +14 -0
  119. package/dist/maintenance/MemoGrafterCrawler.d.ts.map +1 -0
  120. package/dist/maintenance/MemoGrafterCrawler.js +108 -0
  121. package/dist/maintenance/MemoGrafterCrawler.js.map +1 -0
  122. package/dist/maintenance/VersioningPass.d.ts +6 -0
  123. package/dist/maintenance/VersioningPass.d.ts.map +1 -0
  124. package/dist/maintenance/VersioningPass.js +40 -0
  125. package/dist/maintenance/VersioningPass.js.map +1 -0
  126. package/dist/maintenance/decayScoring.d.ts +7 -0
  127. package/dist/maintenance/decayScoring.d.ts.map +1 -0
  128. package/dist/maintenance/decayScoring.js +9 -0
  129. package/dist/maintenance/decayScoring.js.map +1 -0
  130. package/dist/maintenance/index.d.ts +7 -0
  131. package/dist/maintenance/index.d.ts.map +1 -0
  132. package/dist/maintenance/index.js +5 -0
  133. package/dist/maintenance/index.js.map +1 -0
  134. package/dist/maintenance/memoryMaintenance.d.ts +23 -0
  135. package/dist/maintenance/memoryMaintenance.d.ts.map +1 -0
  136. package/dist/maintenance/memoryMaintenance.js +141 -0
  137. package/dist/maintenance/memoryMaintenance.js.map +1 -0
  138. package/dist/maintenance/types.d.ts +65 -0
  139. package/dist/maintenance/types.d.ts.map +1 -0
  140. package/dist/maintenance/types.js +2 -0
  141. package/dist/maintenance/types.js.map +1 -0
  142. package/dist/pipeline/GrafterPipeline.d.ts +2 -0
  143. package/dist/pipeline/GrafterPipeline.d.ts.map +1 -1
  144. package/dist/pipeline/GrafterPipeline.js +33 -7
  145. package/dist/pipeline/GrafterPipeline.js.map +1 -1
  146. package/dist/pipeline/RetrieverPipeline.d.ts +1 -0
  147. package/dist/pipeline/RetrieverPipeline.d.ts.map +1 -1
  148. package/dist/pipeline/RetrieverPipeline.js +16 -5
  149. package/dist/pipeline/RetrieverPipeline.js.map +1 -1
  150. package/dist/prompts/factRetrievalPrompt.d.ts +1 -1
  151. package/dist/prompts/factRetrievalPrompt.d.ts.map +1 -1
  152. package/dist/prompts/historyCompressionPrompt.d.ts +1 -1
  153. package/dist/prompts/historyCompressionPrompt.d.ts.map +1 -1
  154. package/dist/prompts/intentShiftPrompt.d.ts +1 -1
  155. package/dist/prompts/intentShiftPrompt.d.ts.map +1 -1
  156. package/dist/prompts/memoryInjectionPrompt.d.ts +1 -1
  157. package/dist/prompts/memoryInjectionPrompt.d.ts.map +1 -1
  158. package/dist/prompts/segmentExtractionPrompt.d.ts +1 -1
  159. package/dist/prompts/segmentExtractionPrompt.d.ts.map +1 -1
  160. package/dist/retrieval/GrafterPipeline.d.ts +26 -0
  161. package/dist/retrieval/GrafterPipeline.d.ts.map +1 -0
  162. package/dist/retrieval/GrafterPipeline.js +117 -0
  163. package/dist/retrieval/GrafterPipeline.js.map +1 -0
  164. package/dist/retrieval/RetrieverPipeline.d.ts +28 -0
  165. package/dist/retrieval/RetrieverPipeline.d.ts.map +1 -0
  166. package/dist/retrieval/RetrieverPipeline.js +160 -0
  167. package/dist/retrieval/RetrieverPipeline.js.map +1 -0
  168. package/dist/schema/builders.d.ts +40 -0
  169. package/dist/schema/builders.d.ts.map +1 -0
  170. package/dist/schema/builders.js +10 -0
  171. package/dist/schema/builders.js.map +1 -0
  172. package/dist/schema/index.d.ts +3 -0
  173. package/dist/schema/index.d.ts.map +1 -0
  174. package/dist/schema/index.js +3 -0
  175. package/dist/schema/index.js.map +1 -0
  176. package/dist/schema/mg-tables.d.ts +7 -0
  177. package/dist/schema/mg-tables.d.ts.map +1 -0
  178. package/dist/schema/mg-tables.js +180 -0
  179. package/dist/schema/mg-tables.js.map +1 -0
  180. package/dist/store/GraphStore.d.ts +19 -1
  181. package/dist/store/GraphStore.d.ts.map +1 -1
  182. package/dist/store/postgres-pgvector/GraphStore.d.ts +33 -1
  183. package/dist/store/postgres-pgvector/GraphStore.d.ts.map +1 -1
  184. package/dist/store/postgres-pgvector/GraphStore.js +491 -16
  185. package/dist/store/postgres-pgvector/GraphStore.js.map +1 -1
  186. package/dist/tsconfig.cli.tsbuildinfo +1 -0
  187. package/dist/types.d.ts +53 -0
  188. package/dist/types.d.ts.map +1 -1
  189. package/dist/utils/drift/adaptiveDriftSensitivity.d.ts +1 -1
  190. package/dist/utils/drift/adaptiveDriftSensitivity.d.ts.map +1 -1
  191. package/dist/utils/drift/driftScore.d.ts +1 -1
  192. package/dist/utils/drift/driftScore.d.ts.map +1 -1
  193. package/dist/utils/drift/driftThreshold.d.ts +1 -1
  194. package/dist/utils/drift/driftThreshold.d.ts.map +1 -1
  195. package/dist/utils/drift/reentryMatch.d.ts +1 -1
  196. package/dist/utils/drift/reentryMatch.d.ts.map +1 -1
  197. package/dist/utils/extraction/segmentExtraction.d.ts +1 -1
  198. package/dist/utils/extraction/segmentExtraction.d.ts.map +1 -1
  199. package/dist/utils/reentry/reentryEdges.d.ts +1 -1
  200. package/dist/utils/reentry/reentryEdges.d.ts.map +1 -1
  201. package/dist/utils/reentry/reentrySimilarity.d.ts +1 -1
  202. package/dist/utils/reentry/reentrySimilarity.d.ts.map +1 -1
  203. package/dist/utils/reentry/reentryText.d.ts +1 -1
  204. package/dist/utils/reentry/reentryText.d.ts.map +1 -1
  205. package/package.json +14 -1
package/README.md CHANGED
@@ -38,10 +38,14 @@ MemoGrafter stores conversation turns, tracks which messages have already been i
38
38
 
39
39
  ```bash
40
40
  npm install memo-grafter
41
+ npx memo-grafter init
42
+ npx memo-grafter migrate
41
43
  ```
42
44
 
43
45
  MemoGrafter runs server-side on Node.js. The built-in storage backend uses PostgreSQL with `pgvector`.
44
46
 
47
+ `init` creates local project files under `src/memo-grafter/` (`mg-schema.ts`, `schema.ts`, and `mg.config.ts`) without touching your database. `migrate` creates or updates MemoGrafter-owned `mg_*` tables. Application tables remain managed by your existing tool, such as Prisma, Drizzle, or SQL migrations.
48
+
45
49
  ## Minimal Example
46
50
 
47
51
  ```ts
@@ -68,12 +72,34 @@ await agent.ingestText("The product roadmap now prioritizes document imports.",
68
72
  source: "import",
69
73
  });
70
74
 
75
+ await agent.remember("The user prefers concise TypeScript examples.");
76
+
71
77
  const recall = await agent.recall("travel preferences");
72
78
  console.log(recall.facts);
73
79
 
74
80
  await agent.close();
75
81
  ```
76
82
 
83
+ ## Shared Fleet Memory
84
+
85
+ Fleets can store common knowledge once and make it available to workers without
86
+ copying it into each worker session.
87
+
88
+ ```ts
89
+ const fleet = new MemoGrafterFleet(config, {
90
+ id: "support-fleet",
91
+ defaultWorkerMemory: "both",
92
+ });
93
+
94
+ await fleet.initialize();
95
+ await fleet.ingestToFleet("Refund policy: customers can request a refund within 30 days.");
96
+
97
+ const support = await fleet.createWorker({ color: "support" });
98
+ const recall = await support.recall("refund policy", { memory: "both" });
99
+
100
+ console.log(recall.facts);
101
+ ```
102
+
77
103
  ## Learn More
78
104
 
79
105
  - [USER_GUIDE.md](https://github.com/mayhemking007/memo-grafter/blob/main/USER_GUIDE.md) covers setup, configuration, adapters, queue mode, fleet APIs, examples, and troubleshooting.
package/USER_GUIDE.md CHANGED
@@ -69,13 +69,20 @@ REDIS_URL=redis://localhost:6379
69
69
 
70
70
  `REDIS_URL` is optional and only needed when you pass `queue` or `cache` config.
71
71
 
72
- Enable `pgvector` in PostgreSQL:
72
+ Initialize MemoGrafter project files and migrate the MemoGrafter tables:
73
73
 
74
- ```sql
75
- CREATE EXTENSION IF NOT EXISTS vector;
74
+ ```bash
75
+ npx memo-grafter init
76
+ npx memo-grafter migrate
76
77
  ```
77
78
 
78
- The built-in `PostgresGraphStore` creates its own tables during `initialize()`.
79
+ `memo-grafter init` creates local project files only:
80
+
81
+ - `src/memo-grafter/mg-schema.ts`: generated MemoGrafter schema reference for `mg_*` tables. This file is regenerated on every `init` run.
82
+ - `src/memo-grafter/schema.ts`: user-owned schema composition file. It is created only if missing and is never overwritten.
83
+ - `src/memo-grafter/mg.config.ts`: user-editable MemoGrafter CLI config.
84
+
85
+ `memo-grafter migrate` creates `pgvector`, `pgcrypto`, and MemoGrafter-owned `mg_*` tables in the database. It does not migrate app tables from `schema.ts`; keep using Prisma, Drizzle, raw SQL, or another migration tool for application tables.
79
86
 
80
87
  Current v1 tables:
81
88
 
@@ -94,6 +101,13 @@ Current v1 tables:
94
101
 
95
102
  ## Quick Start
96
103
 
104
+ Run the setup commands once for your app:
105
+
106
+ ```bash
107
+ npx memo-grafter init
108
+ npx memo-grafter migrate
109
+ ```
110
+
97
111
  Create `src/index.ts`:
98
112
 
99
113
  ```ts
@@ -185,6 +199,8 @@ Important fields:
185
199
  - `messageRange`: source message range.
186
200
  - `topicOrder`: chronological order.
187
201
  - `driftScore`: topic-change score.
202
+ - `suppressed`: whether the topic is temporarily hidden from recall, grafting, crawler maintenance, and active topic reads.
203
+ - `suppressedAt`: timestamp for the latest suppression, or `null` when active.
188
204
  - `agentColor`, `fleetId`, `agentId`: nullable fleet metadata.
189
205
 
190
206
  Topic nodes are stored in `mg_topic_nodes`.
@@ -201,12 +217,14 @@ Important fields:
201
217
  - `topicNodeId`: parent topic node ID.
202
218
  - `tags`: optional normalized tags copied from the session or ingest call.
203
219
  - `decayed`: whether the memory is stale.
220
+ - `forgotten`: whether the memory has been explicitly hidden by an application.
221
+ - `forgottenAt`: timestamp for the explicit forget action, or `null` when active.
204
222
  - `hasConflict`: whether crawler maintenance found a conflicting active fact.
205
223
  - `supersededBy`: newer memory ID when this memory has been replaced.
206
224
 
207
225
  Memory nodes are stored in `mg_memory_nodes`.
208
226
 
209
- `decayed`, `hasConflict`, and `supersededBy` are maintenance fields. Normal ingestion creates active memories. Optional crawler passes can later annotate existing memory rows, but they do not delete rows or rewrite topic summaries.
227
+ `decayed`, `hasConflict`, and `supersededBy` are maintenance fields. `forgotten` is an application-controlled lifecycle field. Normal ingestion creates active memories. Optional crawler passes can later annotate existing memory rows, but they do not delete rows or rewrite topic summaries.
210
228
 
211
229
  ### Graph Edges
212
230
 
@@ -241,7 +259,7 @@ There are two common forms:
241
259
  - Preview memory with `graft()`.
242
260
  - Copy memory into another chatbot with `absorbFromAgent()` or `ingestGraftedNodes()`.
243
261
 
244
- When topic nodes are absorbed into another session, MemoGrafter also copies their active memory nodes so targeted recall can find the transferred facts. Copied memory rows get fresh IDs, keep their existing embeddings, and are copied as active memories only when the source row is not decayed or superseded.
262
+ When topic nodes are absorbed into another session, MemoGrafter also copies their active memory nodes so targeted recall can find the transferred facts. Copied memory rows get fresh IDs, keep their existing embeddings, and are copied as active memories only when the source row is not decayed, superseded, forgotten, or attached to a suppressed topic.
245
263
 
246
264
  Absorbed topic nodes are also registered in `mg_graft_registry`. The registry records the destination session, copied node ID, source session ID, source node ID, and graft timestamp so applications can inspect provenance or remove a graft later.
247
265
 
@@ -324,6 +342,19 @@ Without `replace`, each text call appends to the current session memory. Later `
324
342
 
325
343
  In queue mode, `await agent.ingestText()` confirms that the ingestion job was queued. Reads may need to wait for the worker to finish before the new graph content is visible.
326
344
 
345
+ ### Remembering Explicit Facts
346
+
347
+ Use `remember()` when your application already knows a fact, preference, or note and wants to store it without running an assistant turn:
348
+
349
+ ```ts
350
+ await agent.remember("The user prefers concise TypeScript examples.", {
351
+ label: "User preference",
352
+ source: "profile-settings",
353
+ });
354
+ ```
355
+
356
+ `remember()` is a convenience wrapper around `ingestText()`. It uses the same extraction pipeline, applies the current session tags automatically, does not change `getHistory()`, and defaults `source` to `"remember"` when you do not provide one. The extraction LLM still decides which structured memories to create, so this API is best for natural-language facts and preferences rather than exact row-level inserts.
357
+
327
358
  ### Clearing A Session
328
359
 
329
360
  Use `clearSession()` when you intentionally want to reset an agent:
@@ -334,6 +365,117 @@ await agent.clearSession();
334
365
 
335
366
  This waits for pending ingestion, clears the agent's local in-memory history, removes stored messages, topic nodes, memory nodes, graph edges, segments, and resets the session ingest cursor. It is a destructive operation and is not part of normal `invoke()` processing.
336
367
 
368
+ ### Memory Lifecycle Controls
369
+
370
+ Use lifecycle controls when your application needs user-controlled memory management without physically deleting graph rows by default.
371
+
372
+ Forget a single memory node:
373
+
374
+ ```ts
375
+ const recall = await agent.recall("food preferences");
376
+ const memoryId = recall.facts[0]!.id;
377
+
378
+ const changed = await agent.forget(memoryId);
379
+ console.log(changed); // true when the memory was newly marked forgotten
380
+ ```
381
+
382
+ Forget several memory nodes at once:
383
+
384
+ ```ts
385
+ const changedCount = await agent.forgetMany([
386
+ "memory-id-a",
387
+ "memory-id-b",
388
+ ]);
389
+ ```
390
+
391
+ Suppress a topic temporarily:
392
+
393
+ ```ts
394
+ const nodes = await agent.getActiveNodes();
395
+ const topicId = nodes[0]!.id;
396
+
397
+ await agent.suppressTopic(topicId);
398
+ ```
399
+
400
+ Restore a suppressed topic:
401
+
402
+ ```ts
403
+ await agent.restoreTopic(topicId);
404
+ ```
405
+
406
+ Forgotten memories stay in `mg_memory_nodes` with `forgotten = TRUE` and `forgotten_at` set. Suppressed topics stay in `mg_topic_nodes` with `suppressed = TRUE` and `suppressed_at` set. These rows are excluded from targeted recall, invoke-time recall, graft prompt assembly, semantic graft seed selection, absorption, active topic listing, and crawler maintenance until restored where applicable.
407
+
408
+ `forget()` and `forgetMany()` are one-way soft lifecycle operations. There is no built-in `restoreMemory()` API because user-requested memory deletion and privacy flows usually need conservative behavior. Applications that require undo or hard deletion can implement that policy at the storage layer.
409
+
410
+ `getGraphSnapshot()` remains useful for audit and visualization. Snapshot memory reads include forgotten, decayed, conflicted, and superseded rows, and snapshot topic reads include suppressed topics, so UIs can display lifecycle state explicitly.
411
+
412
+ The lower-level `MemoGrafter` class exposes the same methods when you manage sessions yourself:
413
+
414
+ ```ts
415
+ await memo.forget(memoryId);
416
+ await memo.forgetMany(memoryIds);
417
+ await memo.suppressTopic(topicId);
418
+ await memo.restoreTopic(topicId);
419
+ ```
420
+
421
+ ### Memory History And Diff
422
+
423
+ Use memory history APIs when your application needs audit trails, explainability, or debugging for facts that changed over time.
424
+
425
+ Look up history from a specific memory node:
426
+
427
+ ```ts
428
+ const history = await agent.getMemoryHistory(memoryId);
429
+
430
+ for (const entry of history.entries) {
431
+ console.log(entry.versionIndex);
432
+ console.log(entry.status);
433
+ console.log(entry.memory.value);
434
+ console.log(entry.supersededBy);
435
+ console.log(entry.supersedes);
436
+ console.log(entry.conflictsWith);
437
+ }
438
+
439
+ console.log(history.currentMemory);
440
+ ```
441
+
442
+ Look up history by fact key:
443
+
444
+ ```ts
445
+ const history = await agent.getMemoryHistory("user", "location");
446
+ ```
447
+
448
+ `MemoGrafterAgent` scopes history lookups to the current session. If you manage sessions yourself with `MemoGrafter`, pass the session explicitly:
449
+
450
+ ```ts
451
+ const history = await memo.getMemoryHistory("user", "location", {
452
+ sessionId,
453
+ });
454
+ ```
455
+
456
+ Compare two memory versions:
457
+
458
+ ```ts
459
+ const diff = await agent.getMemoryDiff(oldMemoryId, newMemoryId);
460
+
461
+ console.log(diff.changedFields);
462
+ console.log(diff.relationship.supersededBy);
463
+ console.log(diff.relationship.updateEdges);
464
+ console.log(diff.relationship.conflictEdges);
465
+ ```
466
+
467
+ History results are read-only and derived from existing memory rows plus `supersededBy`, `updates`, and `conflicts` metadata. They intentionally include superseded, decayed, forgotten, and suppressed-topic memories, even though those rows are excluded from normal recall and grafting.
468
+
469
+ `MemoryHistoryEntry.status` is one of:
470
+
471
+ - `"active"`: not superseded, decayed, forgotten, or conflicting.
472
+ - `"superseded"`: the memory has `supersededBy` set.
473
+ - `"conflicting"`: the memory has `hasConflict` or a `conflicts` edge.
474
+ - `"decayed"`: crawler decay marked the memory stale.
475
+ - `"forgotten"`: an application explicitly forgot the memory.
476
+
477
+ `getMemoryDiff()` is structural. It compares stored fields such as `value`, `confidence`, lifecycle flags, tags, source metadata, and timestamps. It does not call an LLM or generate prose explanations.
478
+
337
479
  ### Session Tags
338
480
 
339
481
  Use session tags when you want to organize memory by project, planning area, week, domain, or worker route.
@@ -418,7 +560,7 @@ const projectMemory = await agent.recall("deployment decisions", {
418
560
  });
419
561
  ```
420
562
 
421
- This can return matching active memories from older or different sessions with the same tag. If your development database contains repeated smoke-test runs, you may see more than one matching fact because the older tagged rows are still present.
563
+ This can return matching active memories from older or different sessions with the same tag. Active recall excludes decayed, superseded, forgotten, and suppressed-topic memories. If your development database contains repeated smoke-test runs, you may see more than one matching fact because the older tagged rows are still present.
422
564
 
423
565
  `MemoGrafterAgent.invoke()` also calls `recall()` internally before answering when the session has topic nodes. In that automatic path, the returned `systemPrompt` is pinned as a single system message before the recent raw chat window. Automatic recall uses `inject.recallLimit` and `inject.recallMinSimilarity`, defaulting to `6` and `0.55`.
424
566
 
@@ -436,6 +578,7 @@ console.log(snapshot.nodes);
436
578
  console.log(snapshot.snapshotNodes);
437
579
  console.log(snapshot.edges);
438
580
  console.log(snapshot.memories);
581
+ console.log(snapshot.snapshotMemories);
439
582
  console.log(snapshot.memoryEdges);
440
583
  console.log(snapshot.capturedAt);
441
584
  ```
@@ -443,18 +586,30 @@ console.log(snapshot.capturedAt);
443
586
  `getGraphSnapshot()` returns a `GraphSnapshot`:
444
587
 
445
588
  - `sessionId`: current agent session ID.
446
- - `nodes`: active topic nodes for the session.
447
- - `snapshotNodes`: active topic nodes wrapped with provenance metadata when a node came from a graft.
589
+ - `nodes`: topic nodes for the session, including suppressed nodes for audit views.
590
+ - `snapshotNodes`: topic nodes wrapped with lifecycle metadata and optional graft provenance.
448
591
  - `edges`: topic edges where either endpoint belongs to a session topic node.
449
- - `memories`: all memory nodes for the session, including decayed or superseded rows.
592
+ - `memories`: all memory nodes for the session, including forgotten, decayed, conflicted, or superseded rows.
593
+ - `snapshotMemories`: memory nodes wrapped with lifecycle metadata.
450
594
  - `memoryEdges`: memory-level edges such as `semantic`, `conflicts`, `updates`, and `related`.
451
595
  - `capturedAt`: ISO timestamp for when the snapshot was produced.
452
596
 
453
- Each `snapshotNodes` entry contains the topic `node` and an optional `graftOrigin` with `sourceSessionId`, `sourceNodeId`, and `graftedAt`. The plain `nodes` array remains available for callers that only need the topic nodes.
597
+ Each `snapshotNodes` entry contains:
598
+
599
+ - `node`: the topic node.
600
+ - `lifecycle`: `{ suppressed, suppressedAt }`.
601
+ - `graftOrigin`: optional `{ sourceSessionId, sourceNodeId, graftedAt }` when the node came from a graft.
602
+
603
+ Each `snapshotMemories` entry contains:
604
+
605
+ - `memory`: the memory node.
606
+ - `lifecycle`: `{ forgotten, forgottenAt, decayed, supersededBy, hasConflict }`.
607
+
608
+ The `nodes`, `edges`, `memories`, and `memoryEdges` arrays remain available for backward-compatible callers that already read the raw graph rows directly. Snapshot arrays are sorted deterministically so graph UIs can use them as a stable primary data source.
454
609
 
455
610
  This method is read-only. It does not include raw `mg_message_buffer` content and does not add rendering, layout, or color decisions. Like `getActiveNodes()` and `getActiveSegments()`, it waits for the agent's pending ingest work before reading. If called immediately after `invoke()` in queue mode, it waits for the current ingest job to settle before returning.
456
611
 
457
- Graph snapshots intentionally include stale and maintenance metadata so visualizers can show memory lifecycle state. For example, a UI can fade `decayed` memories, show `hasConflict` badges, draw `conflicts` edges between contradictory facts, and draw `updates` edges from the current fact to the older fact it replaced.
612
+ Graph snapshots intentionally include stale and maintenance metadata so visualizers can show memory lifecycle state. For example, a UI can hide or label `forgotten` memories, fade `decayed` memories, show `hasConflict` badges, draw `conflicts` edges between contradictory facts, draw `updates` edges from the current fact to the older fact it replaced, and show suppressed topics separately from active topics.
458
613
 
459
614
  Read active topic nodes:
460
615
 
@@ -553,6 +708,8 @@ Active memory facts:
553
708
 
554
709
  This keeps history intact while telling the downstream model which fact is current.
555
710
 
711
+ Suppressed topics are not included in graft prompts, even if their IDs are passed explicitly. Forgotten memories are not included as active facts or as replacement details in maintenance notes.
712
+
556
713
  ## Maintaining Memory With The Crawler
557
714
 
558
715
  `MemoGrafterCrawler` is an optional graph maintenance worker. It can run once on demand or on a simple in-process interval. It does not use Redis, BullMQ, OpenAI, embeddings, or LLMs for the built-in conflict/versioning/decay passes.
@@ -608,6 +765,7 @@ The built-in conflict and versioning passes use separate deterministic classifie
608
765
  - a group conflicts when it has different normalized `value` strings and the newest value does not contain an explicit update cue;
609
766
  - a group versions only when its newest value contains an explicit replacement or update cue such as `actually`, `now`, `changed to`, or `instead`;
610
767
  - decayed memories are skipped;
768
+ - forgotten memories and memories attached to suppressed topics are skipped;
611
769
  - already superseded memories are skipped;
612
770
  - broad topic memories with generic subject/predicate pairs are skipped unless they match a recognized competing trip-plan pattern;
613
771
  - version replacement candidates are selected by `createdAt`;
@@ -624,7 +782,7 @@ recency_factor = exp(-(ln(2) / half_life_days) * age_days)
624
782
  decay_score = confidence * recency_factor
625
783
  ```
626
784
 
627
- If `decay_score < minScore`, the memory is marked `decayed: true`. Superseded memories and already decayed memories are skipped. Conservative defaults are used when options are omitted:
785
+ If `decay_score < minScore`, the memory is marked `decayed: true`. Superseded memories, forgotten memories, and already decayed memories are skipped. Conservative defaults are used when options are omitted:
628
786
 
629
787
  ```ts
630
788
  new DecayScoringPass({
@@ -647,7 +805,7 @@ When explicit replacements are found:
647
805
  - an `updates` edge is created as `newer_memory --updates--> older_memory`.
648
806
  - stale active memories can be marked `decayed: true` by the decay pass.
649
807
 
650
- Crawler maintenance is non-destructive. It annotates existing memory rows and creates memory edges. It does not delete nodes, does not rebuild topics, and does not rewrite topic summaries.
808
+ Crawler maintenance is non-destructive. It annotates existing memory rows and creates memory edges. It does not delete nodes, does not rebuild topics, and does not rewrite topic summaries. Forgotten memories and memories attached to suppressed topics are ignored by maintenance scans.
651
809
 
652
810
  Existing incorrect conflict edges are not automatically deleted. If an older crawler run created a false-positive edge, handle cleanup with a future explicit pruning pass or filter displayed memory edges to active memories in your app.
653
811
 
@@ -689,7 +847,7 @@ const response = await writingBot.invoke(
689
847
  console.log(response);
690
848
  ```
691
849
 
692
- Absorbing copies selected topic nodes into the target session and creates `grafted` edges back to their source nodes. It also copies active memory facts attached to those topic nodes into the target session so future `recall()` and `invoke()` calls can surface the transferred context. Decayed or superseded source memories are not copied.
850
+ Absorbing copies selected topic nodes into the target session and creates `grafted` edges back to their source nodes. It also copies active memory facts attached to those topic nodes into the target session so future `recall()` and `invoke()` calls can surface the transferred context. Decayed, superseded, forgotten, or suppressed-topic source memories are not copied.
693
851
 
694
852
  Each copied topic node is recorded in the graft registry. Registry entries let you answer where a graft came from and which copied destination node owns it.
695
853
 
@@ -1030,6 +1188,18 @@ Run the semantic grafting smoke with a real PostgreSQL database:
1030
1188
  npx tsx --env-file=.env ./tests/manual/graft/graft-by-relevance-smoke.ts
1031
1189
  ```
1032
1190
 
1191
+ Run the memory lifecycle smoke with a real PostgreSQL database and `OPENAI_API_KEY`:
1192
+
1193
+ ```powershell
1194
+ npx tsx --env-file=.env ./tests/manual/graft/memory-lifecycle-smoke.ts
1195
+ ```
1196
+
1197
+ Run the memory history smoke with a real PostgreSQL database:
1198
+
1199
+ ```powershell
1200
+ npx tsx --env-file=.env ./tests/manual/graft/memory-history-smoke.ts
1201
+ ```
1202
+
1033
1203
  Use the forward-slash path in PowerShell. An unquoted backslash path can be collapsed before `tsx` receives it.
1034
1204
 
1035
1205
  The smoke creates two tagged sessions, writes one memory into each, verifies current-session tag filtering with `getActiveNodes()`, and verifies cross-session project recall with `recall(..., { scope: "tagged" })`. If you run it repeatedly against the same database, tagged recall can return rows from previous smoke runs because those historical sessions are still present.
@@ -1158,6 +1328,7 @@ import {
1158
1328
  } from "memo-grafter";
1159
1329
 
1160
1330
  const store = new PostgresGraphStore(process.env.DATABASE_URL!);
1331
+ await store.migrate(); // Or run `npx memo-grafter migrate` before app startup.
1161
1332
  await store.initialize();
1162
1333
 
1163
1334
  const embedder = new OpenAIEmbedAdapter("text-embedding-3-small");
@@ -1234,6 +1405,63 @@ await fleet.close();
1234
1405
 
1235
1406
  The worker color `conductor` is reserved.
1236
1407
 
1408
+ ### Shared fleet memory
1409
+
1410
+ Fleet memory is a shared parent scope for every worker in a fleet. Use it for
1411
+ common knowledge such as product docs, company policies, operating procedures,
1412
+ or global application context.
1413
+
1414
+ ```ts
1415
+ await fleet.ingestToFleet(
1416
+ "Refund policy: customers can request a refund within 30 days.",
1417
+ {
1418
+ tags: ["policy"],
1419
+ source: "support-handbook",
1420
+ }
1421
+ );
1422
+
1423
+ const shared = await fleet.getSharedMemory();
1424
+ console.log(shared.memories);
1425
+
1426
+ const recall = await fleet.recallFromFleet("refund policy");
1427
+ console.log(recall.facts);
1428
+ ```
1429
+
1430
+ Workers keep their own session memory. When a worker should also inherit fleet
1431
+ knowledge, configure its memory mode:
1432
+
1433
+ ```ts
1434
+ const support = await fleet.createWorker({
1435
+ color: "support",
1436
+ memory: "both",
1437
+ });
1438
+
1439
+ await support.invoke("What is the refund window?");
1440
+ ```
1441
+
1442
+ Worker retrieval and relevance grafting can also choose the scope per call:
1443
+
1444
+ ```ts
1445
+ await support.recall("refund policy", {
1446
+ memory: "fleet",
1447
+ });
1448
+
1449
+ await support.graftByRelevance("refund policy", {
1450
+ memory: "both",
1451
+ minSimilarity: 0.55,
1452
+ });
1453
+ ```
1454
+
1455
+ Memory modes:
1456
+
1457
+ - `"local"`: only the worker session memory.
1458
+ - `"fleet"`: only the shared fleet memory.
1459
+ - `"both"`: worker session memory plus shared fleet memory.
1460
+
1461
+ The default worker mode is `"local"` for compatibility. You can set
1462
+ `defaultWorkerMemory: "both"` when creating the fleet if all workers should
1463
+ inherit shared fleet memory unless overridden.
1464
+
1237
1465
  Prompt-guided fleet grafting:
1238
1466
 
1239
1467
  ```ts
@@ -1405,6 +1633,7 @@ Practical notes:
1405
1633
  - Tune `tokenBudget` to control prompt size and cost.
1406
1634
  - Use queue mode if ingestion becomes slow.
1407
1635
  - Use `clearSession()` only for intentional resets; normal ingestion preserves the graph incrementally.
1636
+ - Use `forget()`, `forgetMany()`, `suppressTopic()`, and `restoreTopic()` for user-controlled memory lifecycle flows.
1408
1637
  - Use the optional recall cache for long sessions with repeated direct or invoke-time recall.
1409
1638
  - Store your own user/session mapping outside MemoGrafter.
1410
1639
  - Call `close()` during graceful shutdown.
@@ -1440,6 +1669,7 @@ Main exports:
1440
1669
  - `TagFilterOptions`
1441
1670
  - `IngestOptions`
1442
1671
  - `IngestTextOptions`
1672
+ - `RememberOptions`
1443
1673
  - public shared and fleet types
1444
1674
 
1445
1675
  Useful `GraphStore` inspection methods:
@@ -1453,21 +1683,36 @@ Useful `GraphStore` inspection methods:
1453
1683
  - `getMemoryEdgesBySession(sessionId)`
1454
1684
  - `getSessionNodeCount(sessionId)`
1455
1685
  - `getSessionIngestState(sessionId)`
1686
+ - `forgetMemory(memoryId)`
1687
+ - `forgetMemories(memoryIds)`
1688
+ - `suppressTopic(topicId)`
1689
+ - `restoreTopic(topicId)`
1690
+ - `getMemoryHistoryById(memoryId, options?)`
1691
+ - `getMemoryHistoryByFact(subject, predicate, options?)`
1692
+ - `getMemoryDiff(fromMemoryId, toMemoryId)`
1456
1693
 
1457
1694
  Common `MemoGrafterAgent` methods:
1458
1695
 
1459
- - `initialize()`: initialize storage.
1696
+ - `initialize()`: verify that MemoGrafter storage has already been migrated.
1460
1697
  - `invoke(message)`: send a user message and receive an assistant response.
1461
1698
  - `ingestText(text, options?)`: ingest raw text without generating an assistant response.
1699
+ - `remember(text, options?)`: store explicit natural-language facts or preferences through the text ingestion path.
1462
1700
  - `getHistory()`: read local chat history.
1463
1701
  - `getSessionId()`: read the current session ID.
1464
- - `getGraphSnapshot()`: read nodes, edges, memories, session ID, and capture timestamp for visualization or inspection.
1702
+ - `getGraphSnapshot()`: read a stable graph snapshot with raw topic and memory rows, graph edges, lifecycle metadata, graft metadata, session ID, and capture timestamp for visualization or inspection.
1465
1703
  - `getGraftRegistry()`: inspect provenance for grafted nodes in the current session.
1466
1704
  - `getActiveNodes(options?)`: inspect topic nodes, optionally filtered by tags.
1467
1705
  - `getActiveSegments()`: inspect topic segments.
1468
1706
  - `setSessionTags(tags)`: replace tags on the current session and apply them to future ingested memories.
1469
1707
  - `getSessionTags()`: read the current agent's normalized session tags.
1470
1708
  - `clearSession()`: explicitly clear local history and stored session memory.
1709
+ - `forget(memoryId)`: soft-forget a memory node so it is excluded from future recall, grafting, absorption, and crawler maintenance.
1710
+ - `forgetMany(memoryIds)`: soft-forget several memory nodes and return the number changed.
1711
+ - `suppressTopic(topicId)`: hide a topic from active reads, recall, grafting, absorption, and crawler maintenance.
1712
+ - `restoreTopic(topicId)`: make a suppressed topic active again.
1713
+ - `getMemoryHistory(memoryId)`: inspect the current session lineage for a specific memory.
1714
+ - `getMemoryHistory(subject, predicate)`: inspect the current session lineage for a fact key.
1715
+ - `getMemoryDiff(fromMemoryId, toMemoryId)`: compare two memory versions and their maintenance relationship.
1471
1716
  - `recall(query, options?)`: retrieve structured memory by semantic query, optionally filtered by tags.
1472
1717
  - `graft(topicIds?)`: preview memory injection.
1473
1718
  - `graftByRelevance(query, options?)`: preview memory injection selected by semantic topic-node relevance.
@@ -2,7 +2,7 @@ import { Redis } from "ioredis";
2
2
  import { MemoGrafterFleet } from "./fleet/MemoGrafterFleet.js";
3
3
  import type { MemoGrafterFleetOptions } from "./fleet/types.js";
4
4
  import type { GraphStore } from "./store/index.js";
5
- import type { AbsorbFromAgentOptions, EmbedAdapter, GraftByRelevanceOptions, IngestOptions, IngestTextOptions, InjectionResult, LLMAdapter, MemoGrafterConfig, Message, TopicNode, TopicSegment } from "./types.js";
5
+ import type { AbsorbFromAgentOptions, EmbedAdapter, GraftByRelevanceOptions, IngestOptions, IngestTextOptions, InjectionResult, LLMAdapter, MemoryDiff, MemoryHistoryOptions, MemoryHistoryResult, MemoGrafterConfig, Message, TagFilterOptions, TopicNode, TopicSegment } from "./types.js";
6
6
  export declare class MemoGrafter {
7
7
  readonly llm: LLMAdapter;
8
8
  readonly embedder: EmbedAdapter;
@@ -20,14 +20,18 @@ export declare class MemoGrafter {
20
20
  enqueueIngest(messages: Message[], sessionId: string, options?: IngestOptions): Promise<void>;
21
21
  ingestText(text: string, sessionId: string, options?: IngestTextOptions & IngestOptions): Promise<TopicNode[]>;
22
22
  enqueueTextIngest(text: string, sessionId: string, options?: IngestTextOptions & IngestOptions): Promise<void>;
23
- getTopics(sessionId: string, options?: {
24
- tags?: string[];
25
- tagMode?: "all" | "any";
26
- }): Promise<{
23
+ getTopics(sessionId: string, options?: TagFilterOptions): Promise<{
27
24
  nodes: TopicNode[];
28
25
  segments: TopicSegment[];
29
26
  }>;
30
27
  inject(sessionId: string, topicIds: string[]): Promise<InjectionResult>;
28
+ forget(memoryId: string): Promise<boolean>;
29
+ forgetMany(memoryIds: string[]): Promise<number>;
30
+ suppressTopic(topicId: string): Promise<boolean>;
31
+ restoreTopic(topicId: string): Promise<boolean>;
32
+ getMemoryHistory(memoryId: string, options?: MemoryHistoryOptions): Promise<MemoryHistoryResult>;
33
+ getMemoryHistory(subject: string, predicate: string, options?: MemoryHistoryOptions): Promise<MemoryHistoryResult>;
34
+ getMemoryDiff(fromMemoryId: string, toMemoryId: string): Promise<MemoryDiff>;
31
35
  graftByRelevance(sessionId: string, query: string, options?: GraftByRelevanceOptions): Promise<InjectionResult>;
32
36
  ingestGraftedNodes(nodes: TopicNode[], targetSessionId: string): Promise<TopicNode[]>;
33
37
  selectNodesForAbsorb(sourceSessionId: string, options: AbsorbFromAgentOptions): Promise<TopicNode[]>;
@@ -36,5 +40,7 @@ export declare class MemoGrafter {
36
40
  close(): Promise<void>;
37
41
  private assertServerEnvironment;
38
42
  private toTextPipelineOptions;
43
+ private clearRecallCache;
44
+ private resolveSessionIds;
39
45
  }
40
46
  //# sourceMappingURL=MemoGrafter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MemoGrafter.d.ts","sourceRoot":"","sources":["../src/MemoGrafter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MemoGrafter.d.ts","sourceRoot":"","sources":["../src/MemoGrafter.ts"],"names":[],"mappings":"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"}
@@ -107,18 +107,61 @@ export class MemoGrafter {
107
107
  inject(sessionId, topicIds) {
108
108
  return this.grafterPipeline.run(sessionId, topicIds);
109
109
  }
110
+ async forget(memoryId) {
111
+ const changed = await this.store.forgetMemory(memoryId);
112
+ if (changed)
113
+ await this.clearRecallCache();
114
+ return changed;
115
+ }
116
+ async forgetMany(memoryIds) {
117
+ const changed = await this.store.forgetMemories(memoryIds);
118
+ if (changed > 0)
119
+ await this.clearRecallCache();
120
+ return changed;
121
+ }
122
+ async suppressTopic(topicId) {
123
+ const changed = await this.store.suppressTopic(topicId);
124
+ if (changed)
125
+ await this.clearRecallCache();
126
+ return changed;
127
+ }
128
+ async restoreTopic(topicId) {
129
+ const changed = await this.store.restoreTopic(topicId);
130
+ if (changed)
131
+ await this.clearRecallCache();
132
+ return changed;
133
+ }
134
+ getMemoryHistory(memoryIdOrSubject, predicateOrOptions, options = {}) {
135
+ if (typeof predicateOrOptions === "string") {
136
+ return this.store.getMemoryHistoryByFact(memoryIdOrSubject, predicateOrOptions, options);
137
+ }
138
+ return this.store.getMemoryHistoryById(memoryIdOrSubject, predicateOrOptions ?? {});
139
+ }
140
+ getMemoryDiff(fromMemoryId, toMemoryId) {
141
+ return this.store.getMemoryDiff(fromMemoryId, toMemoryId);
142
+ }
110
143
  async graftByRelevance(sessionId, query, options = {}) {
111
144
  const embedding = await this.embedder.embed(query);
112
- const seedNodes = await this.store.getSimilarNodes(embedding, sessionId, {
113
- k: options.topK ?? this.graphTopK,
114
- minSimilarity: options.minSimilarity ?? 0.6,
115
- });
145
+ const configuredSessionIds = options.sessionIds?.filter(Boolean) ?? [];
146
+ const sessionIds = this.resolveSessionIds(sessionId, configuredSessionIds);
147
+ const useConfiguredSessions = configuredSessionIds.length > 0
148
+ && (sessionIds.length > 1 || sessionIds[0] !== sessionId);
149
+ const seedNodes = useConfiguredSessions
150
+ ? await this.store.getSimilarNodesAcrossSessions(embedding, sessionIds, {
151
+ k: options.topK ?? this.graphTopK,
152
+ minSimilarity: options.minSimilarity ?? 0.6,
153
+ })
154
+ : await this.store.getSimilarNodes(embedding, sessionId, {
155
+ k: options.topK ?? this.graphTopK,
156
+ minSimilarity: options.minSimilarity ?? 0.6,
157
+ });
116
158
  if (seedNodes.length === 0) {
117
159
  return { systemPrompt: "", nodes: [], tokenCount: 0 };
118
160
  }
119
161
  return this.grafterPipeline.run(sessionId, seedNodes.map((node) => node.id), {
120
162
  hopDepth: options.hopDepth ?? this.graphHopDepth,
121
163
  expansionStrategy: options.expansionStrategy ?? "graph",
164
+ ...(configuredSessionIds.length > 0 ? { sessionIds } : {}),
122
165
  });
123
166
  }
124
167
  async ingestGraftedNodes(nodes, targetSessionId) {
@@ -172,5 +215,22 @@ export class MemoGrafter {
172
215
  sourceType: "document",
173
216
  };
174
217
  }
218
+ async clearRecallCache() {
219
+ if (!this.recallCache)
220
+ return;
221
+ try {
222
+ const keys = await this.recallCache.keys("mg:recall:*");
223
+ if (keys.length > 0) {
224
+ await this.recallCache.del(...keys);
225
+ }
226
+ }
227
+ catch (error) {
228
+ console.warn("MemoGrafter recall cache invalidation warning:", error);
229
+ }
230
+ }
231
+ resolveSessionIds(sessionId, configured) {
232
+ const sessionIds = configured && configured.length > 0 ? configured : [sessionId];
233
+ return [...new Set(sessionIds)];
234
+ }
175
235
  }
176
236
  //# sourceMappingURL=MemoGrafter.js.map