@melandlabs/memory-store 0.3.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +209 -56
- package/dist/{config-2Q092MUz.d.ts → config-CnbqSek5.d.ts} +215 -2
- package/dist/contracts.d.ts +1 -0
- package/dist/contracts.js +2 -0
- package/dist/http.d.ts +21 -5
- package/dist/http.js +1051 -155
- package/dist/index.d.ts +230 -15
- package/dist/index.js +1087 -152
- package/dist/mcp.d.ts +14 -5
- package/dist/mcp.js +1188 -174
- package/dist/policies/memory-graph-correction-policy.d.ts +1 -0
- package/dist/policies/memory-graph-correction-policy.js +4 -0
- package/dist/policies/memory-graph-write-policy.d.ts +1 -0
- package/dist/policies/memory-graph-write-policy.js +2 -0
- package/dist/search/unified-search.d.ts +6 -19
- package/dist/search/unified-search.js +749 -145
- package/dist/server/cli-http.js +1051 -155
- package/dist/server/cli-mcp.js +1185 -171
- package/dist/server/cli-shared.d.ts +5 -2
- package/dist/server/cli-shared.js +6 -4
- package/dist/storage/chroma-memory-index.d.ts +1 -0
- package/dist/storage/chroma-memory-index.js +1 -2
- package/dist/storage/postgres-raw-message-factory.d.ts +4 -1
- package/dist/storage/raw-message-store.d.ts +5 -2
- package/dist/storage/raw-message-store.js +6 -4
- package/dist/storage/sqlite-raw-message-store.d.ts +5 -1
- package/dist/storage/sqlite-raw-message-store.js +6 -4
- package/dist/storage/sqlite-vector-index.d.ts +4 -1
- package/dist/storage/sqlite-vector-index.js +4 -4
- package/dist/unified-search-Bft57TRH.d.ts +122 -0
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
OpenContext memory storage + search SDK with optional HTTP and MCP server
|
|
9
9
|
entry points. The package is intentionally decoupled from the opencontext
|
|
10
|
-
web app's database
|
|
11
|
-
|
|
10
|
+
web app's database layer — every consumer wires up its own backend via
|
|
11
|
+
the `db` contract on `MemoryStoreConfig`.
|
|
12
12
|
|
|
13
13
|
- **SDK** (`memory-store`) — embed in a Node.js host
|
|
14
14
|
- **HTTP** (`memory-store/http`) — REST daemon
|
|
@@ -23,20 +23,35 @@ pnpm add @melandlabs/opencontext
|
|
|
23
23
|
## Quick start
|
|
24
24
|
|
|
25
25
|
```ts
|
|
26
|
-
import { createMemoryStore } from "
|
|
26
|
+
import { createMemoryStore } from "@melandlabs/opencontext";
|
|
27
27
|
|
|
28
28
|
const store = await createMemoryStore({
|
|
29
|
+
// Required for the postgres backend (OPENCONTEXT_MEMORY_STORE_BACKEND=postgres).
|
|
30
|
+
// For the default sqlite backend, omit db and the SDK writes to
|
|
31
|
+
// ~/.opencontext/memory/store.db (override with MEMORY_STORE_DB_PATH).
|
|
29
32
|
db: { getDb: () => drizzleDb() },
|
|
30
|
-
env: { isTauriMode: () => false },
|
|
31
33
|
unified: {
|
|
32
34
|
embedQuery: async ({ query }) => myEmbed(query),
|
|
33
35
|
},
|
|
34
36
|
});
|
|
35
37
|
|
|
36
|
-
await store.
|
|
37
|
-
const hits = await store.searchUnifiedMemory({ userId, query });
|
|
38
|
+
const hits = await store.search({ userId, query });
|
|
38
39
|
```
|
|
39
40
|
|
|
41
|
+
## Capabilities
|
|
42
|
+
|
|
43
|
+
The store exposes the four-verb memory API plus two read/write reflection
|
|
44
|
+
endpoints:
|
|
45
|
+
|
|
46
|
+
| Capability | SDK method | HTTP | MCP tool |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| Read-only search across all sources | `store.search(input)` | `POST /v1/search` | `memory.search` |
|
|
49
|
+
| Read a single `RawMessage` | `manager.getMessageById(id)` | `GET /v1/raw-messages/:id?userId=…` | `memory.getRawMessage` |
|
|
50
|
+
| Persist a `RawMessage` | `manager.storeMessages([…])` | `POST /v1/raw-messages` | `memory.writeRawMessage` |
|
|
51
|
+
| Read-only LLM synthesis over evidence | `store.search({ ...input, synthesize: true })` | `POST /v1/search` (set `synthesize: true`) | `memory.search` (set `synthesize: true`) |
|
|
52
|
+
| **Agentic write-back** (gather → plan → vet → persist) | `store.consolidate(input)` | `POST /v1/consolidate:apply` | `memory.consolidate` |
|
|
53
|
+
| Health probe | — | `GET /health` | `memory.health` |
|
|
54
|
+
|
|
40
55
|
## Entry points
|
|
41
56
|
|
|
42
57
|
| Import | What you get |
|
|
@@ -56,10 +71,9 @@ opencontext-memory-mcp
|
|
|
56
71
|
|
|
57
72
|
| Key | Required | Description |
|
|
58
73
|
| ----------------------------------------------------- | ------------------------------- | --------------------------------------------------------- |
|
|
59
|
-
| `db.getDb()` | yes for
|
|
60
|
-
| `db.tables.rawMessages` / `db.tables.memorySummaries` |
|
|
61
|
-
| `
|
|
62
|
-
| `env.getTauriDbPath()` / `env.getTauriDataDir()` | for Tauri | where to place the SQLite files |
|
|
74
|
+
| `db.getDb()` | yes for postgres backend | Drizzle DB handle factory |
|
|
75
|
+
| `db.tables.rawMessages` / `db.tables.memorySummaries` | when using postgres backend | Drizzle table references owned by the host |
|
|
76
|
+
| `dbPath` | optional | SQLite path override (also reads `MEMORY_STORE_DB_PATH`) |
|
|
63
77
|
| `vector.backend` | one of `sqlite-vec` or `chroma` | vector index backend (auto-detected if omitted) |
|
|
64
78
|
| `vector.sqliteVec.dbPath` | when backend = sqlite-vec | sqlite-vec DB path |
|
|
65
79
|
| `vector.chroma.url` | when backend = chroma | chroma server URL |
|
|
@@ -67,8 +81,19 @@ opencontext-memory-mcp
|
|
|
67
81
|
| `unified.searchKnowledge` | optional | RAG over uploaded documents |
|
|
68
82
|
| `unified.searchInsights` | optional | semantic search over extracted insights |
|
|
69
83
|
| `unified.searchRawMessagesAnn` | optional | postgres-side ANN over `raw_messages` (database fallback) |
|
|
84
|
+
| `unified.searchRawMessagesLexical` | optional | BM25/FTS5 fallback when lexical search is enabled |
|
|
85
|
+
| `unified.searchSummaries` | optional | L1/L2/L3 summary recall (used by `reflect`) |
|
|
86
|
+
| `unified.peerScopeCheck` | optional | host check that gates `peerFilter` narrowing |
|
|
87
|
+
| `unified.reranker` | optional | cross-encoder / learned ranker applied after merge |
|
|
88
|
+
| `graphStore` | optional | `MemoryGraphStoreWithOperationHistory`; powers `consolidate` |
|
|
89
|
+
| `storage` | optional | `MemoryStorageAdapter` for `deprecateRecords` writes |
|
|
70
90
|
| `logger` | optional | `console`-shaped logger; defaults to `console` |
|
|
71
91
|
|
|
92
|
+
Backend selection is **env-var driven, not host-injected**: the default is
|
|
93
|
+
SQLite at `~/.opencontext/memory/store.db`; set
|
|
94
|
+
`OPENCONTEXT_MEMORY_STORE_BACKEND=postgres` to opt into the host's
|
|
95
|
+
registered Postgres factory (call `registerPostgresFactory` at startup).
|
|
96
|
+
|
|
72
97
|
If any of `unified.embedQuery`, `unified.searchKnowledge`, `unified.searchInsights`,
|
|
73
98
|
or `unified.searchRawMessagesAnn` are absent, the corresponding source in
|
|
74
99
|
`searchUnifiedMemory` returns empty results with a warning. The SDK still
|
|
@@ -86,7 +111,7 @@ import {
|
|
|
86
111
|
createMemoryStore,
|
|
87
112
|
registerPostgresFactory,
|
|
88
113
|
type PostgresRawMessageManagerLike,
|
|
89
|
-
} from "memory-store";
|
|
114
|
+
} from "@melandlabs/memory-store";
|
|
90
115
|
import { myPostgresRawMessageManager } from "./postgres-raw-message-store";
|
|
91
116
|
import * as schema from "./schema";
|
|
92
117
|
|
|
@@ -105,7 +130,6 @@ const store = await createMemoryStore({
|
|
|
105
130
|
memorySummaries: schema.memorySummaries,
|
|
106
131
|
},
|
|
107
132
|
},
|
|
108
|
-
env: { isTauriMode: () => false },
|
|
109
133
|
unified: {
|
|
110
134
|
embedQuery: async ({ query }) => myEmbedder.embedQuery(query),
|
|
111
135
|
searchInsights: mySearchInsights,
|
|
@@ -121,15 +145,11 @@ const store = await createMemoryStore({
|
|
|
121
145
|
});
|
|
122
146
|
```
|
|
123
147
|
|
|
124
|
-
### 2.
|
|
148
|
+
### 2. SQLite-vec backend (desktop / local)
|
|
125
149
|
|
|
126
150
|
```ts
|
|
127
151
|
const store = await createMemoryStore({
|
|
128
|
-
|
|
129
|
-
isTauriMode: () => true,
|
|
130
|
-
getTauriDataDir: () => appDataDir(),
|
|
131
|
-
getTauriDbPath: () => `${appDataDir()}/memory.sqlite`,
|
|
132
|
-
},
|
|
152
|
+
dbPath: `${appDataDir()}/memory.sqlite`,
|
|
133
153
|
vector: {
|
|
134
154
|
backend: "sqlite-vec",
|
|
135
155
|
sqliteVec: { dbPath: `${appDataDir()}/vectors.sqlite` },
|
|
@@ -144,7 +164,6 @@ const store = await createMemoryStore({
|
|
|
144
164
|
|
|
145
165
|
```ts
|
|
146
166
|
const store = await createMemoryStore({
|
|
147
|
-
env: { isTauriMode: () => false },
|
|
148
167
|
vector: {
|
|
149
168
|
backend: "chroma",
|
|
150
169
|
chroma: {
|
|
@@ -167,7 +186,7 @@ the fallback — same semantics as the web app.
|
|
|
167
186
|
You don't need to wire all of them; the ones you omit just emit a warning:
|
|
168
187
|
|
|
169
188
|
```ts
|
|
170
|
-
import { createUnifiedSearch } from "memory-store/unified-search";
|
|
189
|
+
import { createUnifiedSearch } from "@melandlabs/memory-store/unified-search";
|
|
171
190
|
|
|
172
191
|
const search = createUnifiedSearch({
|
|
173
192
|
embedQuery: async ({ userId, query, authToken }) =>
|
|
@@ -209,36 +228,160 @@ const result = await search.searchUnifiedMemory({
|
|
|
209
228
|
// e.g. { source: "memory", code: "raw_message_storage_unavailable", ... }
|
|
210
229
|
```
|
|
211
230
|
|
|
212
|
-
### 5.
|
|
231
|
+
### 5. FactType filter
|
|
232
|
+
|
|
233
|
+
Atomic facts are classified as `world` (facts about the world), `experience`
|
|
234
|
+
(first-person events), or `mental_model` (generalised patterns). The
|
|
235
|
+
`FactType` union lives in `@melandlabs/ai/memory/contracts`; the
|
|
236
|
+
`rawMessageToMemoryRecord` adapter (in both `indexeddb` and `memory-store`)
|
|
237
|
+
carries it through.
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
// Write side — set factType on each RawMessage.
|
|
241
|
+
await manager.storeMessages([
|
|
242
|
+
{
|
|
243
|
+
messageId: "f-1",
|
|
244
|
+
userId: "u-42",
|
|
245
|
+
content: "water boils at 100°C at sea level",
|
|
246
|
+
platform: "tutorial",
|
|
247
|
+
botId: "tutorial-bot",
|
|
248
|
+
timestamp: Date.now(),
|
|
249
|
+
factType: "world",
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
messageId: "f-2",
|
|
253
|
+
userId: "u-42",
|
|
254
|
+
content: "I went hiking last weekend",
|
|
255
|
+
platform: "tutorial",
|
|
256
|
+
botId: "tutorial-bot",
|
|
257
|
+
timestamp: Date.now(),
|
|
258
|
+
factType: "experience",
|
|
259
|
+
},
|
|
260
|
+
]);
|
|
261
|
+
|
|
262
|
+
// Read side — filter by factType.
|
|
263
|
+
const hits = await store.search({
|
|
264
|
+
userId: "u-42",
|
|
265
|
+
query: "what did I do recently?",
|
|
266
|
+
factTypes: ["experience"],
|
|
267
|
+
limit: 5,
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Schema migration: IndexedDB `DB_VERSION` 3 → 4 (additive `factType` index on
|
|
272
|
+
`raw_messages`), SQLite `RAW_MESSAGES_SCHEMA_VERSION` 3 → 4 (additive
|
|
273
|
+
`fact_type` column + partial index). Both migrations are idempotent and
|
|
274
|
+
tolerate v3 rows whose `factType` is undefined.
|
|
275
|
+
|
|
276
|
+
### 6. Read-only `search({ synthesize: true })` — LLM synthesis
|
|
277
|
+
|
|
278
|
+
`store.search({ ...input, synthesize: true })` is the read-only sibling of
|
|
279
|
+
the write-back loop. It fans out across raw messages, summaries,
|
|
280
|
+
insights, and knowledge chunks, then asks the LLM to produce a single
|
|
281
|
+
synthesised answer. No writes.
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
const out = await store.search({
|
|
285
|
+
userId: "u-42",
|
|
286
|
+
query: "what does the user like to do on weekends?",
|
|
287
|
+
tiers: ["summary", "raw", "insight", "knowledge"],
|
|
288
|
+
limit: 20,
|
|
289
|
+
threshold: 0.7,
|
|
290
|
+
synthesize: true,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
console.log(out.answer); // LLM synthesis
|
|
294
|
+
console.log(out.evidence); // the bracket-cited evidence items
|
|
295
|
+
console.log(out.warnings); // structured warnings, never throws
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The LLM is wired via `unified.reasoning.complete` — the same hook used by
|
|
299
|
+
the search-rewrite and iterative-recall strategies. When no LLM is wired,
|
|
300
|
+
`reflect()` returns the gathered evidence with a
|
|
301
|
+
`reflect_llm_not_configured` warning instead of throwing.
|
|
302
|
+
|
|
303
|
+
### 7. Agentic write-back `consolidate()` — gather → plan → vet → persist
|
|
304
|
+
|
|
305
|
+
`store.consolidate()` is the agentic counterpart. It runs the same
|
|
306
|
+
evidence pipeline as `reflect()`, then:
|
|
307
|
+
|
|
308
|
+
1. Builds a `MemoryConsolidationPlan` from the evidence (rule-based; the
|
|
309
|
+
LLM is not free to invent `MemoryGraphOperation`s).
|
|
310
|
+
2. **Optionally** asks the LLM (`reasoning.complete`) to approve or veto
|
|
311
|
+
plan entries. The LLM never adds new entries — it only marks existing
|
|
312
|
+
ones as `approve` or `veto` with a reason.
|
|
313
|
+
3. Persists via `MemoryGraphStore.persistPlan` (when `graphStore` is wired)
|
|
314
|
+
and always runs `storage.deprecateRecords` for `deprecate` entries.
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
import { createMemoryStore, attachMemoryGraphStore } from "@melandlabs/memory-store";
|
|
318
|
+
|
|
319
|
+
// 1. Wire the graph store (opt-in).
|
|
320
|
+
attachMemoryGraphStore(store, {
|
|
321
|
+
storage: myIndexedDbStorage,
|
|
322
|
+
ownerScope: { userId: "u-42" },
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// 2. Inspect the plan first (dry-run).
|
|
326
|
+
const dry = await store.consolidate({
|
|
327
|
+
userId: "u-42",
|
|
328
|
+
query: "summarise the last week",
|
|
329
|
+
ownerScope: { userId: "u-42" },
|
|
330
|
+
tiers: ["raw", "summary"],
|
|
331
|
+
dryRun: true,
|
|
332
|
+
});
|
|
333
|
+
console.log(dry.plan); // MemoryConsolidationPlan
|
|
334
|
+
console.log(dry.applied); // false
|
|
335
|
+
|
|
336
|
+
// 3. Apply for real.
|
|
337
|
+
const result = await store.consolidate({
|
|
338
|
+
userId: "u-42",
|
|
339
|
+
query: "summarise the last week",
|
|
340
|
+
ownerScope: { userId: "u-42" },
|
|
341
|
+
tiers: ["raw", "summary"],
|
|
342
|
+
dryRun: false,
|
|
343
|
+
});
|
|
344
|
+
console.log(result.applied); // true
|
|
345
|
+
console.log(result.persistenceResult); // { applied, skipped, conflicts }
|
|
346
|
+
console.log(result.deprecationCounts); // [{ supersededBySummaryId, count }]
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Failure modes are typed:
|
|
350
|
+
- `reflect_apply_llm_skipped` — no LLM configured; the rule-based plan runs.
|
|
351
|
+
- `reflect_apply_llm_vet_failed` — LLM threw; approve-all fallback.
|
|
352
|
+
- `reflect_apply_graph_store_not_configured` — `deprecateRecords` still runs.
|
|
353
|
+
- `reflect_apply_dry_run` — `dryRun: true`; nothing was written.
|
|
354
|
+
- `reflect_apply_no_writes` — plan contains no actionable entries.
|
|
355
|
+
|
|
356
|
+
### 8. Postgres manager factory (lazy registration)
|
|
213
357
|
|
|
214
358
|
If the host application owns the postgres raw-message manager (e.g. an
|
|
215
359
|
existing Drizzle-based repo), register it via the factory pattern. The
|
|
216
360
|
memory-store package will resolve it on first use:
|
|
217
361
|
|
|
218
362
|
```ts
|
|
219
|
-
import { registerPostgresFactory } from "memory-store/postgres-raw-message-factory";
|
|
363
|
+
import { registerPostgresFactory } from "@melandlabs/memory-store/postgres-raw-message-factory";
|
|
220
364
|
import { myPostgresManager } from "./managers/postgres-raw-message";
|
|
221
365
|
|
|
222
366
|
registerPostgresFactory(async () => myPostgresManager);
|
|
223
367
|
// Later — anywhere in the codebase:
|
|
224
|
-
import { getRawMessageManager } from "memory-store";
|
|
368
|
+
import { getRawMessageManager } from "@melandlabs/memory-store";
|
|
225
369
|
const manager = await getRawMessageManager();
|
|
226
370
|
```
|
|
227
371
|
|
|
228
|
-
If you don't register a factory, the
|
|
229
|
-
|
|
230
|
-
registering the factory is mandatory.
|
|
372
|
+
If you don't register a factory, the default SQLite backend (`dbPath` or
|
|
373
|
+
`~/.opencontext/memory/store.db`) is used. For server-side hosts that
|
|
374
|
+
want Postgres, registering the factory is mandatory.
|
|
231
375
|
|
|
232
|
-
###
|
|
376
|
+
### 9. HTTP daemon
|
|
233
377
|
|
|
234
378
|
```ts
|
|
235
|
-
import { startHttpServer } from "memory-store/http";
|
|
379
|
+
import { startHttpServer } from "@melandlabs/memory-store/http";
|
|
236
380
|
|
|
237
381
|
const { url, port, stop } = await startHttpServer({
|
|
238
382
|
port: 7421,
|
|
239
383
|
host: "127.0.0.1",
|
|
240
384
|
// MemoryStoreConfig passthrough:
|
|
241
|
-
env: { isTauriMode: () => false },
|
|
242
385
|
vector: { backend: "chroma", chroma: { url: process.env.CHROMA_URL! } },
|
|
243
386
|
unified: { embedQuery: myEmbedder },
|
|
244
387
|
});
|
|
@@ -255,12 +398,13 @@ MEMORY_HTTP_HOST=0.0.0.0 MEMORY_HTTP_PORT=7421 opencontext-memory-http
|
|
|
255
398
|
|
|
256
399
|
Endpoints:
|
|
257
400
|
|
|
258
|
-
| Method + path | Body
|
|
259
|
-
| -------------------------------------- |
|
|
260
|
-
| `GET /health` | —
|
|
261
|
-
| `POST /v1/search` | `{ userId, query, limit?, threshold?, sources?, botIds?, documentIds? }`
|
|
262
|
-
| `POST /v1/
|
|
263
|
-
| `
|
|
401
|
+
| Method + path | Body |
|
|
402
|
+
| -------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
403
|
+
| `GET /health` | — |
|
|
404
|
+
| `POST /v1/search` | `{ userId, query, limit?, threshold?, sources?, botIds?, documentIds?, factTypes?, synthesize? }` |
|
|
405
|
+
| `POST /v1/consolidate:apply` | `{ userId, query, ownerScope, tiers?, limit?, threshold?, dryRun?, expectedVersion?, llmPlanReview? }` |
|
|
406
|
+
| `POST /v1/raw-messages` | `{ userId, messages: RawMessage[] }` |
|
|
407
|
+
| `GET /v1/raw-messages/:id?userId=...` | — |
|
|
264
408
|
|
|
265
409
|
For container / LAN deployment, put it behind a reverse proxy:
|
|
266
410
|
|
|
@@ -272,7 +416,7 @@ location /memory/ {
|
|
|
272
416
|
}
|
|
273
417
|
```
|
|
274
418
|
|
|
275
|
-
###
|
|
419
|
+
### 10. MCP daemon
|
|
276
420
|
|
|
277
421
|
```bash
|
|
278
422
|
opencontext-memory-mcp
|
|
@@ -280,12 +424,13 @@ opencontext-memory-mcp
|
|
|
280
424
|
|
|
281
425
|
Tools exposed over stdio:
|
|
282
426
|
|
|
283
|
-
| Tool | Required args
|
|
284
|
-
| ------------------------ |
|
|
285
|
-
| `memory.health` | —
|
|
286
|
-
| `memory.
|
|
287
|
-
| `memory.writeRawMessage` | `userId`, `message: { role, content, platform?, botId?, ... }`
|
|
288
|
-
| `memory.getRawMessage` | `userId`, `messageId`
|
|
427
|
+
| Tool | Required args |
|
|
428
|
+
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
429
|
+
| `memory.health` | — |
|
|
430
|
+
| `memory.search` | `userId`, `query`, optional `limit`, `threshold`, `sources`, `botIds`, `documentIds`, `factTypes`, `synthesize`, `tiers` |
|
|
431
|
+
| `memory.writeRawMessage` | `userId`, `message: { role, content, platform?, botId?, factType?, peer?, ... }` |
|
|
432
|
+
| `memory.getRawMessage` | `userId`, `messageId` |
|
|
433
|
+
| `memory.consolidate` | `userId`, `query`, `ownerScope`, optional `tiers`, `dryRun`, `expectedVersion`, `llmPlanReview`, `plan` |
|
|
289
434
|
|
|
290
435
|
#### Claude Desktop (`claude_desktop_config.json`)
|
|
291
436
|
|
|
@@ -333,24 +478,24 @@ Same shape — Cursor reads `mcpServers` from its MCP settings
|
|
|
333
478
|
}
|
|
334
479
|
```
|
|
335
480
|
|
|
336
|
-
After registering, the
|
|
481
|
+
After registering, the six `memory.*` tools become available inside the
|
|
337
482
|
editor. Tool calls appear in the chat like any other MCP tool.
|
|
338
483
|
|
|
339
484
|
## Subpath exports
|
|
340
485
|
|
|
341
|
-
| Subpath | Contents
|
|
342
|
-
| --------------------------------------------- |
|
|
343
|
-
| `memory-store` | `createMemoryStore`, top-level types
|
|
344
|
-
| `memory-store/http` | `startHttpServer`, `StartedHttpServer`
|
|
345
|
-
| `memory-store/mcp` | `startMcpServer`
|
|
346
|
-
| `memory-store/unified-search` | `createUnifiedSearch(deps)` factory + result types
|
|
347
|
-
| `memory-store/raw-message-store` | `createRawMessageStore`, `getRawMessageManager`, `isRawMessageStorageAvailable`
|
|
348
|
-
| `memory-store/sqlite-raw-message-store` | SQLite-vec raw-message manager (Tauri / desktop)
|
|
349
|
-
| `memory-store/postgres-raw-message-factory` | `registerPostgresFactory`, `resolvePostgresFactory`
|
|
350
|
-
| `memory-store/sqlite-vector-index` | Direct sqlite-vec insight index helpers
|
|
351
|
-
| `memory-store/chroma-memory-index` | Direct chroma upsert / search helpers
|
|
352
|
-
| `memory-store/memory-graph-write-policy` | `resolveMemoryGraphWritePolicy`, allowlist gating
|
|
353
|
-
| `memory-store/memory-graph-correction-policy` | `resolveMemoryGraphCorrectionPolicy`
|
|
486
|
+
| Subpath | Contents |
|
|
487
|
+
| --------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
488
|
+
| `memory-store` | `createMemoryStore`, `attachMemoryGraphStore`, top-level types |
|
|
489
|
+
| `memory-store/http` | `startHttpServer`, `StartedHttpServer` |
|
|
490
|
+
| `memory-store/mcp` | `startMcpServer` |
|
|
491
|
+
| `memory-store/unified-search` | `createUnifiedSearch(deps)` factory + result types |
|
|
492
|
+
| `memory-store/raw-message-store` | `createRawMessageStore`, `getRawMessageManager`, `isRawMessageStorageAvailable` |
|
|
493
|
+
| `memory-store/sqlite-raw-message-store` | SQLite-vec raw-message manager (Tauri / desktop) |
|
|
494
|
+
| `memory-store/postgres-raw-message-factory` | `registerPostgresFactory`, `resolvePostgresFactory` |
|
|
495
|
+
| `memory-store/sqlite-vector-index` | Direct sqlite-vec insight index helpers |
|
|
496
|
+
| `memory-store/chroma-memory-index` | Direct chroma upsert / search helpers |
|
|
497
|
+
| `memory-store/memory-graph-write-policy` | `resolveMemoryGraphWritePolicy`, allowlist gating |
|
|
498
|
+
| `memory-store/memory-graph-correction-policy` | `resolveMemoryGraphCorrectionPolicy` |
|
|
354
499
|
|
|
355
500
|
## Behaviour notes
|
|
356
501
|
|
|
@@ -368,9 +513,17 @@ editor. Tool calls appear in the chat like any other MCP tool.
|
|
|
368
513
|
silent inflation. `threshold` is clamped to `[-1, 1]`.
|
|
369
514
|
- Chroma failures fall back to `unified.searchRawMessagesAnn` when both
|
|
370
515
|
are configured; otherwise the memory source returns empty.
|
|
516
|
+
- `reflect()` and `consolidate()` reuse the same evidence pipeline;
|
|
517
|
+
`reflect()` is read-only, `consolidate()` additionally persists
|
|
518
|
+
via the graph store + storage adapter.
|
|
519
|
+
- `applyReflectedConsolidationPlan` is idempotent — `persistPlan`
|
|
520
|
+
deduplicates on `operationId` and `deprecateRecords` no-ops on
|
|
521
|
+
already-deprecated rows.
|
|
371
522
|
|
|
372
523
|
## See also
|
|
373
524
|
|
|
374
525
|
- [`docs/architecture.md`](../../docs/architecture.md) — the overall data
|
|
375
526
|
model, lifecycle, and transport surfaces that the memory primitives
|
|
376
527
|
plug into.
|
|
528
|
+
- [`docs/tutorials/03-advanced-usage.md`](../../docs/tutorials/03-advanced-usage.md#reflection-and-write-back)
|
|
529
|
+
— end-to-end walkthrough of `reflect()` + `consolidate()`.
|