mnemocyte 0.1.0 → 0.1.1

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 CHANGED
@@ -1,19 +1,25 @@
1
1
  # Mnemocyte
2
2
 
3
- Persistent memory for TypeScript AI apps.
3
+ Persistent memory for TypeScript AI applications.
4
4
 
5
- > Warning
6
- >
7
- > Mnemocyte is in active early development. APIs may change significantly before v1.0.
5
+ Mnemocyte stores small, durable memories for users, agents, sessions, or
6
+ other entities. It provides hybrid retrieval, context formatting, lifecycle
7
+ operations, audit logging, and duplicate-consolidation tools without requiring
8
+ a separate vector database.
8
9
 
9
- ## Current status
10
+ > Mnemocyte is early software. APIs may change before v1.0.
10
11
 
11
- Mnemocyte currently provides an MVP API with two backends:
12
+ ## Features
12
13
 
13
- - **In-memory backend** when `databaseUrl` is omitted.
14
- - **Postgres + pgvector backend** when `databaseUrl` is provided.
14
+ - In-memory backend for tests, demos, and short-lived processes.
15
+ - Postgres + pgvector backend for persistent storage.
16
+ - Hybrid recall using vector similarity, lexical matching, recency,
17
+ confidence, access count, and importance.
18
+ - Prompt-ready context output in Markdown, plain text, or XML.
19
+ - Provider timeouts, retries, and `AbortSignal` cancellation.
20
+ - Pruning, duplicate detection, audit logs, and experimental consolidation.
15
21
 
16
- The package is ESM-only. Use `import` rather than CommonJS `require`.
22
+ Mnemocyte is ESM-only. Use `import`, not CommonJS `require`.
17
23
 
18
24
  ## Install
19
25
 
@@ -21,242 +27,218 @@ The package is ESM-only. Use `import` rather than CommonJS `require`.
21
27
  pnpm add mnemocyte
22
28
  ```
23
29
 
24
- ## Basic usage
30
+ ## Quick Start
25
31
 
26
32
  ```ts
27
33
  import { createMnemocyte } from "mnemocyte";
28
34
 
29
35
  const client = createMnemocyte({
30
- embedder: {
31
- model: "demo",
32
- dimensions: 3,
33
- async embed(texts) {
34
- return texts.map((text) => [text.length, 1, 0]);
35
- },
36
- },
36
+ embedder: {
37
+ model: "demo",
38
+ dimensions: 3,
39
+ async embed(texts) {
40
+ return texts.map((text) => [text.length, 1, 0]);
41
+ },
42
+ },
37
43
  });
38
44
 
39
45
  await client.remember({
40
- entityId: "user_123",
41
- content: "Prefers short, direct answers.",
42
- type: "preference",
46
+ entityId: "user_123",
47
+ content: "Prefers short, direct answers.",
48
+ type: "preference",
43
49
  });
44
50
 
45
51
  const memories = await client.recall({
46
- entityId: "user_123",
47
- query: "How should I respond?",
48
- limit: 5,
49
- explain: true,
52
+ entityId: "user_123",
53
+ query: "How should I respond?",
54
+ limit: 5,
55
+ explain: true,
50
56
  });
51
57
 
52
58
  await client.close();
53
59
  ```
54
60
 
55
- See also: [Provider resilience](#provider-resilience),
56
- [Pruning memories](#pruning-memories),
57
- [Finding duplicates](#finding-duplicates-experimental),
58
- [Audit log](#audit-log-experimental), and
59
- [Consolidating duplicates](#consolidating-duplicates-experimental).
61
+ When `databaseUrl` is omitted, Mnemocyte uses the in-memory backend.
60
62
 
61
- ## Postgres usage
63
+ ## Postgres
62
64
 
63
- Run the included migration against a Postgres database with pgvector enabled, then pass `databaseUrl`:
65
+ Apply the bundled migration to a Postgres database with pgvector enabled, then
66
+ pass `databaseUrl`:
64
67
 
65
68
  ```ts
66
69
  const client = createMnemocyte({
67
- databaseUrl: process.env.DATABASE_URL,
68
- embedder, // embedder.dimensions MUST be 1536 — see below
70
+ databaseUrl: process.env.DATABASE_URL,
71
+ embedder, // embedder.dimensions must be 1536 for the Postgres backend.
69
72
  });
70
73
  ```
71
74
 
72
75
  The published package includes `migrations/0000_initial.sql`.
73
76
 
74
- > **Embedding dimensionality is pinned to 1536 on the Postgres backend.**
75
- > The bundled migration creates `embedding vector(1536)`. If
76
- > `embedder.dimensions` is anything else, `createMnemocyte` throws a
77
- > `MnemocyteError` with code `"CONFIG"` *before* opening the connection
78
- > pool. The in-memory backend has no such constraint.
77
+ The current Postgres schema uses `embedding vector(1536)`. If
78
+ `embedder.dimensions` is anything else, `createMnemocyte` throws a
79
+ `MnemocyteError` with code `"CONFIG"` before opening the connection pool. The
80
+ in-memory backend does not enforce this constraint.
79
81
 
80
- ## Provider resilience
82
+ ## Provider Resilience
81
83
 
82
- Mnemocyte applies an optional timeout and retry policy to every outbound
83
- embedder call, and forwards `AbortSignal` cancellation to in-flight
84
- attempts. Defaults disable both retries and timeouts so existing setups
85
- are unaffected.
84
+ Mnemocyte can apply timeouts and retries to embedder calls, and forwards
85
+ `AbortSignal` cancellation to in-flight attempts. Retries and timeouts are
86
+ disabled by default.
86
87
 
87
88
  ```ts
88
89
  const client = createMnemocyte({
89
- embedder,
90
- provider: {
91
- timeoutMs: 5_000,
92
- retries: 2,
93
- baseDelayMs: 200,
94
- maxDelayMs: 2_000,
95
- },
90
+ embedder,
91
+ provider: {
92
+ timeoutMs: 5_000,
93
+ retries: 2,
94
+ baseDelayMs: 200,
95
+ maxDelayMs: 2_000,
96
+ },
96
97
  });
97
98
 
98
99
  const controller = new AbortController();
99
100
  setTimeout(() => controller.abort(), 1_000);
100
101
 
101
102
  await client.remember({
102
- entityId: "user_123",
103
- content: "Prefers short answers.",
104
- signal: controller.signal,
103
+ entityId: "user_123",
104
+ content: "Prefers short answers.",
105
+ signal: controller.signal,
105
106
  });
106
107
  ```
107
108
 
108
- Failures surface as `MnemocyteError` with stable `code`s:
109
+ Provider failures surface as `MnemocyteError` values with stable `code`s:
109
110
 
110
- - `"TIMEOUT"` — a single provider attempt exceeded `timeoutMs`.
111
- - `"ABORTED"` — the operation was cancelled via `signal` (never retried).
112
- - `"EMBEDDING"` — the embedder failed after all retries are exhausted.
111
+ - `"TIMEOUT"`: a provider attempt exceeded `timeoutMs`.
112
+ - `"ABORTED"`: the operation was cancelled via `signal` and is not retried.
113
+ - `"EMBEDDING"`: the embedder failed after retries were exhausted.
113
114
 
114
- ## Pruning memories
115
+ ## Pruning
115
116
 
116
- `prune` bulk-deletes memories matching a filter. At least one selector
117
- is required; `prune({})` is rejected to avoid accidental full deletion.
117
+ `prune` deletes memories matching a filter. At least one selector is required;
118
+ `prune({})` is rejected to avoid accidental full deletion.
118
119
 
119
120
  ```ts
120
- // Drop expired memories for one entity.
121
121
  await client.prune({ entityId: "user_123", expired: true });
122
122
 
123
- // Evict memories not accessed in the last 30 days, but never drop
124
- // "high" or "critical" memories.
125
123
  await client.prune({
126
- notAccessedSince: new Date(Date.now() - 30 * 24 * 3600 * 1000),
127
- maxImportance: "normal",
124
+ notAccessedSince: new Date(Date.now() - 30 * 24 * 3600 * 1000),
125
+ maxImportance: "normal",
128
126
  });
129
127
 
130
- // Count what would be deleted without touching the store.
131
128
  const preview = await client.prune({
132
- entityId: "user_123",
133
- superseded: true,
134
- dryRun: true,
129
+ entityId: "user_123",
130
+ superseded: true,
131
+ dryRun: true,
135
132
  });
136
133
  console.log(preview.matchedCount);
137
134
  ```
138
135
 
139
136
  Available selectors: `entityId`, `expired`, `superseded`, `createdBefore`,
140
- `notAccessedSince`, `types`, `tags`, `maxImportance`. They AND together.
137
+ `notAccessedSince`, `types`, `tags`, `maxImportance`. Selectors are combined
138
+ with AND semantics.
141
139
 
142
- ## Finding duplicates (experimental)
140
+ ## Duplicate Detection
143
141
 
144
- `findDuplicates` is a **read-only** scan that surfaces near-identical
145
- memories for one entity using pairwise cosine similarity. It is
146
- intentionally passive — nothing is deleted or modified — so callers can
147
- decide their own consolidation policy.
142
+ `findDuplicates` is an experimental, read-only scan that surfaces
143
+ near-identical memories for one entity using pairwise cosine similarity.
148
144
 
149
145
  ```ts
150
146
  const pairs = await client.findDuplicates({
151
- entityId: "user_123",
152
- threshold: 0.95, // default 0.95
153
- limit: 50, // default 100, ordered by similarity desc
147
+ entityId: "user_123",
148
+ threshold: 0.95,
149
+ limit: 50,
154
150
  });
155
151
 
156
152
  for (const { a, b, similarity } of pairs) {
157
- console.log(similarity.toFixed(3), a.content, "<>", b.content);
153
+ console.log(similarity.toFixed(3), a.content, "<>", b.content);
158
154
  }
159
155
  ```
160
156
 
161
- Optional selectors: `types`, `tags` (both required on each pair member),
162
- `includeSuperseded`, `includeExpired`. Superseded and expired memories
163
- are excluded by default.
157
+ Optional selectors: `types`, `tags`, `includeSuperseded`, `includeExpired`.
158
+ `types` and `tags` must match on both memories in each pair. Superseded and
159
+ expired memories are excluded by default.
164
160
 
165
- > Part of Phase 6 (consolidation tooling). The API surface may change in
166
- > follow-up releases as conflict detection and active dedup land.
161
+ ## Audit Log
167
162
 
168
- ## Audit log (experimental)
169
-
170
- When `audit.enabled` is `true`, Mnemocyte records an entry on every
171
- state-changing operation (`remember`, `forget`, `forgetAll`, `prune`).
172
- Read with `client.listAuditLog()`.
163
+ When `audit.enabled` is `true`, Mnemocyte records an entry for state-changing
164
+ operations. Read entries with `client.listAuditLog()`.
173
165
 
174
166
  ```ts
175
167
  const client = createMnemocyte({
176
- embedder,
177
- audit: { enabled: true },
168
+ embedder,
169
+ audit: { enabled: true },
178
170
  });
179
171
 
180
172
  await client.remember({ entityId: "user_123", content: "Likes tea." });
181
173
  await client.prune({ entityId: "user_123", expired: true });
182
174
 
183
175
  const log = await client.listAuditLog({
184
- entityId: "user_123",
185
- limit: 100,
176
+ entityId: "user_123",
177
+ limit: 100,
186
178
  });
179
+
187
180
  for (const event of log) {
188
- console.log(event.timestamp, event.description, event.metadata);
181
+ console.log(event.timestamp, event.description, event.metadata);
189
182
  }
190
183
  ```
191
184
 
192
185
  Recorded `description` slugs:
193
186
 
194
- - `"memory.created"` — single insert; metadata: `{ memoryId, type, importance }`
195
- - `"memory.deleted"` — single `forget`; metadata: `{ memoryId }`
196
- - `"entity.cleared"` — `forgetAll`; metadata: `{ count }`
197
- - `"memory.pruned"` — real (non-dryRun) `prune` with an `entityId` selector; metadata: `{ count }`
198
-
199
- Audit entries are **sticky**: `forgetAll` no longer erases prior log
200
- entries — wiping an entity is itself a recorded `"entity.cleared"`
201
- event. Disable audit by leaving `audit.enabled` unset (the default);
202
- historical entries remain readable.
187
+ - `"memory.created"`: single insert.
188
+ - `"memory.deleted"`: single `forget`.
189
+ - `"entity.cleared"`: `forgetAll`.
190
+ - `"memory.pruned"`: non-dry-run `prune` with an `entityId` selector.
191
+ - `"memory.superseded"`: experimental consolidation.
203
192
 
204
- > Part of Phase 6 (consolidation tooling). The API surface may change
205
- > as conflict detection and consolidation land.
193
+ Audit entries are sticky: `forgetAll` does not erase prior log entries. Disable
194
+ audit by leaving `audit.enabled` unset.
206
195
 
207
- ## Consolidating duplicates (experimental)
196
+ ## Consolidation
208
197
 
209
- `client.experimental.consolidate()` merges likely-duplicate memories
210
- into a single survivor. Each loser is marked `supersededBy = survivor.id`
211
- and excluded from `recall` by default. Tags are unioned onto the
212
- survivor unless `mergeTags: false`. Idempotent — already-superseded
213
- memories are skipped.
214
-
215
- Pair it with `findDuplicates` to build a complete dedup pipeline:
198
+ `client.experimental.consolidate()` marks likely-duplicate memories as
199
+ superseded by a survivor. Superseded memories are excluded from `recall` by
200
+ default. Tags are unioned onto the survivor unless `mergeTags: false`.
216
201
 
217
202
  ```ts
218
203
  const pairs = await client.findDuplicates({
219
- entityId: "user_123",
220
- threshold: 0.97,
204
+ entityId: "user_123",
205
+ threshold: 0.97,
221
206
  });
222
207
 
223
208
  for (const { a, b } of pairs) {
224
- await client.experimental.consolidate({
225
- entityId: "user_123",
226
- survivorId: a.id,
227
- supersededIds: [b.id],
228
- });
209
+ await client.experimental.consolidate({
210
+ entityId: "user_123",
211
+ survivorId: a.id,
212
+ supersededIds: [b.id],
213
+ });
229
214
  }
230
215
  ```
231
216
 
232
- When `audit.enabled` is `true`, each newly superseded memory writes a
233
- `"memory.superseded"` audit event with metadata `{ memoryId, supersededBy }`.
234
-
235
- > The `experimental` namespace is intentionally unstable. Members may
236
- > change or move to the main client surface in future releases.
217
+ The `experimental` namespace is intentionally unstable. Members may change or
218
+ move before v1.0.
237
219
 
238
- ## Retrieval tuning
220
+ ## Retrieval Tuning
239
221
 
240
222
  ```ts
241
223
  const client = createMnemocyte({
242
- embedder,
243
- retrieval: {
244
- weights: {
245
- vector: 0.55,
246
- lexical: 0.2,
247
- recency: 0.1,
248
- confidence: 0.05,
249
- access: 0.05,
250
- importance: 0.05,
251
- },
252
- recencyHalfLifeDays: 90,
253
- accessSaturation: 10,
254
- candidateMultiplier: 3,
255
- },
224
+ embedder,
225
+ retrieval: {
226
+ weights: {
227
+ vector: 0.55,
228
+ lexical: 0.2,
229
+ recency: 0.1,
230
+ confidence: 0.05,
231
+ access: 0.05,
232
+ importance: 0.05,
233
+ },
234
+ recencyHalfLifeDays: 90,
235
+ accessSaturation: 10,
236
+ candidateMultiplier: 3,
237
+ },
256
238
  });
257
239
  ```
258
240
 
259
- ## Development checks
241
+ ## Development
260
242
 
261
243
  ```bash
262
244
  pnpm checktypes
@@ -270,4 +252,5 @@ pnpm run pack:check
270
252
 
271
253
  ## Architecture
272
254
 
273
- See `ARCHITECTURE.md` for the canonical architecture, roadmap, and production plan.
255
+ See [ARCHITECTURE.md](./ARCHITECTURE.md) for implementation details and
256
+ [ROADMAP.md](./ROADMAP.md) for planned work.
package/dist/index.mjs CHANGED
@@ -24,12 +24,16 @@ const vector = customType({
24
24
  return `vector(${typeof config === "number" ? config : 1536})`;
25
25
  },
26
26
  toDriver(value) {
27
- return `[${value.join(",")}]`;
27
+ return `[${value.map(formatVectorComponent$1).join(",")}]`;
28
28
  },
29
29
  fromDriver(value) {
30
30
  return value.slice(1, -1).split(",").filter(Boolean).map(Number);
31
31
  }
32
32
  });
33
+ function formatVectorComponent$1(value) {
34
+ if (!Number.isFinite(value)) throw new Error("Vector values must be finite numbers.");
35
+ return Object.is(value, -0) ? "0" : value.toFixed(17);
36
+ }
33
37
  const memoriesTable = pgTable("mnemocyte_memories", {
34
38
  id: text("id").primaryKey(),
35
39
  entityId: text("entity_id").notNull(),
@@ -43,7 +47,7 @@ const memoriesTable = pgTable("mnemocyte_memories", {
43
47
  embedding: vector("embedding", { dimensions: 1536 }),
44
48
  embeddingModel: text("embedding_model").notNull(),
45
49
  embeddingDimensions: integer("embedding_dimensions").notNull(),
46
- supersededBy: text("superseded_by"),
50
+ supersededBy: text("superseded_by").references(() => memoriesTable.id),
47
51
  supersededAt: timestamp("superseded_at", { withTimezone: true }),
48
52
  expiresAt: timestamp("expires_at", { withTimezone: true }),
49
53
  lastAccessedAt: timestamp("last_accessed_at", { withTimezone: true }),
@@ -138,7 +142,11 @@ function formatMetadata(memory) {
138
142
  if (memory.tags.length > 0) parts.push(`tags=${memory.tags.join(",")}`);
139
143
  return parts.join("; ");
140
144
  }
141
- function formatMarkdown(memories, query) {
145
+ function markdownFence(value) {
146
+ const longestBacktickRun = Math.max(0, ...Array.from(value.matchAll(/`+/g), (match) => match[0].length));
147
+ return "`".repeat(Math.max(3, longestBacktickRun + 1));
148
+ }
149
+ function formatMarkdown(memories, query, omittedCount) {
142
150
  const lines = [
143
151
  "# Memory Context",
144
152
  "",
@@ -146,10 +154,14 @@ function formatMarkdown(memories, query) {
146
154
  "",
147
155
  "## Relevant Memories"
148
156
  ];
149
- for (const memory of memories) lines.push("", `- ${memory.content}`, ` - ${formatMetadata(memory)}`);
157
+ for (const memory of memories) {
158
+ const fence = markdownFence(memory.content);
159
+ lines.push("", `- ${formatMetadata(memory)}`, ` ${fence}text`, ...memory.content.split("\n").map((line) => ` ${line}`), ` ${fence}`);
160
+ }
161
+ if (omittedCount > 0) lines.push("", `[${omittedCount} memories omitted to fit token budget]`);
150
162
  return lines.join("\n");
151
163
  }
152
- function formatPlain(memories, query) {
164
+ function formatPlain(memories, query, omittedCount) {
153
165
  const lines = [
154
166
  "MEMORY CONTEXT",
155
167
  "",
@@ -157,20 +169,22 @@ function formatPlain(memories, query) {
157
169
  "",
158
170
  "RELEVANT MEMORIES"
159
171
  ];
160
- for (const memory of memories) lines.push("", memory.content, formatMetadata(memory));
172
+ for (const [index, memory] of memories.entries()) lines.push("", `--- MEMORY ${index + 1} START ---`, formatMetadata(memory), memory.content, `--- MEMORY ${index + 1} END ---`);
173
+ if (omittedCount > 0) lines.push("", `[${omittedCount} memories omitted to fit token budget]`);
161
174
  return lines.join("\n");
162
175
  }
163
- function formatXml(memories, query) {
176
+ function formatXml(memories, query, omittedCount) {
164
177
  const lines = [`<memory_context query="${escapeXml(query)}">`];
165
178
  for (const memory of memories) lines.push(` <memory id="${escapeXml(memory.id)}" type="${escapeXml(memory.type)}" importance="${escapeXml(memory.importance)}" score="${memory.score.toFixed(3)}">`, ` <content>${escapeXml(memory.content)}</content>`, ` <metadata>${escapeXml(formatMetadata(memory))}</metadata>`, " </memory>");
179
+ if (omittedCount > 0) lines.push(` <omitted count="${omittedCount}" reason="token_budget" />`);
166
180
  lines.push("</memory_context>");
167
181
  return lines.join("\n");
168
182
  }
169
- function formatContext(memories, query, format) {
183
+ function formatContext(memories, query, format, omittedCount = 0) {
170
184
  switch (format) {
171
- case "markdown": return formatMarkdown(memories, query);
172
- case "plain": return formatPlain(memories, query);
173
- case "xml": return formatXml(memories, query);
185
+ case "markdown": return formatMarkdown(memories, query, omittedCount);
186
+ case "plain": return formatPlain(memories, query, omittedCount);
187
+ case "xml": return formatXml(memories, query, omittedCount);
174
188
  }
175
189
  }
176
190
  //#endregion
@@ -199,7 +213,13 @@ async function buildContext(options) {
199
213
  const format = options.input.format ?? "markdown";
200
214
  const maxTokens = options.input.maxTokens ?? 1200;
201
215
  const tokenCounter = options.input.tokenCounter ?? heuristicTokenCounter;
202
- return trimToTokenBudget(formatContext(await options.recall(options.input), options.input.query, format), maxTokens, tokenCounter);
216
+ const memories = await options.recall(options.input);
217
+ for (let count = memories.length; count >= 0; count -= 1) {
218
+ const omittedCount = memories.length - count;
219
+ const context = formatContext(memories.slice(0, count), options.input.query, format, omittedCount);
220
+ if (tokenCounter.count(context) <= maxTokens) return context;
221
+ }
222
+ return trimToTokenBudget(formatContext([], options.input.query, format, memories.length), maxTokens, tokenCounter);
203
223
  }
204
224
  //#endregion
205
225
  //#region src/observability.ts
@@ -1009,10 +1029,14 @@ async function listEvents(db, filter) {
1009
1029
  //#endregion
1010
1030
  //#region src/db/queries/memories.ts
1011
1031
  function vectorLiteral(embedding) {
1012
- return `[${embedding.join(",")}]`;
1032
+ return `[${embedding.map(formatVectorComponent).join(",")}]`;
1033
+ }
1034
+ function formatVectorComponent(value) {
1035
+ if (!Number.isFinite(value)) throw new Error("Vector values must be finite numbers.");
1036
+ return Object.is(value, -0) ? "0" : value.toFixed(17);
1013
1037
  }
1014
1038
  function filterConditions(filter) {
1015
- return and(eq(memoriesTable.entityId, filter.entityId), filter.includeSuperseded ? void 0 : isNull(memoriesTable.supersededBy), filter.includeExpired ? void 0 : sql`(${memoriesTable.expiresAt} IS NULL OR ${memoriesTable.expiresAt} > now())`, filter.types && filter.types.length > 0 ? inArray(memoriesTable.type, [...filter.types]) : void 0, filter.tags && filter.tags.length > 0 ? sql`${memoriesTable.tags} && ${filter.tags}` : void 0, filter.before ? lt(memoriesTable.createdAt, filter.before) : void 0, filter.after ? gt(memoriesTable.createdAt, filter.after) : void 0);
1039
+ return and(eq(memoriesTable.entityId, filter.entityId), filter.includeSuperseded ? void 0 : isNull(memoriesTable.supersededBy), filter.includeExpired ? void 0 : sql`(${memoriesTable.expiresAt} IS NULL OR ${memoriesTable.expiresAt} > now())`, filter.types && filter.types.length > 0 ? inArray(memoriesTable.type, [...filter.types]) : void 0, filter.tags && filter.tags.length > 0 ? sql`${memoriesTable.tags} @> ${filter.tags}` : void 0, filter.before ? lt(memoriesTable.createdAt, filter.before) : void 0, filter.after ? gt(memoriesTable.createdAt, filter.after) : void 0);
1016
1040
  }
1017
1041
  async function insertMemory(db, row) {
1018
1042
  const inserted = (await db.insert(memoriesTable).values(row).returning())[0];
@@ -1210,7 +1234,7 @@ async function vectorSearch(db, input) {
1210
1234
  ${input.includeSuperseded ? sql`` : sql`AND superseded_by IS NULL`}
1211
1235
  ${input.includeExpired ? sql`` : sql`AND (expires_at IS NULL OR expires_at > now())`}
1212
1236
  ${input.types && input.types.length > 0 ? sql`AND type IN (${sql.join(input.types.map((type) => sql`${type}`), sql`, `)})` : sql``}
1213
- ${input.tags && input.tags.length > 0 ? sql`AND tags && ${input.tags}` : sql``}
1237
+ ${input.tags && input.tags.length > 0 ? sql`AND tags @> ${input.tags}` : sql``}
1214
1238
  ${input.before ? sql`AND created_at < ${input.before}` : sql``}
1215
1239
  ${input.after ? sql`AND created_at > ${input.after}` : sql``}
1216
1240
  AND 1 - (embedding <=> ${embedding}::vector) >= ${minScore}
@@ -1247,7 +1271,7 @@ async function lexicalSearch(db, input) {
1247
1271
  ${input.includeSuperseded ? sql`` : sql`AND superseded_by IS NULL`}
1248
1272
  ${input.includeExpired ? sql`` : sql`AND (expires_at IS NULL OR expires_at > now())`}
1249
1273
  ${input.types && input.types.length > 0 ? sql`AND type IN (${sql.join(input.types.map((type) => sql`${type}`), sql`, `)})` : sql``}
1250
- ${input.tags && input.tags.length > 0 ? sql`AND tags && ${input.tags}` : sql``}
1274
+ ${input.tags && input.tags.length > 0 ? sql`AND tags @> ${input.tags}` : sql``}
1251
1275
  ${input.before ? sql`AND created_at < ${input.before}` : sql``}
1252
1276
  ${input.after ? sql`AND created_at > ${input.after}` : sql``}
1253
1277
  AND to_tsvector('english', content) @@ websearch_to_tsquery('english', ${input.query})
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/db/schema.ts","../src/db/index.ts","../src/errors.ts","../src/context/formatter.ts","../src/context/tokens.ts","../src/context/builder.ts","../src/observability.ts","../src/resilience.ts","../src/memory/shared.ts","../src/retrieval/scorer.ts","../src/memory/in-memory.ts","../src/db/queries/events.ts","../src/db/queries/memories.ts","../src/retrieval/index.ts","../src/memory/postgres.ts","../src/client.ts"],"sourcesContent":["import { sql } from \"drizzle-orm\";\nimport {\n\tcustomType,\n\tindex,\n\tinteger,\n\tjsonb,\n\tpgTable,\n\treal,\n\ttext,\n\ttimestamp,\n} from \"drizzle-orm/pg-core\";\n\nconst vector = customType<{ data: number[]; driverData: string }>({\n\tdataType(config) {\n\t\tconst dimensions = typeof config === \"number\" ? config : 1536;\n\t\treturn `vector(${dimensions})`;\n\t},\n\ttoDriver(value) {\n\t\treturn `[${value.join(\",\")}]`;\n\t},\n\tfromDriver(value) {\n\t\treturn value.slice(1, -1).split(\",\").filter(Boolean).map(Number);\n\t},\n});\n\nexport const memoriesTable = pgTable(\n\t\"mnemocyte_memories\",\n\t{\n\t\tid: text(\"id\").primaryKey(),\n\t\tentityId: text(\"entity_id\").notNull(),\n\t\tcontent: text(\"content\").notNull(),\n\t\ttype: text(\"type\").notNull().default(\"fact\"),\n\t\timportance: text(\"importance\").notNull().default(\"normal\"),\n\t\ttags: text(\"tags\").array().notNull().default(sql`'{}'::text[]`),\n\t\tsource: text(\"source\"),\n\t\tmetadata: jsonb(\"metadata\").notNull().default({}),\n\t\tconfidence: real(\"confidence\").notNull().default(1),\n\t\tembedding: vector(\"embedding\", { dimensions: 1536 }),\n\t\tembeddingModel: text(\"embedding_model\").notNull(),\n\t\tembeddingDimensions: integer(\"embedding_dimensions\").notNull(),\n\t\tsupersededBy: text(\"superseded_by\"),\n\t\tsupersededAt: timestamp(\"superseded_at\", { withTimezone: true }),\n\t\texpiresAt: timestamp(\"expires_at\", { withTimezone: true }),\n\t\tlastAccessedAt: timestamp(\"last_accessed_at\", { withTimezone: true }),\n\t\taccessCount: integer(\"access_count\").notNull().default(0),\n\t\tcreatedAt: timestamp(\"created_at\", { withTimezone: true })\n\t\t\t.notNull()\n\t\t\t.defaultNow(),\n\t\tupdatedAt: timestamp(\"updated_at\", { withTimezone: true })\n\t\t\t.notNull()\n\t\t\t.defaultNow(),\n\t},\n\t(table) => [\n\t\tindex(\"mnemocyte_memories_entity_idx\").on(table.entityId),\n\t\tindex(\"mnemocyte_memories_entity_type_idx\").on(table.entityId, table.type),\n\t],\n);\n\nexport const eventsTable = pgTable(\n\t\"mnemocyte_events\",\n\t{\n\t\tid: text(\"id\").primaryKey(),\n\t\tentityId: text(\"entity_id\").notNull(),\n\t\tdescription: text(\"description\").notNull(),\n\t\tmetadata: jsonb(\"metadata\").notNull().default({}),\n\t\ttimestamp: timestamp(\"timestamp\", { withTimezone: true })\n\t\t\t.notNull()\n\t\t\t.defaultNow(),\n\t},\n\t(table) => [\n\t\tindex(\"mnemocyte_events_entity_time_idx\").on(\n\t\t\ttable.entityId,\n\t\t\ttable.timestamp,\n\t\t),\n\t],\n);\n\nexport type MemoryRow = typeof memoriesTable.$inferSelect;\nexport type NewMemoryRow = typeof memoriesTable.$inferInsert;\nexport type EventRow = typeof eventsTable.$inferSelect;\nexport type NewEventRow = typeof eventsTable.$inferInsert;\n","import { drizzle, type PostgresJsDatabase } from \"drizzle-orm/postgres-js\";\nimport postgres from \"postgres\";\nimport * as schema from \"./schema.js\";\n\nexport type MnemocyteDatabase = PostgresJsDatabase<typeof schema>;\n\nexport interface DatabaseHandle {\n\tdb: MnemocyteDatabase;\n\tclose(): Promise<void>;\n}\n\nexport function createDatabase(databaseUrl: string): DatabaseHandle {\n\tconst client = postgres(databaseUrl, {\n\t\tmax: 10,\n\t\tidle_timeout: 20,\n\t\tconnect_timeout: 10,\n\t});\n\n\treturn {\n\t\tdb: drizzle(client, { schema }),\n\t\tasync close() {\n\t\t\tawait client.end();\n\t\t},\n\t};\n}\n","/**\n * Stable, machine-readable error code attached to every {@link MnemocyteError}.\n *\n * - `\"CONFIG\"` — invalid client configuration (e.g. missing or malformed embedder).\n * - `\"VALIDATION\"` — invalid argument passed to a client method.\n * - `\"DB\"` — Postgres or driver-level failure.\n * - `\"EMBEDDING\"` — embedder threw or returned an invalid vector.\n * - `\"NOT_FOUND\"` — referenced memory or entity does not exist.\n * - `\"MIGRATION\"` — schema/migration check failed against the target database.\n * - `\"TIMEOUT\"` — a provider call exceeded its configured timeout.\n * - `\"ABORTED\"` — the operation was cancelled via an `AbortSignal`.\n */\nexport type MnemocyteErrorCode =\n\t| \"CONFIG\"\n\t| \"VALIDATION\"\n\t| \"DB\"\n\t| \"EMBEDDING\"\n\t| \"NOT_FOUND\"\n\t| \"MIGRATION\"\n\t| \"TIMEOUT\"\n\t| \"ABORTED\";\n\n/**\n * Error type thrown by every public Mnemocyte API.\n *\n * Use the {@link MnemocyteError.code} property — not the message — to branch\n * on failure modes, or call {@link isMnemocyteError} as a type guard when\n * working with `unknown` errors.\n *\n * @example\n * ```ts\n * try {\n * await client.recall({ entityId: \"u1\", query: \"hi\" });\n * } catch (err) {\n * if (isMnemocyteError(err) && err.code === \"DB\") {\n * // handle database failure\n * }\n * throw err;\n * }\n * ```\n */\nexport class MnemocyteError extends Error {\n\t/** Stable, machine-readable failure code. See {@link MnemocyteErrorCode}. */\n\treadonly code: MnemocyteErrorCode;\n\t/** Underlying cause, if any (e.g. an original driver or embedder error). */\n\toverride readonly cause?: unknown;\n\n\t/**\n\t * @param message - Human-readable error message.\n\t * @param code - Stable failure code; see {@link MnemocyteErrorCode}.\n\t * @param cause - Optional underlying cause (driver error, network error, etc.).\n\t */\n\tconstructor(message: string, code: MnemocyteErrorCode, cause?: unknown) {\n\t\tsuper(message);\n\t\tthis.name = \"MnemocyteError\";\n\t\tthis.code = code;\n\t\tthis.cause = cause;\n\t}\n}\n\n/**\n * Type guard for {@link MnemocyteError}.\n *\n * Prefer this over `instanceof` when working across module boundaries or\n * bundlers where multiple copies of the class may exist.\n *\n * @param error - Value to test (typically a caught `unknown`).\n * @returns `true` if `error` is a {@link MnemocyteError}.\n */\nexport function isMnemocyteError(error: unknown): error is MnemocyteError {\n\treturn error instanceof MnemocyteError;\n}\n","import type { ContextFormat, MemoryWithScore } from \"../types.js\";\n\nfunction escapeXml(value: string): string {\n\treturn value\n\t\t.replaceAll(\"&\", \"&amp;\")\n\t\t.replaceAll(\"<\", \"&lt;\")\n\t\t.replaceAll(\">\", \"&gt;\")\n\t\t.replaceAll('\"', \"&quot;\")\n\t\t.replaceAll(\"'\", \"&apos;\");\n}\n\nfunction formatMetadata(memory: MemoryWithScore): string {\n\tconst parts = [\n\t\t`type=${memory.type}`,\n\t\t`importance=${memory.importance}`,\n\t\t`score=${memory.score.toFixed(3)}`,\n\t];\n\tif (memory.source) {\n\t\tparts.push(`source=${memory.source}`);\n\t}\n\tif (memory.tags.length > 0) {\n\t\tparts.push(`tags=${memory.tags.join(\",\")}`);\n\t}\n\treturn parts.join(\"; \");\n}\n\nfunction formatMarkdown(\n\tmemories: readonly MemoryWithScore[],\n\tquery: string,\n): string {\n\tconst lines = [\n\t\t\"# Memory Context\",\n\t\t\"\",\n\t\t`Query: ${query}`,\n\t\t\"\",\n\t\t\"## Relevant Memories\",\n\t];\n\tfor (const memory of memories) {\n\t\tlines.push(\"\", `- ${memory.content}`, ` - ${formatMetadata(memory)}`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction formatPlain(\n\tmemories: readonly MemoryWithScore[],\n\tquery: string,\n): string {\n\tconst lines = [\n\t\t\"MEMORY CONTEXT\",\n\t\t\"\",\n\t\t`QUERY: ${query}`,\n\t\t\"\",\n\t\t\"RELEVANT MEMORIES\",\n\t];\n\tfor (const memory of memories) {\n\t\tlines.push(\"\", memory.content, formatMetadata(memory));\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction formatXml(\n\tmemories: readonly MemoryWithScore[],\n\tquery: string,\n): string {\n\tconst lines = [`<memory_context query=\"${escapeXml(query)}\">`];\n\tfor (const memory of memories) {\n\t\tlines.push(\n\t\t\t` <memory id=\"${escapeXml(memory.id)}\" type=\"${escapeXml(memory.type)}\" importance=\"${escapeXml(memory.importance)}\" score=\"${memory.score.toFixed(3)}\">`,\n\t\t\t` <content>${escapeXml(memory.content)}</content>`,\n\t\t\t` <metadata>${escapeXml(formatMetadata(memory))}</metadata>`,\n\t\t\t\" </memory>\",\n\t\t);\n\t}\n\tlines.push(\"</memory_context>\");\n\treturn lines.join(\"\\n\");\n}\n\nexport function formatContext(\n\tmemories: readonly MemoryWithScore[],\n\tquery: string,\n\tformat: ContextFormat,\n): string {\n\tswitch (format) {\n\t\tcase \"markdown\":\n\t\t\treturn formatMarkdown(memories, query);\n\t\tcase \"plain\":\n\t\t\treturn formatPlain(memories, query);\n\t\tcase \"xml\":\n\t\t\treturn formatXml(memories, query);\n\t}\n}\n","import type { TokenCounter } from \"../types.js\";\n\nexport const heuristicTokenCounter: TokenCounter = {\n\tcount(text) {\n\t\treturn Math.ceil(text.length / 4);\n\t},\n};\n\nexport function trimToTokenBudget(\n\ttext: string,\n\tmaxTokens: number,\n\ttokenCounter: TokenCounter,\n): string {\n\tif (maxTokens < 1 || tokenCounter.count(text) <= maxTokens) {\n\t\treturn text;\n\t}\n\tlet low = 0;\n\tlet high = text.length;\n\tlet best = \"\";\n\twhile (low <= high) {\n\t\tconst mid = Math.floor((low + high) / 2);\n\t\tconst candidate = text.slice(0, mid).trimEnd();\n\t\tconst output = `${candidate}\\n[truncated to fit token budget]`;\n\t\tif (tokenCounter.count(output) <= maxTokens) {\n\t\t\tbest = output;\n\t\t\tlow = mid + 1;\n\t\t} else {\n\t\t\thigh = mid - 1;\n\t\t}\n\t}\n\treturn best || \"[truncated to fit token budget]\";\n}\n","import type { BuildContextInput, MemoryWithScore } from \"../types.js\";\nimport { formatContext } from \"./formatter.js\";\nimport { heuristicTokenCounter, trimToTokenBudget } from \"./tokens.js\";\n\nexport interface BuildContextOptions {\n\tinput: BuildContextInput;\n\trecall(input: BuildContextInput): Promise<MemoryWithScore[]>;\n}\n\nexport async function buildContext(\n\toptions: BuildContextOptions,\n): Promise<string> {\n\tconst format = options.input.format ?? \"markdown\";\n\tconst maxTokens = options.input.maxTokens ?? 1200;\n\tconst tokenCounter = options.input.tokenCounter ?? heuristicTokenCounter;\n\tconst memories = await options.recall(options.input);\n\tconst context = formatContext(memories, options.input.query, format);\n\treturn trimToTokenBudget(context, maxTokens, tokenCounter);\n}\n","import type {\n\tMnemocyteBackend,\n\tMnemocyteConfig,\n\tMnemocyteObservation,\n\tMnemocyteOperation,\n} from \"./types.js\";\n\ninterface ObservationMetadata {\n\tentityId?: string;\n\tmemoryId?: string;\n\tcount?: number;\n}\n\nfunction withMetadata(\n\tevent: MnemocyteObservation,\n\tmetadata: ObservationMetadata,\n): MnemocyteObservation {\n\treturn {\n\t\t...event,\n\t\t...(metadata.entityId === undefined ? {} : { entityId: metadata.entityId }),\n\t\t...(metadata.memoryId === undefined ? {} : { memoryId: metadata.memoryId }),\n\t\t...(metadata.count === undefined ? {} : { count: metadata.count }),\n\t};\n}\n\nasync function emitObservation(\n\tconfig: MnemocyteConfig,\n\tevent: MnemocyteObservation,\n): Promise<void> {\n\ttry {\n\t\tawait config.observability?.onEvent?.(event);\n\t} catch {\n\t\treturn;\n\t}\n}\n\nexport async function observe<T>(\n\tconfig: MnemocyteConfig,\n\tbackend: MnemocyteBackend,\n\toperation: MnemocyteOperation,\n\tmetadata: ObservationMetadata,\n\taction: () => Promise<T>,\n\tsuccessMetadata?: (result: T) => ObservationMetadata,\n): Promise<T> {\n\tconst startedAt = Date.now();\n\tawait emitObservation(\n\t\tconfig,\n\t\twithMetadata(\n\t\t\t{\n\t\t\t\toperation,\n\t\t\t\tphase: \"start\",\n\t\t\t\tbackend,\n\t\t\t\ttimestamp: new Date(startedAt),\n\t\t\t},\n\t\t\tmetadata,\n\t\t),\n\t);\n\ttry {\n\t\tconst result = await action();\n\t\tawait emitObservation(\n\t\t\tconfig,\n\t\t\twithMetadata(\n\t\t\t\t{\n\t\t\t\t\toperation,\n\t\t\t\t\tphase: \"success\",\n\t\t\t\t\tbackend,\n\t\t\t\t\ttimestamp: new Date(),\n\t\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t\t},\n\t\t\t\t{ ...metadata, ...successMetadata?.(result) },\n\t\t\t),\n\t\t);\n\t\treturn result;\n\t} catch (error) {\n\t\tawait emitObservation(\n\t\t\tconfig,\n\t\t\twithMetadata(\n\t\t\t\t{\n\t\t\t\t\toperation,\n\t\t\t\t\tphase: \"error\",\n\t\t\t\t\tbackend,\n\t\t\t\t\ttimestamp: new Date(),\n\t\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t\t\terror,\n\t\t\t\t},\n\t\t\t\tmetadata,\n\t\t\t),\n\t\t);\n\t\tthrow error;\n\t}\n}\n","import { MnemocyteError } from \"./errors.js\";\nimport type { ProviderResilienceConfig } from \"./types.js\";\n\n/**\n * Default per-provider-call timeout. Disabled by default so that callers\n * who do not configure {@link ProviderResilienceConfig.timeoutMs} are\n * unaffected.\n */\nconst DEFAULT_TIMEOUT_MS = 0;\n/** Default number of retry attempts on transient provider failures. */\nconst DEFAULT_RETRIES = 0;\n/** Default base backoff delay used between retry attempts. */\nconst DEFAULT_BASE_DELAY_MS = 100;\n/** Default ceiling for retry backoff delay. */\nconst DEFAULT_MAX_DELAY_MS = 2000;\n\n/**\n * Internal helper: returns the AbortSignal as a typed value if available,\n * otherwise `undefined`. Used so call sites can stay narrow.\n */\nexport function getSignal(\n\tsource: { signal?: AbortSignal } | undefined,\n): AbortSignal | undefined {\n\treturn source?.signal;\n}\n\n/**\n * Throw a {@link MnemocyteError} with code `\"ABORTED\"` if `signal` is\n * already aborted. Safe to call with `undefined`.\n */\nexport function throwIfAborted(signal: AbortSignal | undefined): void {\n\tif (signal?.aborted) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"Operation was aborted.\",\n\t\t\t\"ABORTED\",\n\t\t\tsignal.reason,\n\t\t);\n\t}\n}\n\n/**\n * Heuristic default for whether an error should be retried.\n *\n * Conservative by design: only retries on common transient failure\n * indicators (network errors, 5xx-ish messages, `ECONN*` etc.). Never\n * retries on validation, configuration, or {@link MnemocyteError} of\n * code `\"VALIDATION\"` / `\"CONFIG\"` / `\"ABORTED\"`.\n */\nexport function defaultShouldRetry(error: unknown): boolean {\n\tif (error instanceof MnemocyteError) {\n\t\tif (\n\t\t\terror.code === \"VALIDATION\" ||\n\t\t\terror.code === \"CONFIG\" ||\n\t\t\terror.code === \"ABORTED\"\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\tif (error instanceof Error) {\n\t\tconst message = error.message.toLowerCase();\n\t\tif (\n\t\t\tmessage.includes(\"econn\") ||\n\t\t\tmessage.includes(\"etimedout\") ||\n\t\t\tmessage.includes(\"network\") ||\n\t\t\tmessage.includes(\"timeout\") ||\n\t\t\tmessage.includes(\"temporarily\") ||\n\t\t\tmessage.includes(\"rate limit\") ||\n\t\t\tmessage.includes(\"503\") ||\n\t\t\tmessage.includes(\"502\") ||\n\t\t\tmessage.includes(\"504\") ||\n\t\t\tmessage.includes(\"500\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Compute the backoff delay for the given retry attempt, using exponential\n * growth capped at {@link ProviderResilienceConfig.maxDelayMs}.\n *\n * `attempt` is 1-indexed: the delay before the first retry uses\n * `attempt = 1`, before the second retry `attempt = 2`, etc.\n */\nfunction computeDelayMs(\n\tattempt: number,\n\tbaseDelayMs: number,\n\tmaxDelayMs: number,\n): number {\n\tconst exponential = baseDelayMs * 2 ** (attempt - 1);\n\treturn Math.max(0, Math.min(maxDelayMs, exponential));\n}\n\n/**\n * Promise-based `setTimeout` that rejects with an `\"ABORTED\"`\n * {@link MnemocyteError} if `signal` aborts while waiting.\n */\nfunction delay(ms: number, signal: AbortSignal | undefined): Promise<void> {\n\tif (ms <= 0) {\n\t\tthrowIfAborted(signal);\n\t\treturn Promise.resolve();\n\t}\n\treturn new Promise<void>((resolve, reject) => {\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = (): void => {\n\t\t\tclearTimeout(timer);\n\t\t\treject(\n\t\t\t\tnew MnemocyteError(\"Operation was aborted.\", \"ABORTED\", signal?.reason),\n\t\t\t);\n\t\t};\n\t\tif (signal) {\n\t\t\tif (signal.aborted) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(\n\t\t\t\t\tnew MnemocyteError(\n\t\t\t\t\t\t\"Operation was aborted.\",\n\t\t\t\t\t\t\"ABORTED\",\n\t\t\t\t\t\tsignal.reason,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t});\n}\n\n/**\n * Race `promise` against the configured `timeoutMs` and the caller's\n * `signal`. Rejects with `\"TIMEOUT\"` or `\"ABORTED\"` respectively. Resolves\n * with the original promise value if it settles first.\n */\nfunction withTimeout<T>(\n\tpromise: Promise<T>,\n\ttimeoutMs: number,\n\tsignal: AbortSignal | undefined,\n): Promise<T> {\n\tif (timeoutMs <= 0 && !signal) {\n\t\treturn promise;\n\t}\n\treturn new Promise<T>((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst timer =\n\t\t\ttimeoutMs > 0\n\t\t\t\t? setTimeout(() => {\n\t\t\t\t\t\tif (settled) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\treject(\n\t\t\t\t\t\t\tnew MnemocyteError(\n\t\t\t\t\t\t\t\t`Provider call timed out after ${timeoutMs}ms.`,\n\t\t\t\t\t\t\t\t\"TIMEOUT\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}, timeoutMs)\n\t\t\t\t: undefined;\n\t\tconst onAbort = (): void => {\n\t\t\tif (settled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettled = true;\n\t\t\tif (timer) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t}\n\t\t\treject(\n\t\t\t\tnew MnemocyteError(\"Operation was aborted.\", \"ABORTED\", signal?.reason),\n\t\t\t);\n\t\t};\n\t\tif (signal) {\n\t\t\tif (signal.aborted) {\n\t\t\t\tif (timer) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t}\n\t\t\t\tsettled = true;\n\t\t\t\treject(\n\t\t\t\t\tnew MnemocyteError(\n\t\t\t\t\t\t\"Operation was aborted.\",\n\t\t\t\t\t\t\"ABORTED\",\n\t\t\t\t\t\tsignal.reason,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t\tpromise.then(\n\t\t\t(value) => {\n\t\t\t\tif (settled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsettled = true;\n\t\t\t\tif (timer) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t}\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(error) => {\n\t\t\t\tif (settled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsettled = true;\n\t\t\t\tif (timer) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t}\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\treject(error);\n\t\t\t},\n\t\t);\n\t});\n}\n\n/**\n * Options accepted by {@link withResilience}.\n */\nexport interface ResilienceCallOptions {\n\t/** External cancellation signal forwarded to each attempt. */\n\tsignal?: AbortSignal;\n\t/** Provider-level retry/timeout configuration. */\n\tresilience?: ProviderResilienceConfig;\n}\n\n/**\n * Run `action` with timeout, retry, and abort handling derived from\n * `options.resilience` and `options.signal`. Each retry attempt receives\n * a fresh `AbortSignal` linked to the caller's signal — so callers may\n * abort mid-retry and the in-flight attempt will cancel promptly if the\n * underlying provider honours signals.\n *\n * Errors from {@link MnemocyteError} with code `\"VALIDATION\"` /\n * `\"CONFIG\"` / `\"ABORTED\"` are never retried.\n */\nexport async function withResilience<T>(\n\taction: (signal: AbortSignal | undefined) => Promise<T>,\n\toptions: ResilienceCallOptions = {},\n): Promise<T> {\n\tconst config = options.resilience ?? {};\n\tconst timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst retries = Math.max(0, config.retries ?? DEFAULT_RETRIES);\n\tconst baseDelayMs = Math.max(0, config.baseDelayMs ?? DEFAULT_BASE_DELAY_MS);\n\tconst maxDelayMs = Math.max(\n\t\tbaseDelayMs,\n\t\tconfig.maxDelayMs ?? DEFAULT_MAX_DELAY_MS,\n\t);\n\tconst shouldRetry = config.shouldRetry ?? defaultShouldRetry;\n\tconst externalSignal = options.signal;\n\n\tthrowIfAborted(externalSignal);\n\n\tconst maxAttempts = retries + 1;\n\tlet lastError: unknown;\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n\t\tthrowIfAborted(externalSignal);\n\t\ttry {\n\t\t\treturn await withTimeout(\n\t\t\t\taction(externalSignal),\n\t\t\t\ttimeoutMs,\n\t\t\t\texternalSignal,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tlastError = error;\n\t\t\tif (error instanceof MnemocyteError && error.code === \"ABORTED\") {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (attempt >= maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (!shouldRetry(error, attempt)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst waitMs = computeDelayMs(attempt, baseDelayMs, maxDelayMs);\n\t\t\tawait delay(waitMs, externalSignal);\n\t\t}\n\t}\n\tthrow lastError;\n}\n","import type { MemoryRow } from \"../db/schema.js\";\nimport { MnemocyteError } from \"../errors.js\";\nimport { withResilience } from \"../resilience.js\";\nimport type {\n\tBuildContextInput,\n\tConsolidateInput,\n\tEmbedder,\n\tFindDuplicatesInput,\n\tImportanceLevel,\n\tListAuditLogInput,\n\tMemory,\n\tMemoryType,\n\tProviderResilienceConfig,\n\tPruneInput,\n\tRecallInput,\n\tRememberInput,\n} from \"../types.js\";\n\nexport const DEFAULT_LIMIT = 10;\nexport const DEFAULT_MIN_SCORE = 0;\nexport const DEFAULT_TYPE: MemoryType = \"fact\";\nexport const DEFAULT_IMPORTANCE: ImportanceLevel = \"normal\";\n\n/**\n * Ordering of {@link ImportanceLevel} from least to most important. Used\n * by `prune({ maxImportance })` to compare a memory's importance against\n * the caller-supplied ceiling.\n */\nexport const IMPORTANCE_RANK: Record<ImportanceLevel, number> = {\n\tlow: 0,\n\tnormal: 1,\n\thigh: 2,\n\tcritical: 3,\n};\n\nexport interface StoredMemory extends Memory {\n\tembedding: number[];\n}\n\nexport function assertNonEmptyString(value: string, field: string): void {\n\tif (value.trim().length === 0) {\n\t\tthrow new MnemocyteError(\n\t\t\t`${field} must be a non-empty string.`,\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n}\n\nexport function assertLimit(value: number): void {\n\tif (!Number.isInteger(value) || value < 1) {\n\t\tthrow new MnemocyteError(\"limit must be a positive integer.\", \"VALIDATION\");\n\t}\n}\n\nexport function assertMinScore(value: number): void {\n\tif (!Number.isFinite(value) || value < 0 || value > 1) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"minScore must be a number between 0 and 1.\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n}\n\nexport function assertEmbedder(embedder: Embedder): void {\n\tif (!embedder || typeof embedder.embed !== \"function\") {\n\t\tthrow new MnemocyteError(\n\t\t\t\"embedder with an embed function is required.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n\tassertNonEmptyString(embedder.model, \"embedder.model\");\n\tif (!Number.isInteger(embedder.dimensions) || embedder.dimensions < 1) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"embedder.dimensions must be a positive integer.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n}\n\nexport function normalizeTags(tags: readonly string[] | undefined): string[] {\n\tif (!tags) {\n\t\treturn [];\n\t}\n\treturn [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];\n}\n\nexport function createId(): string {\n\treturn `mem_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/** Generate a unique audit-event id (`evt_*`). */\nexport function createEventId(): string {\n\treturn `evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport function isExpired(memory: Memory, now: Date): boolean {\n\treturn (\n\t\tmemory.expiresAt !== null && memory.expiresAt.getTime() <= now.getTime()\n\t);\n}\n\nexport function cloneMemory(memory: Memory): Memory {\n\treturn {\n\t\t...memory,\n\t\ttags: [...memory.tags],\n\t\tmetadata: { ...memory.metadata },\n\t\tsupersededAt: memory.supersededAt ? new Date(memory.supersededAt) : null,\n\t\texpiresAt: memory.expiresAt ? new Date(memory.expiresAt) : null,\n\t\tlastAccessedAt: memory.lastAccessedAt\n\t\t\t? new Date(memory.lastAccessedAt)\n\t\t\t: null,\n\t\tcreatedAt: new Date(memory.createdAt),\n\t\tupdatedAt: new Date(memory.updatedAt),\n\t};\n}\n\nexport function rowToMemory(row: MemoryRow): Memory {\n\treturn {\n\t\tid: row.id,\n\t\tentityId: row.entityId,\n\t\tcontent: row.content,\n\t\ttype: row.type as MemoryType,\n\t\timportance: row.importance as ImportanceLevel,\n\t\ttags: row.tags,\n\t\tsource: row.source,\n\t\tmetadata: row.metadata as Record<string, unknown>,\n\t\tconfidence: row.confidence,\n\t\tembeddingModel: row.embeddingModel,\n\t\tembeddingDimensions: row.embeddingDimensions,\n\t\tsupersededBy: row.supersededBy,\n\t\tsupersededAt: row.supersededAt,\n\t\texpiresAt: row.expiresAt,\n\t\tlastAccessedAt: row.lastAccessedAt,\n\t\taccessCount: row.accessCount,\n\t\tcreatedAt: row.createdAt,\n\t\tupdatedAt: row.updatedAt,\n\t};\n}\n\nexport async function embedOne(\n\tembedder: Embedder,\n\ttext: string,\n\toptions: {\n\t\tsignal?: AbortSignal;\n\t\tresilience?: ProviderResilienceConfig;\n\t} = {},\n): Promise<number[]> {\n\tlet embeddings: number[][];\n\ttry {\n\t\tembeddings = await withResilience(\n\t\t\t(signal) =>\n\t\t\t\tsignal === undefined\n\t\t\t\t\t? embedder.embed([text])\n\t\t\t\t\t: embedder.embed([text], { signal }),\n\t\t\t{\n\t\t\t\t...(options.signal === undefined ? {} : { signal: options.signal }),\n\t\t\t\t...(options.resilience === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { resilience: options.resilience }),\n\t\t\t},\n\t\t);\n\t} catch (error) {\n\t\tif (\n\t\t\terror instanceof MnemocyteError &&\n\t\t\t(error.code === \"TIMEOUT\" || error.code === \"ABORTED\")\n\t\t) {\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new MnemocyteError(\"Failed to embed text.\", \"EMBEDDING\", error);\n\t}\n\tconst embedding = embeddings[0];\n\tif (!embedding) {\n\t\tthrow new MnemocyteError(\"Embedder returned no embedding.\", \"EMBEDDING\");\n\t}\n\tif (embedding.length !== embedder.dimensions) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"Embedder returned an embedding with unexpected dimensions.\",\n\t\t\t\"EMBEDDING\",\n\t\t);\n\t}\n\treturn embedding;\n}\n\nexport function validateRememberInput(input: RememberInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tassertNonEmptyString(input.content, \"content\");\n\tif (\n\t\tinput.confidence !== undefined &&\n\t\t(!Number.isFinite(input.confidence) ||\n\t\t\tinput.confidence < 0 ||\n\t\t\tinput.confidence > 1)\n\t) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"confidence must be a number between 0 and 1.\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n}\n\nexport function validateRecallInput(input: RecallInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tassertNonEmptyString(input.query, \"query\");\n\tif (input.limit !== undefined) {\n\t\tassertLimit(input.limit);\n\t}\n\tif (input.minScore !== undefined) {\n\t\tassertMinScore(input.minScore);\n\t}\n}\n\nexport function contextInputToRecallInput(\n\tinput: BuildContextInput,\n): RecallInput {\n\treturn {\n\t\tentityId: input.entityId,\n\t\tquery: input.query,\n\t\t...(input.limit === undefined ? {} : { limit: input.limit }),\n\t\t...(input.minScore === undefined ? {} : { minScore: input.minScore }),\n\t\t...(input.types === undefined ? {} : { types: input.types }),\n\t\t...(input.tags === undefined ? {} : { tags: input.tags }),\n\t\t...(input.includeSuperseded === undefined\n\t\t\t? {}\n\t\t\t: { includeSuperseded: input.includeSuperseded }),\n\t\t...(input.includeExpired === undefined\n\t\t\t? {}\n\t\t\t: { includeExpired: input.includeExpired }),\n\t};\n}\n\n/**\n * Validate a {@link PruneInput} and throw a `\"VALIDATION\"`\n * {@link MnemocyteError} when no selector is supplied. Mnemocyte\n * deliberately rejects `prune({})` to avoid surprise full-table deletes.\n */\nexport function validatePruneInput(input: PruneInput): void {\n\tif (input.entityId !== undefined) {\n\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t}\n\tconst hasSelector =\n\t\tinput.entityId !== undefined ||\n\t\tinput.expired === true ||\n\t\tinput.superseded === true ||\n\t\tinput.createdBefore !== undefined ||\n\t\tinput.notAccessedSince !== undefined ||\n\t\t(input.types !== undefined && input.types.length > 0) ||\n\t\t(input.tags !== undefined && input.tags.length > 0) ||\n\t\tinput.maxImportance !== undefined;\n\tif (!hasSelector) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"prune requires at least one selector (entityId, expired, superseded, createdBefore, notAccessedSince, types, tags, or maxImportance).\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n}\n\n/**\n * Test whether `memory` matches a {@link PruneInput}. All specified\n * selectors are AND-combined; unspecified selectors do not restrict.\n *\n * `now` is supplied by the caller so callers can share a consistent\n * timestamp across a batch.\n */\nexport function matchesPruneFilter(\n\tmemory: Memory,\n\tinput: PruneInput,\n\tnow: Date,\n): boolean {\n\tif (input.entityId !== undefined && memory.entityId !== input.entityId) {\n\t\treturn false;\n\t}\n\tif (input.expired === true && !isExpired(memory, now)) {\n\t\treturn false;\n\t}\n\tif (input.superseded === true && memory.supersededBy === null) {\n\t\treturn false;\n\t}\n\tif (\n\t\tinput.createdBefore !== undefined &&\n\t\tmemory.createdAt.getTime() >= input.createdBefore.getTime()\n\t) {\n\t\treturn false;\n\t}\n\tif (input.notAccessedSince !== undefined) {\n\t\tconst last = memory.lastAccessedAt;\n\t\tif (last !== null && last.getTime() >= input.notAccessedSince.getTime()) {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (input.types !== undefined && !input.types.includes(memory.type)) {\n\t\treturn false;\n\t}\n\tif (\n\t\tinput.tags !== undefined &&\n\t\tinput.tags.length > 0 &&\n\t\t!input.tags.every((tag) => memory.tags.includes(tag))\n\t) {\n\t\treturn false;\n\t}\n\tif (\n\t\tinput.maxImportance !== undefined &&\n\t\tIMPORTANCE_RANK[memory.importance] > IMPORTANCE_RANK[input.maxImportance]\n\t) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/** Default cosine-similarity threshold for {@link FindDuplicatesInput}. */\nexport const DEFAULT_DUPLICATE_THRESHOLD = 0.95;\n/** Default cap on the number of duplicate pairs returned. */\nexport const DEFAULT_DUPLICATE_LIMIT = 100;\n\n/**\n * Validate a {@link FindDuplicatesInput} and throw a `\"VALIDATION\"`\n * {@link MnemocyteError} for malformed `threshold` / `limit` values.\n */\nexport function validateFindDuplicatesInput(input: FindDuplicatesInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tif (input.threshold !== undefined) {\n\t\tif (\n\t\t\t!Number.isFinite(input.threshold) ||\n\t\t\tinput.threshold < 0 ||\n\t\t\tinput.threshold > 1\n\t\t) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"threshold must be a number between 0 and 1.\",\n\t\t\t\t\"VALIDATION\",\n\t\t\t);\n\t\t}\n\t}\n\tif (input.limit !== undefined) {\n\t\tassertLimit(input.limit);\n\t}\n}\n\n/**\n * Return `true` when a memory should participate in a duplicate scan,\n * given the filters on `input` and a shared `now` timestamp.\n */\nexport function matchesDuplicateFilter(\n\tmemory: Memory,\n\tinput: FindDuplicatesInput,\n\tnow: Date,\n): boolean {\n\tif (memory.entityId !== input.entityId) {\n\t\treturn false;\n\t}\n\tif (input.includeSuperseded !== true && memory.supersededBy !== null) {\n\t\treturn false;\n\t}\n\tif (input.includeExpired !== true && isExpired(memory, now)) {\n\t\treturn false;\n\t}\n\tif (input.types !== undefined && !input.types.includes(memory.type)) {\n\t\treturn false;\n\t}\n\tif (\n\t\tinput.tags !== undefined &&\n\t\tinput.tags.length > 0 &&\n\t\t!input.tags.every((tag) => memory.tags.includes(tag))\n\t) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/** Default cap on audit-log entries returned per `listAuditLog`. */\nexport const DEFAULT_AUDIT_LOG_LIMIT = 50;\n\n/**\n * Validate a {@link ConsolidateInput} and throw a `\"VALIDATION\"`\n * {@link MnemocyteError} for malformed inputs (empty `supersededIds`\n * or a `survivorId` appearing in `supersededIds`).\n */\nexport function validateConsolidateInput(input: ConsolidateInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tassertNonEmptyString(input.survivorId, \"survivorId\");\n\tif (input.supersededIds.length === 0) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"supersededIds must contain at least one memory id.\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n\tif (input.supersededIds.includes(input.survivorId)) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"survivorId must not appear in supersededIds.\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n\tfor (const id of input.supersededIds) {\n\t\tassertNonEmptyString(id, \"supersededIds[*]\");\n\t}\n}\n\n/**\n * Validate a {@link ListAuditLogInput} and throw a `\"VALIDATION\"`\n * {@link MnemocyteError} when malformed.\n */\nexport function validateListAuditLogInput(input: ListAuditLogInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tif (input.limit !== undefined) {\n\t\tassertLimit(input.limit);\n\t}\n}\n\nexport function matchesRecallFilter(\n\tmemory: Memory,\n\tinput: RecallInput,\n\tnow: Date,\n): boolean {\n\tif (memory.entityId !== input.entityId) {\n\t\treturn false;\n\t}\n\tif (!input.includeSuperseded && memory.supersededBy !== null) {\n\t\treturn false;\n\t}\n\tif (!input.includeExpired && isExpired(memory, now)) {\n\t\treturn false;\n\t}\n\tif (input.types && !input.types.includes(memory.type)) {\n\t\treturn false;\n\t}\n\tif (input.tags && !input.tags.every((tag) => memory.tags.includes(tag))) {\n\t\treturn false;\n\t}\n\tif (input.before && memory.createdAt >= input.before) {\n\t\treturn false;\n\t}\n\tif (input.after && memory.createdAt <= input.after) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n","import { cloneMemory } from \"../memory/shared.js\";\nimport type {\n\tImportanceLevel,\n\tMemory,\n\tMemoryWithScore,\n\tRecallInput,\n\tRetrievalConfig,\n\tRetrievalScoreWeights,\n} from \"../types.js\";\n\nconst IMPORTANCE_SCORES: Record<ImportanceLevel, number> = {\n\tlow: 0,\n\tnormal: 0.5,\n\thigh: 0.8,\n\tcritical: 1,\n};\n\nconst DEFAULT_WEIGHTS: Required<RetrievalScoreWeights> = {\n\tvector: 0.55,\n\tlexical: 0.2,\n\trecency: 0.1,\n\tconfidence: 0.05,\n\taccess: 0.05,\n\timportance: 0.05,\n};\n\nconst DEFAULT_RECENCY_HALF_LIFE_DAYS = 90;\nconst DEFAULT_ACCESS_SATURATION = 10;\nexport const DEFAULT_CANDIDATE_MULTIPLIER = 3;\n\nexport function cosineSimilarity(\n\ta: readonly number[],\n\tb: readonly number[],\n): number {\n\tlet dot = 0;\n\tlet aMagnitude = 0;\n\tlet bMagnitude = 0;\n\tfor (let i = 0; i < a.length; i += 1) {\n\t\tconst av = a[i] ?? 0;\n\t\tconst bv = b[i] ?? 0;\n\t\tdot += av * bv;\n\t\taMagnitude += av * av;\n\t\tbMagnitude += bv * bv;\n\t}\n\tif (aMagnitude === 0 || bMagnitude === 0) {\n\t\treturn 0;\n\t}\n\treturn dot / (Math.sqrt(aMagnitude) * Math.sqrt(bMagnitude));\n}\n\nexport function lexicalScore(content: string, query: string): number {\n\tconst terms = query.toLowerCase().split(/\\s+/).filter(Boolean);\n\tif (terms.length === 0) {\n\t\treturn 0;\n\t}\n\tconst lowerContent = content.toLowerCase();\n\tconst matches = terms.filter((term) => lowerContent.includes(term)).length;\n\treturn matches / terms.length;\n}\n\nfunction clampScore(value: number): number {\n\tif (!Number.isFinite(value)) {\n\t\treturn 0;\n\t}\n\treturn Math.max(0, Math.min(1, value));\n}\n\nfunction normalizeWeights(\n\tweights: RetrievalScoreWeights | undefined,\n): Required<RetrievalScoreWeights> {\n\tconst merged = { ...DEFAULT_WEIGHTS, ...weights };\n\tconst total =\n\t\tmerged.vector +\n\t\tmerged.lexical +\n\t\tmerged.recency +\n\t\tmerged.confidence +\n\t\tmerged.access +\n\t\tmerged.importance;\n\tif (total <= 0) {\n\t\treturn DEFAULT_WEIGHTS;\n\t}\n\treturn {\n\t\tvector: merged.vector / total,\n\t\tlexical: merged.lexical / total,\n\t\trecency: merged.recency / total,\n\t\tconfidence: merged.confidence / total,\n\t\taccess: merged.access / total,\n\t\timportance: merged.importance / total,\n\t};\n}\n\nfunction recencyScore(createdAt: Date, halfLifeDays: number): number {\n\tconst ageMs = Date.now() - createdAt.getTime();\n\tconst ageDays = Math.max(0, ageMs / 86_400_000);\n\treturn Math.exp((-Math.LN2 * ageDays) / halfLifeDays);\n}\n\nfunction accessScore(accessCount: number, saturation: number): number {\n\tif (accessCount <= 0) {\n\t\treturn 0;\n\t}\n\treturn Math.min(1, Math.log1p(accessCount) / Math.log1p(saturation));\n}\n\nexport function toScoredMemory(\n\tmemory: Memory,\n\tvector: number,\n\tlexical: number,\n\tinput: RecallInput,\n\tconfig?: RetrievalConfig,\n): MemoryWithScore {\n\tconst weights = normalizeWeights(config?.weights);\n\tconst recency = recencyScore(\n\t\tmemory.createdAt,\n\t\tconfig?.recencyHalfLifeDays ?? DEFAULT_RECENCY_HALF_LIFE_DAYS,\n\t);\n\tconst confidence = clampScore(memory.confidence);\n\tconst access = accessScore(\n\t\tmemory.accessCount,\n\t\tconfig?.accessSaturation ?? DEFAULT_ACCESS_SATURATION,\n\t);\n\tconst importance = IMPORTANCE_SCORES[memory.importance];\n\tconst score = Math.max(\n\t\t0,\n\t\tMath.min(\n\t\t\t1,\n\t\t\tclampScore(vector) * weights.vector +\n\t\t\t\tclampScore(lexical) * weights.lexical +\n\t\t\t\trecency * weights.recency +\n\t\t\t\tconfidence * weights.confidence +\n\t\t\t\taccess * weights.access +\n\t\t\t\timportance * weights.importance,\n\t\t),\n\t);\n\treturn {\n\t\t...cloneMemory(memory),\n\t\tscore,\n\t\tscores: {\n\t\t\tvector: clampScore(vector),\n\t\t\tlexical: clampScore(lexical),\n\t\t\trecency,\n\t\t\tconfidence,\n\t\t\taccess,\n\t\t\timportance,\n\t\t},\n\t\texplanation: input.explain\n\t\t\t? {\n\t\t\t\t\tvectorScore: clampScore(vector),\n\t\t\t\t\tlexicalScore: clampScore(lexical),\n\t\t\t\t\trecencyScore: recency,\n\t\t\t\t\tconfidenceScore: confidence,\n\t\t\t\t\taccessScore: access,\n\t\t\t\t\timportanceScore: importance,\n\t\t\t\t\timportanceBoost: importance * weights.importance,\n\t\t\t\t\tweights,\n\t\t\t\t\tfinalScore: score,\n\t\t\t\t}\n\t\t\t: null,\n\t};\n}\n","import { buildContext } from \"../context/builder.js\";\nimport { MnemocyteError } from \"../errors.js\";\nimport { observe } from \"../observability.js\";\nimport {\n\tcosineSimilarity,\n\tlexicalScore,\n\ttoScoredMemory,\n} from \"../retrieval/scorer.js\";\nimport type {\n\tAuditEvent,\n\tConsolidateInput,\n\tConsolidateResult,\n\tDuplicatePair,\n\tEntityStats,\n\tExperimentalMnemocyteClient,\n\tFindDuplicatesInput,\n\tGlobalStats,\n\tListAuditLogInput,\n\tMemory,\n\tMnemocyteClient,\n\tMnemocyteConfig,\n\tPruneInput,\n\tPruneResult,\n\tRememberInput,\n} from \"../types.js\";\nimport {\n\tassertLimit,\n\tassertMinScore,\n\tassertNonEmptyString,\n\tcloneMemory,\n\tcontextInputToRecallInput,\n\tcreateEventId,\n\tcreateId,\n\tDEFAULT_DUPLICATE_LIMIT,\n\tDEFAULT_DUPLICATE_THRESHOLD,\n\tDEFAULT_IMPORTANCE,\n\tDEFAULT_LIMIT,\n\tDEFAULT_MIN_SCORE,\n\tDEFAULT_TYPE,\n\tembedOne,\n\tisExpired,\n\tmatchesDuplicateFilter,\n\tmatchesPruneFilter,\n\tmatchesRecallFilter,\n\tnormalizeTags,\n\ttype StoredMemory,\n\tvalidateConsolidateInput,\n\tvalidateFindDuplicatesInput,\n\tvalidateListAuditLogInput,\n\tvalidatePruneInput,\n\tvalidateRecallInput,\n\tvalidateRememberInput,\n} from \"./shared.js\";\n\nexport function createInMemoryClient(config: MnemocyteConfig): MnemocyteClient {\n\tconst memories = new Map<string, StoredMemory>();\n\tconst auditLog: AuditEvent[] = [];\n\tlet closed = false;\n\n\tfunction assertOpen(): void {\n\t\tif (closed) {\n\t\t\tthrow new MnemocyteError(\"Mnemocyte client is closed.\", \"DB\");\n\t\t}\n\t}\n\n\tfunction recordAudit(\n\t\tentityId: string,\n\t\tdescription: string,\n\t\tmetadata: Record<string, unknown>,\n\t): void {\n\t\tif (config.audit?.enabled !== true) {\n\t\t\treturn;\n\t\t}\n\t\tauditLog.push({\n\t\t\tid: createEventId(),\n\t\t\tentityId,\n\t\t\tdescription,\n\t\t\tmetadata,\n\t\t\ttimestamp: new Date(),\n\t\t});\n\t}\n\n\tfunction cloneAuditEvent(event: AuditEvent): AuditEvent {\n\t\treturn {\n\t\t\tid: event.id,\n\t\t\tentityId: event.entityId,\n\t\t\tdescription: event.description,\n\t\t\tmetadata: { ...event.metadata },\n\t\t\ttimestamp: new Date(event.timestamp),\n\t\t};\n\t}\n\n\tasync function remember(input: RememberInput): Promise<Memory> {\n\t\treturn observe(\n\t\t\tconfig,\n\t\t\t\"in-memory\",\n\t\t\t\"remember\",\n\t\t\t{ entityId: input.entityId },\n\t\t\tasync () => {\n\t\t\t\tassertOpen();\n\t\t\t\tvalidateRememberInput(input);\n\t\t\t\tconst embedding = await embedOne(config.embedder, input.content, {\n\t\t\t\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t\t\t\t...(config.provider === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { resilience: config.provider }),\n\t\t\t\t});\n\t\t\t\tconst now = new Date();\n\t\t\t\tconst memory: StoredMemory = {\n\t\t\t\t\tid: createId(),\n\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\tcontent: input.content,\n\t\t\t\t\ttype: input.type ?? DEFAULT_TYPE,\n\t\t\t\t\timportance: input.importance ?? DEFAULT_IMPORTANCE,\n\t\t\t\t\ttags: normalizeTags(input.tags),\n\t\t\t\t\tsource: input.source ?? null,\n\t\t\t\t\tmetadata: input.metadata ?? {},\n\t\t\t\t\tconfidence: input.confidence ?? 1,\n\t\t\t\t\tembeddingModel: config.embedder.model,\n\t\t\t\t\tembeddingDimensions: config.embedder.dimensions,\n\t\t\t\t\tsupersededBy: null,\n\t\t\t\t\tsupersededAt: null,\n\t\t\t\t\texpiresAt: input.expiresAt ?? null,\n\t\t\t\t\tlastAccessedAt: null,\n\t\t\t\t\taccessCount: 0,\n\t\t\t\t\tcreatedAt: now,\n\t\t\t\t\tupdatedAt: now,\n\t\t\t\t\tembedding,\n\t\t\t\t};\n\t\t\t\tmemories.set(memory.id, memory);\n\t\t\t\trecordAudit(memory.entityId, \"memory.created\", {\n\t\t\t\t\tmemoryId: memory.id,\n\t\t\t\t\ttype: memory.type,\n\t\t\t\t\timportance: memory.importance,\n\t\t\t\t});\n\t\t\t\treturn cloneMemory(memory);\n\t\t\t},\n\t\t\t(memory) => ({ memoryId: memory.id, count: 1 }),\n\t\t);\n\t}\n\n\treturn {\n\t\tremember,\n\t\tasync rememberMany(inputs) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"rememberMany\",\n\t\t\t\t{ count: inputs.length },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tconst result: Memory[] = [];\n\t\t\t\t\tfor (const input of inputs) {\n\t\t\t\t\t\tresult.push(await remember(input));\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync recall(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"recall\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateRecallInput(input);\n\t\t\t\t\tconst limit = input.limit ?? config.defaults?.limit ?? DEFAULT_LIMIT;\n\t\t\t\t\tconst minScore =\n\t\t\t\t\t\tinput.minScore ?? config.defaults?.minScore ?? DEFAULT_MIN_SCORE;\n\t\t\t\t\tassertLimit(limit);\n\t\t\t\t\tassertMinScore(minScore);\n\t\t\t\t\tconst queryEmbedding = await embedOne(config.embedder, input.query, {\n\t\t\t\t\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t\t\t\t\t...(config.provider === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { resilience: config.provider }),\n\t\t\t\t\t});\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tconst scored = Array.from(memories.values())\n\t\t\t\t\t\t.filter((memory) => matchesRecallFilter(memory, input, now))\n\t\t\t\t\t\t.map((memory) =>\n\t\t\t\t\t\t\ttoScoredMemory(\n\t\t\t\t\t\t\t\tmemory,\n\t\t\t\t\t\t\t\tMath.max(0, cosineSimilarity(memory.embedding, queryEmbedding)),\n\t\t\t\t\t\t\t\tlexicalScore(memory.content, input.query),\n\t\t\t\t\t\t\t\tinput,\n\t\t\t\t\t\t\t\tconfig.retrieval,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.filter((memory) => memory.score >= minScore)\n\t\t\t\t\t\t.sort((a, b) => b.score - a.score)\n\t\t\t\t\t\t.slice(0, limit);\n\t\t\t\t\tfor (const memory of scored) {\n\t\t\t\t\t\tconst stored = memories.get(memory.id);\n\t\t\t\t\t\tif (stored) {\n\t\t\t\t\t\t\tstored.lastAccessedAt = now;\n\t\t\t\t\t\t\tstored.accessCount += 1;\n\t\t\t\t\t\t\tstored.updatedAt = now;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn scored;\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync buildContext(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"buildContext\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\treturn buildContext({\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\trecall: (contextInput) => {\n\t\t\t\t\t\t\tconst recallInput = contextInputToRecallInput(contextInput);\n\t\t\t\t\t\t\treturn this.recall(\n\t\t\t\t\t\t\t\tinput.signal === undefined\n\t\t\t\t\t\t\t\t\t? recallInput\n\t\t\t\t\t\t\t\t\t: { ...recallInput, signal: input.signal },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\tasync forget(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"forget\",\n\t\t\t\t{ entityId: input.entityId, memoryId: input.memoryId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t\t\t\t\tassertNonEmptyString(input.memoryId, \"memoryId\");\n\t\t\t\t\tconst memory = memories.get(input.memoryId);\n\t\t\t\t\tif (!memory || memory.entityId !== input.entityId) {\n\t\t\t\t\t\tthrow new MnemocyteError(\"Memory was not found.\", \"NOT_FOUND\");\n\t\t\t\t\t}\n\t\t\t\t\tmemories.delete(input.memoryId);\n\t\t\t\t\trecordAudit(memory.entityId, \"memory.deleted\", {\n\t\t\t\t\t\tmemoryId: memory.id,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\tasync forgetAll(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"forgetAll\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t\t\t\t\tlet deleted = 0;\n\t\t\t\t\tfor (const [id, memory] of memories) {\n\t\t\t\t\t\tif (memory.entityId === input.entityId) {\n\t\t\t\t\t\t\tmemories.delete(id);\n\t\t\t\t\t\t\tdeleted += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\trecordAudit(input.entityId, \"entity.cleared\", { count: deleted });\n\t\t\t\t\treturn deleted;\n\t\t\t\t},\n\t\t\t\t(count) => ({ count }),\n\t\t\t).then(() => undefined);\n\t\t},\n\t\tasync prune(input: PruneInput): Promise<PruneResult> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"prune\",\n\t\t\t\tinput.entityId === undefined ? {} : { entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidatePruneInput(input);\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tconst matched: string[] = [];\n\t\t\t\t\tfor (const memory of memories.values()) {\n\t\t\t\t\t\tif (matchesPruneFilter(memory, input, now)) {\n\t\t\t\t\t\t\tmatched.push(memory.id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst dryRun = input.dryRun === true;\n\t\t\t\t\tif (!dryRun) {\n\t\t\t\t\t\tfor (const id of matched) {\n\t\t\t\t\t\t\tmemories.delete(id);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (matched.length > 0 && input.entityId !== undefined) {\n\t\t\t\t\t\t\trecordAudit(input.entityId, \"memory.pruned\", {\n\t\t\t\t\t\t\t\tcount: matched.length,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tmatchedCount: matched.length,\n\t\t\t\t\t\tdeletedCount: dryRun ? 0 : matched.length,\n\t\t\t\t\t\tdryRun,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.deletedCount }),\n\t\t\t);\n\t\t},\n\t\tasync findDuplicates(input: FindDuplicatesInput): Promise<DuplicatePair[]> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"findDuplicates\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateFindDuplicatesInput(input);\n\t\t\t\t\tconst threshold = input.threshold ?? DEFAULT_DUPLICATE_THRESHOLD;\n\t\t\t\t\tconst limit = input.limit ?? DEFAULT_DUPLICATE_LIMIT;\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tconst candidates = Array.from(memories.values()).filter((memory) =>\n\t\t\t\t\t\tmatchesDuplicateFilter(memory, input, now),\n\t\t\t\t\t);\n\t\t\t\t\tconst pairs: DuplicatePair[] = [];\n\t\t\t\t\tfor (let i = 0; i < candidates.length; i += 1) {\n\t\t\t\t\t\tconst a = candidates[i];\n\t\t\t\t\t\tif (a === undefined) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (let j = i + 1; j < candidates.length; j += 1) {\n\t\t\t\t\t\t\tconst b = candidates[j];\n\t\t\t\t\t\t\tif (b === undefined) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst similarity = Math.max(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tMath.min(1, cosineSimilarity(a.embedding, b.embedding)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (similarity >= threshold) {\n\t\t\t\t\t\t\t\tpairs.push({\n\t\t\t\t\t\t\t\t\ta: cloneMemory(a),\n\t\t\t\t\t\t\t\t\tb: cloneMemory(b),\n\t\t\t\t\t\t\t\t\tsimilarity,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpairs.sort((x, y) => y.similarity - x.similarity);\n\t\t\t\t\treturn pairs.slice(0, limit);\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync listAuditLog(input: ListAuditLogInput): Promise<AuditEvent[]> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"listAuditLog\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateListAuditLogInput(input);\n\t\t\t\t\tconst limit = input.limit ?? 50;\n\t\t\t\t\t// Tag with the insertion index so events sharing a millisecond\n\t\t\t\t\t// timestamp still sort in causal (insertion) order.\n\t\t\t\t\tconst indexed = auditLog.map((event, idx) => ({ event, idx }));\n\t\t\t\t\tconst filtered = indexed\n\t\t\t\t\t\t.filter(({ event }) => {\n\t\t\t\t\t\t\tif (event.entityId !== input.entityId) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tinput.before !== undefined &&\n\t\t\t\t\t\t\t\tevent.timestamp.getTime() >= input.before.getTime()\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tinput.after !== undefined &&\n\t\t\t\t\t\t\t\tevent.timestamp.getTime() <= input.after.getTime()\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.sort((a, b) => {\n\t\t\t\t\t\t\tconst dt =\n\t\t\t\t\t\t\t\tb.event.timestamp.getTime() - a.event.timestamp.getTime();\n\t\t\t\t\t\t\tif (dt !== 0) {\n\t\t\t\t\t\t\t\treturn dt;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn b.idx - a.idx;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.slice(0, limit)\n\t\t\t\t\t\t.map(({ event }) => cloneAuditEvent(event));\n\t\t\t\t\treturn filtered;\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync stats(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"stats\",\n\t\t\t\tinput?.entityId ? { entityId: input.entityId } : {},\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tconst allMemories = Array.from(memories.values());\n\t\t\t\t\tconst selected = input?.entityId\n\t\t\t\t\t\t? allMemories.filter((memory) => memory.entityId === input.entityId)\n\t\t\t\t\t\t: allMemories;\n\t\t\t\t\tconst activeMemoryCount = selected.filter(\n\t\t\t\t\t\t(memory) => !isExpired(memory, now) && memory.supersededBy === null,\n\t\t\t\t\t).length;\n\t\t\t\t\tconst expiredMemoryCount = selected.filter((memory) =>\n\t\t\t\t\t\tisExpired(memory, now),\n\t\t\t\t\t).length;\n\t\t\t\t\tconst supersededMemoryCount = selected.filter(\n\t\t\t\t\t\t(memory) => memory.supersededBy !== null,\n\t\t\t\t\t).length;\n\t\t\t\t\tif (input?.entityId) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\tmemoryCount: selected.length,\n\t\t\t\t\t\t\tactiveMemoryCount,\n\t\t\t\t\t\t\texpiredMemoryCount,\n\t\t\t\t\t\t\tsupersededMemoryCount,\n\t\t\t\t\t\t} satisfies EntityStats;\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tentityCount: new Set(allMemories.map((memory) => memory.entityId))\n\t\t\t\t\t\t\t.size,\n\t\t\t\t\t\tmemoryCount: selected.length,\n\t\t\t\t\t\tactiveMemoryCount,\n\t\t\t\t\t\texpiredMemoryCount,\n\t\t\t\t\t\tsupersededMemoryCount,\n\t\t\t\t\t} satisfies GlobalStats;\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\texperimental: createExperimental(),\n\t\tasync close() {\n\t\t\treturn observe(config, \"in-memory\", \"close\", {}, async () => {\n\t\t\t\tclosed = true;\n\t\t\t\tmemories.clear();\n\t\t\t});\n\t\t},\n\t};\n\n\tfunction createExperimental(): ExperimentalMnemocyteClient {\n\t\treturn {\n\t\t\tasync consolidate(input: ConsolidateInput): Promise<ConsolidateResult> {\n\t\t\t\treturn observe(\n\t\t\t\t\tconfig,\n\t\t\t\t\t\"in-memory\",\n\t\t\t\t\t\"consolidate\",\n\t\t\t\t\t{ entityId: input.entityId, memoryId: input.survivorId },\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\tassertOpen();\n\t\t\t\t\t\tvalidateConsolidateInput(input);\n\t\t\t\t\t\tconst survivor = memories.get(input.survivorId);\n\t\t\t\t\t\tif (!survivor || survivor.entityId !== input.entityId) {\n\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\"Survivor memory was not found.\",\n\t\t\t\t\t\t\t\t\"NOT_FOUND\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (survivor.supersededBy !== null) {\n\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\"Survivor memory is itself superseded.\",\n\t\t\t\t\t\t\t\t\"VALIDATION\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst losers: StoredMemory[] = [];\n\t\t\t\t\t\tfor (const id of input.supersededIds) {\n\t\t\t\t\t\t\tconst memory = memories.get(id);\n\t\t\t\t\t\t\tif (!memory || memory.entityId !== input.entityId) {\n\t\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\t\"Superseded memory was not found.\",\n\t\t\t\t\t\t\t\t\t\"NOT_FOUND\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (memory.supersededBy !== null) {\n\t\t\t\t\t\t\t\t// Idempotent skip: already superseded.\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlosers.push(memory);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst now = new Date();\n\t\t\t\t\t\tconst newSupersededIds: string[] = [];\n\t\t\t\t\t\tfor (const loser of losers) {\n\t\t\t\t\t\t\tloser.supersededBy = survivor.id;\n\t\t\t\t\t\t\tloser.supersededAt = now;\n\t\t\t\t\t\t\tloser.updatedAt = now;\n\t\t\t\t\t\t\tnewSupersededIds.push(loser.id);\n\t\t\t\t\t\t\trecordAudit(input.entityId, \"memory.superseded\", {\n\t\t\t\t\t\t\t\tmemoryId: loser.id,\n\t\t\t\t\t\t\t\tsupersededBy: survivor.id,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst shouldMergeTags =\n\t\t\t\t\t\t\tinput.mergeTags !== false && losers.length > 0;\n\t\t\t\t\t\tif (shouldMergeTags) {\n\t\t\t\t\t\t\tconst mergedTags = new Set(survivor.tags);\n\t\t\t\t\t\t\tfor (const loser of losers) {\n\t\t\t\t\t\t\t\tfor (const tag of loser.tags) {\n\t\t\t\t\t\t\t\t\tmergedTags.add(tag);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (mergedTags.size !== survivor.tags.length) {\n\t\t\t\t\t\t\t\tsurvivor.tags = [...mergedTags];\n\t\t\t\t\t\t\t\tsurvivor.updatedAt = now;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsurvivorId: survivor.id,\n\t\t\t\t\t\t\tsupersededCount: newSupersededIds.length,\n\t\t\t\t\t\t\tsupersededIds: newSupersededIds,\n\t\t\t\t\t\t} satisfies ConsolidateResult;\n\t\t\t\t\t},\n\t\t\t\t\t(result) => ({ count: result.supersededCount }),\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t}\n}\n","import { and, desc, eq, gt, lt } from \"drizzle-orm\";\nimport type { MnemocyteDatabase } from \"../index.js\";\nimport { type EventRow, eventsTable, type NewEventRow } from \"../schema.js\";\n\nexport interface EventFilter {\n\tentityId: string;\n\tlimit?: number;\n\tbefore?: Date;\n\tafter?: Date;\n}\n\nexport async function insertEvent(\n\tdb: MnemocyteDatabase,\n\trow: NewEventRow,\n): Promise<EventRow> {\n\tconst result = await db.insert(eventsTable).values(row).returning();\n\tconst inserted = result[0];\n\tif (!inserted) {\n\t\tthrow new Error(\"Event insert returned no rows.\");\n\t}\n\treturn inserted;\n}\n\nexport async function listEvents(\n\tdb: MnemocyteDatabase,\n\tfilter: EventFilter,\n): Promise<EventRow[]> {\n\treturn db\n\t\t.select()\n\t\t.from(eventsTable)\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(eventsTable.entityId, filter.entityId),\n\t\t\t\tfilter.before ? lt(eventsTable.timestamp, filter.before) : undefined,\n\t\t\t\tfilter.after ? gt(eventsTable.timestamp, filter.after) : undefined,\n\t\t\t),\n\t\t)\n\t\t.orderBy(desc(eventsTable.timestamp))\n\t\t.limit(filter.limit ?? 50);\n}\n\nexport async function deleteEventsForEntity(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n): Promise<number> {\n\tconst result = await db\n\t\t.delete(eventsTable)\n\t\t.where(eq(eventsTable.entityId, entityId))\n\t\t.returning({ id: eventsTable.id });\n\treturn result.length;\n}\n","import {\n\tand,\n\teq,\n\tgt,\n\tinArray,\n\tisNotNull,\n\tisNull,\n\tlt,\n\tor,\n\tsql,\n} from \"drizzle-orm\";\nimport type { ImportanceLevel, MemoryType } from \"../../types.js\";\nimport type { MnemocyteDatabase } from \"../index.js\";\nimport { type MemoryRow, memoriesTable, type NewMemoryRow } from \"../schema.js\";\n\nexport interface MemoryFilter {\n\tentityId: string;\n\ttypes?: readonly MemoryType[];\n\ttags?: readonly string[];\n\tbefore?: Date;\n\tafter?: Date;\n\tincludeSuperseded?: boolean;\n\tincludeExpired?: boolean;\n}\n\nexport interface VectorSearchInput extends MemoryFilter {\n\tembedding: readonly number[];\n\tlimit: number;\n\tminScore?: number;\n}\n\nexport interface LexicalSearchInput extends MemoryFilter {\n\tquery: string;\n\tlimit: number;\n}\n\nfunction vectorLiteral(embedding: readonly number[]): string {\n\treturn `[${embedding.join(\",\")}]`;\n}\n\nfunction filterConditions(filter: MemoryFilter) {\n\treturn and(\n\t\teq(memoriesTable.entityId, filter.entityId),\n\t\tfilter.includeSuperseded ? undefined : isNull(memoriesTable.supersededBy),\n\t\tfilter.includeExpired\n\t\t\t? undefined\n\t\t\t: sql`(${memoriesTable.expiresAt} IS NULL OR ${memoriesTable.expiresAt} > now())`,\n\t\tfilter.types && filter.types.length > 0\n\t\t\t? inArray(memoriesTable.type, [...filter.types])\n\t\t\t: undefined,\n\t\tfilter.tags && filter.tags.length > 0\n\t\t\t? sql`${memoriesTable.tags} && ${filter.tags}`\n\t\t\t: undefined,\n\t\tfilter.before ? lt(memoriesTable.createdAt, filter.before) : undefined,\n\t\tfilter.after ? gt(memoriesTable.createdAt, filter.after) : undefined,\n\t);\n}\n\nexport async function insertMemory(\n\tdb: MnemocyteDatabase,\n\trow: NewMemoryRow,\n): Promise<MemoryRow> {\n\tconst result = await db.insert(memoriesTable).values(row).returning();\n\tconst inserted = result[0];\n\tif (!inserted) {\n\t\tthrow new Error(\"Memory insert returned no rows.\");\n\t}\n\treturn inserted;\n}\n\nexport async function getMemoryById(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n\tmemoryId: string,\n): Promise<MemoryRow | null> {\n\tconst result = await db\n\t\t.select()\n\t\t.from(memoriesTable)\n\t\t.where(\n\t\t\tand(eq(memoriesTable.entityId, entityId), eq(memoriesTable.id, memoryId)),\n\t\t)\n\t\t.limit(1);\n\treturn result[0] ?? null;\n}\n\nexport async function listMemories(\n\tdb: MnemocyteDatabase,\n\tfilter: MemoryFilter,\n): Promise<MemoryRow[]> {\n\treturn db.select().from(memoriesTable).where(filterConditions(filter));\n}\n\nexport async function deleteMemory(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n\tmemoryId: string,\n): Promise<boolean> {\n\tconst result = await db\n\t\t.delete(memoriesTable)\n\t\t.where(\n\t\t\tand(eq(memoriesTable.entityId, entityId), eq(memoriesTable.id, memoryId)),\n\t\t)\n\t\t.returning({ id: memoriesTable.id });\n\treturn result.length > 0;\n}\n\nexport async function deleteMemoriesForEntity(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n): Promise<number> {\n\tconst result = await db\n\t\t.delete(memoriesTable)\n\t\t.where(eq(memoriesTable.entityId, entityId))\n\t\t.returning({ id: memoriesTable.id });\n\treturn result.length;\n}\n\nexport interface PruneFilter {\n\tentityId?: string;\n\texpired?: boolean;\n\tsuperseded?: boolean;\n\tcreatedBefore?: Date;\n\tnotAccessedSince?: Date;\n\ttypes?: readonly MemoryType[];\n\ttags?: readonly string[];\n\tmaxImportanceLevels?: readonly ImportanceLevel[];\n}\n\nfunction pruneConditions(filter: PruneFilter) {\n\treturn and(\n\t\tfilter.entityId !== undefined\n\t\t\t? eq(memoriesTable.entityId, filter.entityId)\n\t\t\t: undefined,\n\t\tfilter.expired\n\t\t\t? and(\n\t\t\t\t\tisNotNull(memoriesTable.expiresAt),\n\t\t\t\t\tsql`${memoriesTable.expiresAt} <= now()`,\n\t\t\t\t)\n\t\t\t: undefined,\n\t\tfilter.superseded ? isNotNull(memoriesTable.supersededBy) : undefined,\n\t\tfilter.createdBefore\n\t\t\t? lt(memoriesTable.createdAt, filter.createdBefore)\n\t\t\t: undefined,\n\t\tfilter.notAccessedSince\n\t\t\t? or(\n\t\t\t\t\tisNull(memoriesTable.lastAccessedAt),\n\t\t\t\t\tlt(memoriesTable.lastAccessedAt, filter.notAccessedSince),\n\t\t\t\t)\n\t\t\t: undefined,\n\t\tfilter.types && filter.types.length > 0\n\t\t\t? inArray(memoriesTable.type, [...filter.types])\n\t\t\t: undefined,\n\t\tfilter.tags && filter.tags.length > 0\n\t\t\t? sql`${memoriesTable.tags} @> ${filter.tags}`\n\t\t\t: undefined,\n\t\tfilter.maxImportanceLevels && filter.maxImportanceLevels.length > 0\n\t\t\t? inArray(memoriesTable.importance, [...filter.maxImportanceLevels])\n\t\t\t: undefined,\n\t);\n}\n\nexport async function countPruneMatches(\n\tdb: MnemocyteDatabase,\n\tfilter: PruneFilter,\n): Promise<number> {\n\tconst result = await db\n\t\t.select({ count: sql<number>`count(*)::int` })\n\t\t.from(memoriesTable)\n\t\t.where(pruneConditions(filter));\n\treturn result[0]?.count ?? 0;\n}\n\nexport async function pruneMemories(\n\tdb: MnemocyteDatabase,\n\tfilter: PruneFilter,\n): Promise<number> {\n\tconst result = await db\n\t\t.delete(memoriesTable)\n\t\t.where(pruneConditions(filter))\n\t\t.returning({ id: memoriesTable.id });\n\treturn result.length;\n}\n\nexport interface DuplicateSearchInput {\n\tentityId: string;\n\tthreshold: number;\n\tlimit: number;\n\ttypes?: readonly string[];\n\ttags?: readonly string[];\n\tincludeSuperseded?: boolean;\n\tincludeExpired?: boolean;\n}\n\nexport async function findDuplicatePairs(\n\tdb: MnemocyteDatabase,\n\tinput: DuplicateSearchInput,\n): Promise<Array<{ a: MemoryRow; b: MemoryRow; similarity: number }>> {\n\tconst rows = await db.execute(sql`\n\t\tSELECT\n\t\t\ta.id AS \"aId\",\n\t\t\ta.entity_id AS \"aEntityId\",\n\t\t\ta.content AS \"aContent\",\n\t\t\ta.type AS \"aType\",\n\t\t\ta.importance AS \"aImportance\",\n\t\t\ta.tags AS \"aTags\",\n\t\t\ta.source AS \"aSource\",\n\t\t\ta.metadata AS \"aMetadata\",\n\t\t\ta.confidence AS \"aConfidence\",\n\t\t\ta.embedding AS \"aEmbedding\",\n\t\t\ta.embedding_model AS \"aEmbeddingModel\",\n\t\t\ta.embedding_dimensions AS \"aEmbeddingDimensions\",\n\t\t\ta.superseded_by AS \"aSupersededBy\",\n\t\t\ta.superseded_at AS \"aSupersededAt\",\n\t\t\ta.expires_at AS \"aExpiresAt\",\n\t\t\ta.last_accessed_at AS \"aLastAccessedAt\",\n\t\t\ta.access_count AS \"aAccessCount\",\n\t\t\ta.created_at AS \"aCreatedAt\",\n\t\t\ta.updated_at AS \"aUpdatedAt\",\n\t\t\tb.id AS \"bId\",\n\t\t\tb.entity_id AS \"bEntityId\",\n\t\t\tb.content AS \"bContent\",\n\t\t\tb.type AS \"bType\",\n\t\t\tb.importance AS \"bImportance\",\n\t\t\tb.tags AS \"bTags\",\n\t\t\tb.source AS \"bSource\",\n\t\t\tb.metadata AS \"bMetadata\",\n\t\t\tb.confidence AS \"bConfidence\",\n\t\t\tb.embedding AS \"bEmbedding\",\n\t\t\tb.embedding_model AS \"bEmbeddingModel\",\n\t\t\tb.embedding_dimensions AS \"bEmbeddingDimensions\",\n\t\t\tb.superseded_by AS \"bSupersededBy\",\n\t\t\tb.superseded_at AS \"bSupersededAt\",\n\t\t\tb.expires_at AS \"bExpiresAt\",\n\t\t\tb.last_accessed_at AS \"bLastAccessedAt\",\n\t\t\tb.access_count AS \"bAccessCount\",\n\t\t\tb.created_at AS \"bCreatedAt\",\n\t\t\tb.updated_at AS \"bUpdatedAt\",\n\t\t\t1 - (a.embedding <=> b.embedding) AS \"similarity\"\n\t\tFROM mnemocyte_memories a\n\t\tJOIN mnemocyte_memories b\n\t\t\tON b.entity_id = a.entity_id\n\t\t\tAND a.id < b.id\n\t\t\tAND a.embedding IS NOT NULL\n\t\t\tAND b.embedding IS NOT NULL\n\t\tWHERE\n\t\t\ta.entity_id = ${input.entityId}\n\t\t\t${input.includeSuperseded ? sql`` : sql`AND a.superseded_by IS NULL AND b.superseded_by IS NULL`}\n\t\t\t${input.includeExpired ? sql`` : sql`AND (a.expires_at IS NULL OR a.expires_at > now()) AND (b.expires_at IS NULL OR b.expires_at > now())`}\n\t\t\t${\n\t\t\t\tinput.types && input.types.length > 0\n\t\t\t\t\t? sql`AND a.type IN (${sql.join(\n\t\t\t\t\t\t\tinput.types.map((type) => sql`${type}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)}) AND b.type IN (${sql.join(\n\t\t\t\t\t\t\tinput.types.map((type) => sql`${type}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)})`\n\t\t\t\t\t: sql``\n\t\t\t}\n\t\t\t${\n\t\t\t\tinput.tags && input.tags.length > 0\n\t\t\t\t\t? sql`AND a.tags @> ${input.tags} AND b.tags @> ${input.tags}`\n\t\t\t\t\t: sql``\n\t\t\t}\n\t\t\tAND 1 - (a.embedding <=> b.embedding) >= ${input.threshold}\n\t\tORDER BY \"similarity\" DESC\n\t\tLIMIT ${input.limit}\n\t`);\n\tconst records = rows as unknown as Array<Record<string, unknown>>;\n\treturn records.map((row) => {\n\t\tconst a = {\n\t\t\tid: row.aId,\n\t\t\tentityId: row.aEntityId,\n\t\t\tcontent: row.aContent,\n\t\t\ttype: row.aType,\n\t\t\timportance: row.aImportance,\n\t\t\ttags: row.aTags,\n\t\t\tsource: row.aSource,\n\t\t\tmetadata: row.aMetadata,\n\t\t\tconfidence: row.aConfidence,\n\t\t\tembedding: row.aEmbedding,\n\t\t\tembeddingModel: row.aEmbeddingModel,\n\t\t\tembeddingDimensions: row.aEmbeddingDimensions,\n\t\t\tsupersededBy: row.aSupersededBy,\n\t\t\tsupersededAt: row.aSupersededAt,\n\t\t\texpiresAt: row.aExpiresAt,\n\t\t\tlastAccessedAt: row.aLastAccessedAt,\n\t\t\taccessCount: row.aAccessCount,\n\t\t\tcreatedAt: row.aCreatedAt,\n\t\t\tupdatedAt: row.aUpdatedAt,\n\t\t} as unknown as MemoryRow;\n\t\tconst b = {\n\t\t\tid: row.bId,\n\t\t\tentityId: row.bEntityId,\n\t\t\tcontent: row.bContent,\n\t\t\ttype: row.bType,\n\t\t\timportance: row.bImportance,\n\t\t\ttags: row.bTags,\n\t\t\tsource: row.bSource,\n\t\t\tmetadata: row.bMetadata,\n\t\t\tconfidence: row.bConfidence,\n\t\t\tembedding: row.bEmbedding,\n\t\t\tembeddingModel: row.bEmbeddingModel,\n\t\t\tembeddingDimensions: row.bEmbeddingDimensions,\n\t\t\tsupersededBy: row.bSupersededBy,\n\t\t\tsupersededAt: row.bSupersededAt,\n\t\t\texpiresAt: row.bExpiresAt,\n\t\t\tlastAccessedAt: row.bLastAccessedAt,\n\t\t\taccessCount: row.bAccessCount,\n\t\t\tcreatedAt: row.bCreatedAt,\n\t\t\tupdatedAt: row.bUpdatedAt,\n\t\t} as unknown as MemoryRow;\n\t\treturn {\n\t\t\ta,\n\t\t\tb,\n\t\t\tsimilarity: Number(row.similarity) || 0,\n\t\t};\n\t});\n}\n\nexport interface SupersedeRow {\n\tid: string;\n\ttags: string[];\n}\n\nexport async function loadConsolidationTargets(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n\tids: readonly string[],\n): Promise<Array<{ id: string; tags: string[]; supersededBy: string | null }>> {\n\tif (ids.length === 0) {\n\t\treturn [];\n\t}\n\tconst rows = await db\n\t\t.select({\n\t\t\tid: memoriesTable.id,\n\t\t\ttags: memoriesTable.tags,\n\t\t\tsupersededBy: memoriesTable.supersededBy,\n\t\t})\n\t\t.from(memoriesTable)\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(memoriesTable.entityId, entityId),\n\t\t\t\tinArray(memoriesTable.id, [...ids]),\n\t\t\t),\n\t\t);\n\treturn rows;\n}\n\nexport async function markMemoriesSuperseded(\n\tdb: MnemocyteDatabase,\n\tparams: {\n\t\tsurvivorId: string;\n\t\tentityId: string;\n\t\tids: readonly string[];\n\t\tnow: Date;\n\t},\n): Promise<SupersedeRow[]> {\n\tif (params.ids.length === 0) {\n\t\treturn [];\n\t}\n\tconst result = await db\n\t\t.update(memoriesTable)\n\t\t.set({\n\t\t\tsupersededBy: params.survivorId,\n\t\t\tsupersededAt: params.now,\n\t\t\tupdatedAt: params.now,\n\t\t})\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(memoriesTable.entityId, params.entityId),\n\t\t\t\tinArray(memoriesTable.id, [...params.ids]),\n\t\t\t\tisNull(memoriesTable.supersededBy),\n\t\t\t),\n\t\t)\n\t\t.returning({ id: memoriesTable.id, tags: memoriesTable.tags });\n\treturn result;\n}\n\nexport async function setMemoryTags(\n\tdb: MnemocyteDatabase,\n\tparams: {\n\t\tentityId: string;\n\t\tmemoryId: string;\n\t\ttags: readonly string[];\n\t\tnow: Date;\n\t},\n): Promise<void> {\n\tawait db\n\t\t.update(memoriesTable)\n\t\t.set({ tags: [...params.tags], updatedAt: params.now })\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(memoriesTable.entityId, params.entityId),\n\t\t\t\teq(memoriesTable.id, params.memoryId),\n\t\t\t),\n\t\t);\n}\n\nexport async function markMemoryAccessed(\n\tdb: MnemocyteDatabase,\n\tmemoryIds: readonly string[],\n): Promise<void> {\n\tif (memoryIds.length === 0) {\n\t\treturn;\n\t}\n\tawait db\n\t\t.update(memoriesTable)\n\t\t.set({\n\t\t\tlastAccessedAt: new Date(),\n\t\t\taccessCount: sql`${memoriesTable.accessCount} + 1`,\n\t\t\tupdatedAt: new Date(),\n\t\t})\n\t\t.where(inArray(memoriesTable.id, [...memoryIds]));\n}\n\nexport async function vectorSearch(\n\tdb: MnemocyteDatabase,\n\tinput: VectorSearchInput,\n): Promise<Array<MemoryRow & { vectorScore: number }>> {\n\tconst embedding = vectorLiteral(input.embedding);\n\tconst minScore = input.minScore ?? 0;\n\tconst rows = await db.execute(sql`\n\t\tSELECT\n\t\t\tid,\n\t\t\tentity_id AS \"entityId\",\n\t\t\tcontent,\n\t\t\ttype,\n\t\t\timportance,\n\t\t\ttags,\n\t\t\tsource,\n\t\t\tmetadata,\n\t\t\tconfidence,\n\t\t\tembedding,\n\t\t\tembedding_model AS \"embeddingModel\",\n\t\t\tembedding_dimensions AS \"embeddingDimensions\",\n\t\t\tsuperseded_by AS \"supersededBy\",\n\t\t\tsuperseded_at AS \"supersededAt\",\n\t\t\texpires_at AS \"expiresAt\",\n\t\t\tlast_accessed_at AS \"lastAccessedAt\",\n\t\t\taccess_count AS \"accessCount\",\n\t\t\tcreated_at AS \"createdAt\",\n\t\t\tupdated_at AS \"updatedAt\",\n\t\t\t1 - (embedding <=> ${embedding}::vector) AS \"vectorScore\"\n\t\tFROM mnemocyte_memories\n\t\tWHERE\n\t\t\tentity_id = ${input.entityId}\n\t\t\tAND embedding IS NOT NULL\n\t\t\t${input.includeSuperseded ? sql`` : sql`AND superseded_by IS NULL`}\n\t\t\t${input.includeExpired ? sql`` : sql`AND (expires_at IS NULL OR expires_at > now())`}\n\t\t\t${\n\t\t\t\tinput.types && input.types.length > 0\n\t\t\t\t\t? sql`AND type IN (${sql.join(\n\t\t\t\t\t\t\tinput.types.map((type) => sql`${type}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)})`\n\t\t\t\t\t: sql``\n\t\t\t}\n\t\t\t${input.tags && input.tags.length > 0 ? sql`AND tags && ${input.tags}` : sql``}\n\t\t\t${input.before ? sql`AND created_at < ${input.before}` : sql``}\n\t\t\t${input.after ? sql`AND created_at > ${input.after}` : sql``}\n\t\t\tAND 1 - (embedding <=> ${embedding}::vector) >= ${minScore}\n\t\tORDER BY embedding <=> ${embedding}::vector\n\t\tLIMIT ${input.limit}\n\t`);\n\treturn rows as unknown as Array<MemoryRow & { vectorScore: number }>;\n}\n\nexport async function lexicalSearch(\n\tdb: MnemocyteDatabase,\n\tinput: LexicalSearchInput,\n): Promise<Array<MemoryRow & { lexicalScore: number }>> {\n\tconst rows = await db.execute(sql`\n\t\tSELECT\n\t\t\tid,\n\t\t\tentity_id AS \"entityId\",\n\t\t\tcontent,\n\t\t\ttype,\n\t\t\timportance,\n\t\t\ttags,\n\t\t\tsource,\n\t\t\tmetadata,\n\t\t\tconfidence,\n\t\t\tembedding,\n\t\t\tembedding_model AS \"embeddingModel\",\n\t\t\tembedding_dimensions AS \"embeddingDimensions\",\n\t\t\tsuperseded_by AS \"supersededBy\",\n\t\t\tsuperseded_at AS \"supersededAt\",\n\t\t\texpires_at AS \"expiresAt\",\n\t\t\tlast_accessed_at AS \"lastAccessedAt\",\n\t\t\taccess_count AS \"accessCount\",\n\t\t\tcreated_at AS \"createdAt\",\n\t\t\tupdated_at AS \"updatedAt\",\n\t\t\tts_rank(to_tsvector('english', content), websearch_to_tsquery('english', ${input.query})) AS \"lexicalScore\"\n\t\tFROM mnemocyte_memories\n\t\tWHERE\n\t\t\tentity_id = ${input.entityId}\n\t\t\t${input.includeSuperseded ? sql`` : sql`AND superseded_by IS NULL`}\n\t\t\t${input.includeExpired ? sql`` : sql`AND (expires_at IS NULL OR expires_at > now())`}\n\t\t\t${\n\t\t\t\tinput.types && input.types.length > 0\n\t\t\t\t\t? sql`AND type IN (${sql.join(\n\t\t\t\t\t\t\tinput.types.map((type) => sql`${type}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)})`\n\t\t\t\t\t: sql``\n\t\t\t}\n\t\t\t${input.tags && input.tags.length > 0 ? sql`AND tags && ${input.tags}` : sql``}\n\t\t\t${input.before ? sql`AND created_at < ${input.before}` : sql``}\n\t\t\t${input.after ? sql`AND created_at > ${input.after}` : sql``}\n\t\t\tAND to_tsvector('english', content) @@ websearch_to_tsquery('english', ${input.query})\n\t\tORDER BY \"lexicalScore\" DESC\n\t\tLIMIT ${input.limit}\n\t`);\n\treturn rows as unknown as Array<MemoryRow & { lexicalScore: number }>;\n}\n","import type { MnemocyteDatabase } from \"../db/index.js\";\nimport {\n\tlexicalSearch,\n\tmarkMemoryAccessed,\n\tvectorSearch,\n} from \"../db/queries/memories.js\";\nimport type { MemoryRow } from \"../db/schema.js\";\nimport { embedOne, rowToMemory } from \"../memory/shared.js\";\nimport type {\n\tEmbedder,\n\tMemoryWithScore,\n\tProviderResilienceConfig,\n\tRecallInput,\n\tRetrievalConfig,\n} from \"../types.js\";\nimport { DEFAULT_CANDIDATE_MULTIPLIER, toScoredMemory } from \"./scorer.js\";\n\ninterface HybridRecallInput {\n\tdb: MnemocyteDatabase;\n\tembedder: Embedder;\n\tinput: RecallInput;\n\tlimit: number;\n\tminScore: number;\n\tretrieval: RetrievalConfig | undefined;\n\tsignal?: AbortSignal;\n\tresilience?: ProviderResilienceConfig;\n}\n\ninterface ScoredRow {\n\trow: MemoryRow;\n\tvectorScore: number;\n\tlexicalScore: number;\n}\n\nexport async function hybridRecall(\n\tinput: HybridRecallInput,\n): Promise<MemoryWithScore[]> {\n\tconst queryEmbedding = await embedOne(input.embedder, input.input.query, {\n\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t...(input.resilience === undefined ? {} : { resilience: input.resilience }),\n\t});\n\tconst candidateMultiplier =\n\t\tinput.retrieval?.candidateMultiplier ?? DEFAULT_CANDIDATE_MULTIPLIER;\n\tconst candidateLimit = Math.max(\n\t\tinput.limit,\n\t\tinput.limit * candidateMultiplier,\n\t);\n\tconst [vectorRows, lexicalRows] = await Promise.all([\n\t\tvectorSearch(input.db, {\n\t\t\t...input.input,\n\t\t\tembedding: queryEmbedding,\n\t\t\tlimit: candidateLimit,\n\t\t\tminScore: 0,\n\t\t}),\n\t\tlexicalSearch(input.db, { ...input.input, limit: candidateLimit }),\n\t]);\n\tconst merged = new Map<string, ScoredRow>();\n\tfor (const row of vectorRows) {\n\t\tmerged.set(row.id, {\n\t\t\trow,\n\t\t\tvectorScore: row.vectorScore,\n\t\t\tlexicalScore: 0,\n\t\t});\n\t}\n\tfor (const row of lexicalRows) {\n\t\tconst existing = merged.get(row.id);\n\t\tif (existing) {\n\t\t\texisting.lexicalScore = row.lexicalScore;\n\t\t} else {\n\t\t\tmerged.set(row.id, {\n\t\t\t\trow,\n\t\t\t\tvectorScore: 0,\n\t\t\t\tlexicalScore: row.lexicalScore,\n\t\t\t});\n\t\t}\n\t}\n\tconst scored = Array.from(merged.values())\n\t\t.map((entry) =>\n\t\t\ttoScoredMemory(\n\t\t\t\trowToMemory(entry.row),\n\t\t\t\tMath.max(0, entry.vectorScore),\n\t\t\t\tMath.max(0, entry.lexicalScore),\n\t\t\t\tinput.input,\n\t\t\t\tinput.retrieval,\n\t\t\t),\n\t\t)\n\t\t.filter((memory) => memory.score >= input.minScore)\n\t\t.sort((a, b) => b.score - a.score)\n\t\t.slice(0, input.limit);\n\tawait markMemoryAccessed(\n\t\tinput.db,\n\t\tscored.map((memory) => memory.id),\n\t);\n\treturn scored;\n}\n","import { buildContext } from \"../context/builder.js\";\nimport type { DatabaseHandle } from \"../db/index.js\";\nimport { insertEvent, listEvents } from \"../db/queries/events.js\";\nimport {\n\tcountPruneMatches,\n\tdeleteMemoriesForEntity,\n\tdeleteMemory,\n\tfindDuplicatePairs,\n\tgetMemoryById,\n\tinsertMemory,\n\tlistMemories,\n\tloadConsolidationTargets,\n\tmarkMemoriesSuperseded,\n\ttype PruneFilter,\n\tpruneMemories,\n\tsetMemoryTags,\n} from \"../db/queries/memories.js\";\nimport { type EventRow, memoriesTable } from \"../db/schema.js\";\nimport { MnemocyteError } from \"../errors.js\";\nimport { observe } from \"../observability.js\";\nimport { hybridRecall } from \"../retrieval/index.js\";\nimport type {\n\tAuditEvent,\n\tConsolidateInput,\n\tConsolidateResult,\n\tDuplicatePair,\n\tEntityStats,\n\tExperimentalMnemocyteClient,\n\tFindDuplicatesInput,\n\tGlobalStats,\n\tImportanceLevel,\n\tListAuditLogInput,\n\tMemory,\n\tMnemocyteClient,\n\tMnemocyteConfig,\n\tPruneInput,\n\tPruneResult,\n\tRememberInput,\n} from \"../types.js\";\nimport {\n\tassertLimit,\n\tassertMinScore,\n\tassertNonEmptyString,\n\tcontextInputToRecallInput,\n\tcreateEventId,\n\tcreateId,\n\tDEFAULT_AUDIT_LOG_LIMIT,\n\tDEFAULT_DUPLICATE_LIMIT,\n\tDEFAULT_DUPLICATE_THRESHOLD,\n\tDEFAULT_IMPORTANCE,\n\tDEFAULT_LIMIT,\n\tDEFAULT_MIN_SCORE,\n\tDEFAULT_TYPE,\n\tembedOne,\n\tIMPORTANCE_RANK,\n\tisExpired,\n\tnormalizeTags,\n\trowToMemory,\n\tvalidateConsolidateInput,\n\tvalidateFindDuplicatesInput,\n\tvalidateListAuditLogInput,\n\tvalidatePruneInput,\n\tvalidateRecallInput,\n\tvalidateRememberInput,\n} from \"./shared.js\";\n\nfunction rowToAuditEvent(row: EventRow): AuditEvent {\n\treturn {\n\t\tid: row.id,\n\t\tentityId: row.entityId,\n\t\tdescription: row.description,\n\t\tmetadata: row.metadata as Record<string, unknown>,\n\t\ttimestamp: row.timestamp,\n\t};\n}\n\nconst IMPORTANCE_LEVELS: readonly ImportanceLevel[] = [\n\t\"low\",\n\t\"normal\",\n\t\"high\",\n\t\"critical\",\n];\n\nfunction importanceCeilingLevels(\n\tmax: ImportanceLevel,\n): readonly ImportanceLevel[] {\n\treturn IMPORTANCE_LEVELS.filter(\n\t\t(level) => IMPORTANCE_RANK[level] <= IMPORTANCE_RANK[max],\n\t);\n}\n\nfunction toPruneFilter(input: PruneInput): PruneFilter {\n\tconst filter: PruneFilter = {};\n\tif (input.entityId !== undefined) {\n\t\tfilter.entityId = input.entityId;\n\t}\n\tif (input.expired === true) {\n\t\tfilter.expired = true;\n\t}\n\tif (input.superseded === true) {\n\t\tfilter.superseded = true;\n\t}\n\tif (input.createdBefore !== undefined) {\n\t\tfilter.createdBefore = input.createdBefore;\n\t}\n\tif (input.notAccessedSince !== undefined) {\n\t\tfilter.notAccessedSince = input.notAccessedSince;\n\t}\n\tif (input.types !== undefined && input.types.length > 0) {\n\t\tfilter.types = input.types;\n\t}\n\tif (input.tags !== undefined && input.tags.length > 0) {\n\t\tfilter.tags = input.tags;\n\t}\n\tif (input.maxImportance !== undefined) {\n\t\tfilter.maxImportanceLevels = importanceCeilingLevels(input.maxImportance);\n\t}\n\treturn filter;\n}\n\nexport function createPostgresClient(\n\tconfig: MnemocyteConfig,\n\thandle: DatabaseHandle,\n): MnemocyteClient {\n\tlet closed = false;\n\n\tfunction assertOpen(): void {\n\t\tif (closed) {\n\t\t\tthrow new MnemocyteError(\"Mnemocyte client is closed.\", \"DB\");\n\t\t}\n\t}\n\n\tasync function recordAudit(\n\t\tentityId: string,\n\t\tdescription: string,\n\t\tmetadata: Record<string, unknown>,\n\t): Promise<void> {\n\t\tif (config.audit?.enabled !== true) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tawait insertEvent(handle.db, {\n\t\t\t\tid: createEventId(),\n\t\t\t\tentityId,\n\t\t\t\tdescription,\n\t\t\t\tmetadata,\n\t\t\t\ttimestamp: new Date(),\n\t\t\t});\n\t\t} catch {\n\t\t\t// Audit writes must not break the primary operation.\n\t\t}\n\t}\n\n\tasync function remember(input: RememberInput): Promise<Memory> {\n\t\treturn observe(\n\t\t\tconfig,\n\t\t\t\"postgres\",\n\t\t\t\"remember\",\n\t\t\t{ entityId: input.entityId },\n\t\t\tasync () => {\n\t\t\t\tassertOpen();\n\t\t\t\tvalidateRememberInput(input);\n\t\t\t\tconst embedding = await embedOne(config.embedder, input.content, {\n\t\t\t\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t\t\t\t...(config.provider === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { resilience: config.provider }),\n\t\t\t\t});\n\t\t\t\tconst now = new Date();\n\t\t\t\tconst row = await insertMemory(handle.db, {\n\t\t\t\t\tid: createId(),\n\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\tcontent: input.content,\n\t\t\t\t\ttype: input.type ?? DEFAULT_TYPE,\n\t\t\t\t\timportance: input.importance ?? DEFAULT_IMPORTANCE,\n\t\t\t\t\ttags: normalizeTags(input.tags),\n\t\t\t\t\tsource: input.source ?? null,\n\t\t\t\t\tmetadata: input.metadata ?? {},\n\t\t\t\t\tconfidence: input.confidence ?? 1,\n\t\t\t\t\tembedding,\n\t\t\t\t\tembeddingModel: config.embedder.model,\n\t\t\t\t\tembeddingDimensions: config.embedder.dimensions,\n\t\t\t\t\tsupersededBy: null,\n\t\t\t\t\tsupersededAt: null,\n\t\t\t\t\texpiresAt: input.expiresAt ?? null,\n\t\t\t\t\tlastAccessedAt: null,\n\t\t\t\t\taccessCount: 0,\n\t\t\t\t\tcreatedAt: now,\n\t\t\t\t\tupdatedAt: now,\n\t\t\t\t});\n\t\t\t\tconst memory = rowToMemory(row);\n\t\t\t\tawait recordAudit(memory.entityId, \"memory.created\", {\n\t\t\t\t\tmemoryId: memory.id,\n\t\t\t\t\ttype: memory.type,\n\t\t\t\t\timportance: memory.importance,\n\t\t\t\t});\n\t\t\t\treturn memory;\n\t\t\t},\n\t\t\t(memory) => ({ memoryId: memory.id, count: 1 }),\n\t\t);\n\t}\n\n\treturn {\n\t\tremember,\n\t\tasync rememberMany(inputs) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"rememberMany\",\n\t\t\t\t{ count: inputs.length },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tconst result: Memory[] = [];\n\t\t\t\t\tfor (const input of inputs) {\n\t\t\t\t\t\tresult.push(await remember(input));\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync recall(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"recall\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateRecallInput(input);\n\t\t\t\t\tconst limit = input.limit ?? config.defaults?.limit ?? DEFAULT_LIMIT;\n\t\t\t\t\tconst minScore =\n\t\t\t\t\t\tinput.minScore ?? config.defaults?.minScore ?? DEFAULT_MIN_SCORE;\n\t\t\t\t\tassertLimit(limit);\n\t\t\t\t\tassertMinScore(minScore);\n\t\t\t\t\treturn hybridRecall({\n\t\t\t\t\t\tdb: handle.db,\n\t\t\t\t\t\tembedder: config.embedder,\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\tlimit,\n\t\t\t\t\t\tminScore,\n\t\t\t\t\t\tretrieval: config.retrieval,\n\t\t\t\t\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t\t\t\t\t...(config.provider === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { resilience: config.provider }),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync buildContext(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"buildContext\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\treturn buildContext({\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\trecall: (contextInput) => {\n\t\t\t\t\t\t\tconst recallInput = contextInputToRecallInput(contextInput);\n\t\t\t\t\t\t\treturn this.recall(\n\t\t\t\t\t\t\t\tinput.signal === undefined\n\t\t\t\t\t\t\t\t\t? recallInput\n\t\t\t\t\t\t\t\t\t: { ...recallInput, signal: input.signal },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\tasync forget(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"forget\",\n\t\t\t\t{ entityId: input.entityId, memoryId: input.memoryId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t\t\t\t\tassertNonEmptyString(input.memoryId, \"memoryId\");\n\t\t\t\t\tconst deleted = await deleteMemory(\n\t\t\t\t\t\thandle.db,\n\t\t\t\t\t\tinput.entityId,\n\t\t\t\t\t\tinput.memoryId,\n\t\t\t\t\t);\n\t\t\t\t\tif (!deleted) {\n\t\t\t\t\t\tthrow new MnemocyteError(\"Memory was not found.\", \"NOT_FOUND\");\n\t\t\t\t\t}\n\t\t\t\t\tawait recordAudit(input.entityId, \"memory.deleted\", {\n\t\t\t\t\t\tmemoryId: input.memoryId,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\tasync forgetAll(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"forgetAll\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t\t\t\t\tconst deletedCount = await deleteMemoriesForEntity(\n\t\t\t\t\t\thandle.db,\n\t\t\t\t\t\tinput.entityId,\n\t\t\t\t\t);\n\t\t\t\t\tawait recordAudit(input.entityId, \"entity.cleared\", {\n\t\t\t\t\t\tcount: deletedCount,\n\t\t\t\t\t});\n\t\t\t\t\treturn deletedCount;\n\t\t\t\t},\n\t\t\t\t(count) => ({ count }),\n\t\t\t).then(() => undefined);\n\t\t},\n\t\tasync prune(input: PruneInput): Promise<PruneResult> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"prune\",\n\t\t\t\tinput.entityId === undefined ? {} : { entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidatePruneInput(input);\n\t\t\t\t\tconst filter = toPruneFilter(input);\n\t\t\t\t\tconst dryRun = input.dryRun === true;\n\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\tconst matchedCount = await countPruneMatches(handle.db, filter);\n\t\t\t\t\t\treturn { matchedCount, deletedCount: 0, dryRun: true };\n\t\t\t\t\t}\n\t\t\t\t\tconst deletedCount = await pruneMemories(handle.db, filter);\n\t\t\t\t\tif (deletedCount > 0 && input.entityId !== undefined) {\n\t\t\t\t\t\tawait recordAudit(input.entityId, \"memory.pruned\", {\n\t\t\t\t\t\t\tcount: deletedCount,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tmatchedCount: deletedCount,\n\t\t\t\t\t\tdeletedCount,\n\t\t\t\t\t\tdryRun: false,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.deletedCount }),\n\t\t\t);\n\t\t},\n\t\tasync findDuplicates(input: FindDuplicatesInput): Promise<DuplicatePair[]> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"findDuplicates\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateFindDuplicatesInput(input);\n\t\t\t\t\tconst threshold = input.threshold ?? DEFAULT_DUPLICATE_THRESHOLD;\n\t\t\t\t\tconst limit = input.limit ?? DEFAULT_DUPLICATE_LIMIT;\n\t\t\t\t\tconst rows = await findDuplicatePairs(handle.db, {\n\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\tthreshold,\n\t\t\t\t\t\tlimit,\n\t\t\t\t\t\t...(input.types === undefined ? {} : { types: input.types }),\n\t\t\t\t\t\t...(input.tags === undefined ? {} : { tags: input.tags }),\n\t\t\t\t\t\t...(input.includeSuperseded === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { includeSuperseded: input.includeSuperseded }),\n\t\t\t\t\t\t...(input.includeExpired === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { includeExpired: input.includeExpired }),\n\t\t\t\t\t});\n\t\t\t\t\treturn rows.map((row) => ({\n\t\t\t\t\t\ta: rowToMemory(row.a),\n\t\t\t\t\t\tb: rowToMemory(row.b),\n\t\t\t\t\t\tsimilarity: Math.max(0, Math.min(1, row.similarity)),\n\t\t\t\t\t}));\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync listAuditLog(input: ListAuditLogInput): Promise<AuditEvent[]> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"listAuditLog\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateListAuditLogInput(input);\n\t\t\t\t\tconst rows = await listEvents(handle.db, {\n\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\tlimit: input.limit ?? DEFAULT_AUDIT_LOG_LIMIT,\n\t\t\t\t\t\t...(input.before === undefined ? {} : { before: input.before }),\n\t\t\t\t\t\t...(input.after === undefined ? {} : { after: input.after }),\n\t\t\t\t\t});\n\t\t\t\t\treturn rows.map(rowToAuditEvent);\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync stats(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"stats\",\n\t\t\t\tinput?.entityId ? { entityId: input.entityId } : {},\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tif (input?.entityId) {\n\t\t\t\t\t\tconst selected = await listMemories(handle.db, {\n\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\tincludeExpired: true,\n\t\t\t\t\t\t\tincludeSuperseded: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\tmemoryCount: selected.length,\n\t\t\t\t\t\t\tactiveMemoryCount: selected.filter(\n\t\t\t\t\t\t\t\t(memory) =>\n\t\t\t\t\t\t\t\t\t!isExpired(rowToMemory(memory), now) &&\n\t\t\t\t\t\t\t\t\tmemory.supersededBy === null,\n\t\t\t\t\t\t\t).length,\n\t\t\t\t\t\t\texpiredMemoryCount: selected.filter((memory) =>\n\t\t\t\t\t\t\t\tisExpired(rowToMemory(memory), now),\n\t\t\t\t\t\t\t).length,\n\t\t\t\t\t\t\tsupersededMemoryCount: selected.filter(\n\t\t\t\t\t\t\t\t(memory) => memory.supersededBy !== null,\n\t\t\t\t\t\t\t).length,\n\t\t\t\t\t\t} satisfies EntityStats;\n\t\t\t\t\t}\n\t\t\t\t\tconst allMemories = await handle.db.select().from(memoriesTable);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tentityCount: new Set(allMemories.map((memory) => memory.entityId))\n\t\t\t\t\t\t\t.size,\n\t\t\t\t\t\tmemoryCount: allMemories.length,\n\t\t\t\t\t\tactiveMemoryCount: allMemories.filter(\n\t\t\t\t\t\t\t(memory) =>\n\t\t\t\t\t\t\t\t!isExpired(rowToMemory(memory), now) &&\n\t\t\t\t\t\t\t\tmemory.supersededBy === null,\n\t\t\t\t\t\t).length,\n\t\t\t\t\t\texpiredMemoryCount: allMemories.filter((memory) =>\n\t\t\t\t\t\t\tisExpired(rowToMemory(memory), now),\n\t\t\t\t\t\t).length,\n\t\t\t\t\t\tsupersededMemoryCount: allMemories.filter(\n\t\t\t\t\t\t\t(memory) => memory.supersededBy !== null,\n\t\t\t\t\t\t).length,\n\t\t\t\t\t} satisfies GlobalStats;\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\texperimental: createExperimental(),\n\t\tasync close() {\n\t\t\treturn observe(config, \"postgres\", \"close\", {}, async () => {\n\t\t\t\tclosed = true;\n\t\t\t\tawait handle.close();\n\t\t\t});\n\t\t},\n\t};\n\n\tfunction createExperimental(): ExperimentalMnemocyteClient {\n\t\treturn {\n\t\t\tasync consolidate(input: ConsolidateInput): Promise<ConsolidateResult> {\n\t\t\t\treturn observe(\n\t\t\t\t\tconfig,\n\t\t\t\t\t\"postgres\",\n\t\t\t\t\t\"consolidate\",\n\t\t\t\t\t{ entityId: input.entityId, memoryId: input.survivorId },\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\tassertOpen();\n\t\t\t\t\t\tvalidateConsolidateInput(input);\n\t\t\t\t\t\tconst survivor = await getMemoryById(\n\t\t\t\t\t\t\thandle.db,\n\t\t\t\t\t\t\tinput.entityId,\n\t\t\t\t\t\t\tinput.survivorId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!survivor) {\n\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\"Survivor memory was not found.\",\n\t\t\t\t\t\t\t\t\"NOT_FOUND\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (survivor.supersededBy !== null) {\n\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\"Survivor memory is itself superseded.\",\n\t\t\t\t\t\t\t\t\"VALIDATION\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst targets = await loadConsolidationTargets(\n\t\t\t\t\t\t\thandle.db,\n\t\t\t\t\t\t\tinput.entityId,\n\t\t\t\t\t\t\tinput.supersededIds,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst foundIds = new Set(targets.map((t) => t.id));\n\t\t\t\t\t\tfor (const id of input.supersededIds) {\n\t\t\t\t\t\t\tif (!foundIds.has(id)) {\n\t\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\t\"Superseded memory was not found.\",\n\t\t\t\t\t\t\t\t\t\"NOT_FOUND\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst losers = targets.filter(\n\t\t\t\t\t\t\t(target) => target.supersededBy === null,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (losers.length === 0) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tsurvivorId: survivor.id,\n\t\t\t\t\t\t\t\tsupersededCount: 0,\n\t\t\t\t\t\t\t\tsupersededIds: [],\n\t\t\t\t\t\t\t} satisfies ConsolidateResult;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst now = new Date();\n\t\t\t\t\t\tconst updated = await markMemoriesSuperseded(handle.db, {\n\t\t\t\t\t\t\tsurvivorId: survivor.id,\n\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\tids: losers.map((loser) => loser.id),\n\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst newSupersededIds = updated.map((row) => row.id);\n\t\t\t\t\t\tfor (const id of newSupersededIds) {\n\t\t\t\t\t\t\tawait recordAudit(input.entityId, \"memory.superseded\", {\n\t\t\t\t\t\t\t\tmemoryId: id,\n\t\t\t\t\t\t\t\tsupersededBy: survivor.id,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (input.mergeTags !== false && updated.length > 0) {\n\t\t\t\t\t\t\tconst mergedTags = new Set(survivor.tags);\n\t\t\t\t\t\t\tfor (const row of updated) {\n\t\t\t\t\t\t\t\tfor (const tag of row.tags) {\n\t\t\t\t\t\t\t\t\tmergedTags.add(tag);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (mergedTags.size !== survivor.tags.length) {\n\t\t\t\t\t\t\t\tawait setMemoryTags(handle.db, {\n\t\t\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\t\t\tmemoryId: survivor.id,\n\t\t\t\t\t\t\t\t\ttags: [...mergedTags],\n\t\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsurvivorId: survivor.id,\n\t\t\t\t\t\t\tsupersededCount: newSupersededIds.length,\n\t\t\t\t\t\t\tsupersededIds: newSupersededIds,\n\t\t\t\t\t\t} satisfies ConsolidateResult;\n\t\t\t\t\t},\n\t\t\t\t\t(result) => ({ count: result.supersededCount }),\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t}\n}\n","import { createDatabase } from \"./db/index.js\";\nimport { MnemocyteError } from \"./errors.js\";\nimport { createInMemoryClient } from \"./memory/in-memory.js\";\nimport { createPostgresClient } from \"./memory/postgres.js\";\nimport { assertEmbedder, assertNonEmptyString } from \"./memory/shared.js\";\nimport type { MnemocyteClient, MnemocyteConfig } from \"./types.js\";\n\n/** Embedding dimensionality pinned by `migrations/0000_initial.sql`. */\nconst POSTGRES_EMBEDDING_DIMENSIONS = 1536;\n\n/**\n * Create a Mnemocyte client.\n *\n * When {@link MnemocyteConfig.databaseUrl} is provided, a Postgres-backed\n * client is returned (requires the `pgvector` extension and the bundled\n * migration applied). Otherwise an in-memory client is returned, intended\n * for tests, demos, and short-lived processes.\n *\n * The returned client owns any underlying resources (e.g. the Postgres\n * connection pool). Call {@link MnemocyteClient.close} when finished to\n * release them.\n *\n * @param config - Client configuration. {@link MnemocyteConfig.embedder} is required.\n * @returns A {@link MnemocyteClient} instance.\n * @throws {MnemocyteError} With code `\"CONFIG\"` if `embedder` is missing or\n * invalid (including when `databaseUrl` is set and `embedder.dimensions`\n * is not 1536 — the dimensionality pinned by the bundled migration), or\n * `\"VALIDATION\"` if `databaseUrl` is provided but empty.\n *\n * @example Postgres-backed client\n * ```ts\n * const client = createMnemocyte({\n * databaseUrl: process.env.DATABASE_URL,\n * embedder, // embedder.dimensions MUST be 1536 for the Postgres backend\n * });\n * ```\n */\nexport function createMnemocyte(config: MnemocyteConfig): MnemocyteClient {\n\tassertEmbedder(config.embedder);\n\tif (config.databaseUrl) {\n\t\tassertNonEmptyString(config.databaseUrl, \"databaseUrl\");\n\t\tif (config.embedder.dimensions !== POSTGRES_EMBEDDING_DIMENSIONS) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t`embedder.dimensions must be ${POSTGRES_EMBEDDING_DIMENSIONS} for the Postgres backend (got ${config.embedder.dimensions}). The bundled migration pins the vector column to vector(${POSTGRES_EMBEDDING_DIMENSIONS}).`,\n\t\t\t\t\"CONFIG\",\n\t\t\t);\n\t\t}\n\t\treturn createPostgresClient(config, createDatabase(config.databaseUrl));\n\t}\n\treturn createInMemoryClient(config);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["formatVectorComponent"],"sources":["../src/db/schema.ts","../src/db/index.ts","../src/errors.ts","../src/context/formatter.ts","../src/context/tokens.ts","../src/context/builder.ts","../src/observability.ts","../src/resilience.ts","../src/memory/shared.ts","../src/retrieval/scorer.ts","../src/memory/in-memory.ts","../src/db/queries/events.ts","../src/db/queries/memories.ts","../src/retrieval/index.ts","../src/memory/postgres.ts","../src/client.ts"],"sourcesContent":["import { sql } from \"drizzle-orm\";\nimport {\n\tcustomType,\n\tindex,\n\tinteger,\n\tjsonb,\n\ttype AnyPgColumn,\n\tpgTable,\n\treal,\n\ttext,\n\ttimestamp,\n} from \"drizzle-orm/pg-core\";\n\nconst vector = customType<{ data: number[]; driverData: string }>({\n\tdataType(config) {\n\t\tconst dimensions = typeof config === \"number\" ? config : 1536;\n\t\treturn `vector(${dimensions})`;\n\t},\n\ttoDriver(value) {\n\t\treturn `[${value.map(formatVectorComponent).join(\",\")}]`;\n\t},\n\tfromDriver(value) {\n\t\treturn value.slice(1, -1).split(\",\").filter(Boolean).map(Number);\n\t},\n});\n\nfunction formatVectorComponent(value: number): string {\n\tif (!Number.isFinite(value)) {\n\t\tthrow new Error(\"Vector values must be finite numbers.\");\n\t}\n\treturn Object.is(value, -0) ? \"0\" : value.toFixed(17);\n}\n\nexport const memoriesTable = pgTable(\n\t\"mnemocyte_memories\",\n\t{\n\t\tid: text(\"id\").primaryKey(),\n\t\tentityId: text(\"entity_id\").notNull(),\n\t\tcontent: text(\"content\").notNull(),\n\t\ttype: text(\"type\").notNull().default(\"fact\"),\n\t\timportance: text(\"importance\").notNull().default(\"normal\"),\n\t\ttags: text(\"tags\").array().notNull().default(sql`'{}'::text[]`),\n\t\tsource: text(\"source\"),\n\t\tmetadata: jsonb(\"metadata\").notNull().default({}),\n\t\tconfidence: real(\"confidence\").notNull().default(1),\n\t\tembedding: vector(\"embedding\", { dimensions: 1536 }),\n\t\tembeddingModel: text(\"embedding_model\").notNull(),\n\t\tembeddingDimensions: integer(\"embedding_dimensions\").notNull(),\n\t\tsupersededBy: text(\"superseded_by\").references(\n\t\t\t(): AnyPgColumn => memoriesTable.id,\n\t\t),\n\t\tsupersededAt: timestamp(\"superseded_at\", { withTimezone: true }),\n\t\texpiresAt: timestamp(\"expires_at\", { withTimezone: true }),\n\t\tlastAccessedAt: timestamp(\"last_accessed_at\", { withTimezone: true }),\n\t\taccessCount: integer(\"access_count\").notNull().default(0),\n\t\tcreatedAt: timestamp(\"created_at\", { withTimezone: true })\n\t\t\t.notNull()\n\t\t\t.defaultNow(),\n\t\tupdatedAt: timestamp(\"updated_at\", { withTimezone: true })\n\t\t\t.notNull()\n\t\t\t.defaultNow(),\n\t},\n\t(table) => [\n\t\tindex(\"mnemocyte_memories_entity_idx\").on(table.entityId),\n\t\tindex(\"mnemocyte_memories_entity_type_idx\").on(table.entityId, table.type),\n\t],\n);\n\nexport const eventsTable = pgTable(\n\t\"mnemocyte_events\",\n\t{\n\t\tid: text(\"id\").primaryKey(),\n\t\tentityId: text(\"entity_id\").notNull(),\n\t\tdescription: text(\"description\").notNull(),\n\t\tmetadata: jsonb(\"metadata\").notNull().default({}),\n\t\ttimestamp: timestamp(\"timestamp\", { withTimezone: true })\n\t\t\t.notNull()\n\t\t\t.defaultNow(),\n\t},\n\t(table) => [\n\t\tindex(\"mnemocyte_events_entity_time_idx\").on(\n\t\t\ttable.entityId,\n\t\t\ttable.timestamp,\n\t\t),\n\t],\n);\n\nexport type MemoryRow = typeof memoriesTable.$inferSelect;\nexport type NewMemoryRow = typeof memoriesTable.$inferInsert;\nexport type EventRow = typeof eventsTable.$inferSelect;\nexport type NewEventRow = typeof eventsTable.$inferInsert;\n","import { drizzle, type PostgresJsDatabase } from \"drizzle-orm/postgres-js\";\nimport postgres from \"postgres\";\nimport * as schema from \"./schema.js\";\n\nexport type MnemocyteDatabase = PostgresJsDatabase<typeof schema>;\n\nexport interface DatabaseHandle {\n\tdb: MnemocyteDatabase;\n\tclose(): Promise<void>;\n}\n\nexport function createDatabase(databaseUrl: string): DatabaseHandle {\n\tconst client = postgres(databaseUrl, {\n\t\tmax: 10,\n\t\tidle_timeout: 20,\n\t\tconnect_timeout: 10,\n\t});\n\n\treturn {\n\t\tdb: drizzle(client, { schema }),\n\t\tasync close() {\n\t\t\tawait client.end();\n\t\t},\n\t};\n}\n","/**\n * Stable, machine-readable error code attached to every {@link MnemocyteError}.\n *\n * - `\"CONFIG\"` — invalid client configuration (e.g. missing or malformed embedder).\n * - `\"VALIDATION\"` — invalid argument passed to a client method.\n * - `\"DB\"` — Postgres or driver-level failure.\n * - `\"EMBEDDING\"` — embedder threw or returned an invalid vector.\n * - `\"NOT_FOUND\"` — referenced memory or entity does not exist.\n * - `\"MIGRATION\"` — schema/migration check failed against the target database.\n * - `\"TIMEOUT\"` — a provider call exceeded its configured timeout.\n * - `\"ABORTED\"` — the operation was cancelled via an `AbortSignal`.\n */\nexport type MnemocyteErrorCode =\n\t| \"CONFIG\"\n\t| \"VALIDATION\"\n\t| \"DB\"\n\t| \"EMBEDDING\"\n\t| \"NOT_FOUND\"\n\t| \"MIGRATION\"\n\t| \"TIMEOUT\"\n\t| \"ABORTED\";\n\n/**\n * Error type thrown by every public Mnemocyte API.\n *\n * Use the {@link MnemocyteError.code} property — not the message — to branch\n * on failure modes, or call {@link isMnemocyteError} as a type guard when\n * working with `unknown` errors.\n *\n * @example\n * ```ts\n * try {\n * await client.recall({ entityId: \"u1\", query: \"hi\" });\n * } catch (err) {\n * if (isMnemocyteError(err) && err.code === \"DB\") {\n * // handle database failure\n * }\n * throw err;\n * }\n * ```\n */\nexport class MnemocyteError extends Error {\n\t/** Stable, machine-readable failure code. See {@link MnemocyteErrorCode}. */\n\treadonly code: MnemocyteErrorCode;\n\t/** Underlying cause, if any (e.g. an original driver or embedder error). */\n\toverride readonly cause?: unknown;\n\n\t/**\n\t * @param message - Human-readable error message.\n\t * @param code - Stable failure code; see {@link MnemocyteErrorCode}.\n\t * @param cause - Optional underlying cause (driver error, network error, etc.).\n\t */\n\tconstructor(message: string, code: MnemocyteErrorCode, cause?: unknown) {\n\t\tsuper(message);\n\t\tthis.name = \"MnemocyteError\";\n\t\tthis.code = code;\n\t\tthis.cause = cause;\n\t}\n}\n\n/**\n * Type guard for {@link MnemocyteError}.\n *\n * Prefer this over `instanceof` when working across module boundaries or\n * bundlers where multiple copies of the class may exist.\n *\n * @param error - Value to test (typically a caught `unknown`).\n * @returns `true` if `error` is a {@link MnemocyteError}.\n */\nexport function isMnemocyteError(error: unknown): error is MnemocyteError {\n\treturn error instanceof MnemocyteError;\n}\n","import type { ContextFormat, MemoryWithScore } from \"../types.js\";\n\nfunction escapeXml(value: string): string {\n\treturn value\n\t\t.replaceAll(\"&\", \"&amp;\")\n\t\t.replaceAll(\"<\", \"&lt;\")\n\t\t.replaceAll(\">\", \"&gt;\")\n\t\t.replaceAll('\"', \"&quot;\")\n\t\t.replaceAll(\"'\", \"&apos;\");\n}\n\nfunction formatMetadata(memory: MemoryWithScore): string {\n\tconst parts = [\n\t\t`type=${memory.type}`,\n\t\t`importance=${memory.importance}`,\n\t\t`score=${memory.score.toFixed(3)}`,\n\t];\n\tif (memory.source) {\n\t\tparts.push(`source=${memory.source}`);\n\t}\n\tif (memory.tags.length > 0) {\n\t\tparts.push(`tags=${memory.tags.join(\",\")}`);\n\t}\n\treturn parts.join(\"; \");\n}\n\nfunction markdownFence(value: string): string {\n\tconst longestBacktickRun = Math.max(\n\t\t0,\n\t\t...Array.from(value.matchAll(/`+/g), (match) => match[0].length),\n\t);\n\treturn \"`\".repeat(Math.max(3, longestBacktickRun + 1));\n}\n\nfunction formatMarkdown(\n\tmemories: readonly MemoryWithScore[],\n\tquery: string,\n\tomittedCount: number,\n): string {\n\tconst lines = [\n\t\t\"# Memory Context\",\n\t\t\"\",\n\t\t`Query: ${query}`,\n\t\t\"\",\n\t\t\"## Relevant Memories\",\n\t];\n\tfor (const memory of memories) {\n\t\tconst fence = markdownFence(memory.content);\n\t\tlines.push(\n\t\t\t\"\",\n\t\t\t`- ${formatMetadata(memory)}`,\n\t\t\t` ${fence}text`,\n\t\t\t...memory.content.split(\"\\n\").map((line) => ` ${line}`),\n\t\t\t` ${fence}`,\n\t\t);\n\t}\n\tif (omittedCount > 0) {\n\t\tlines.push(\"\", `[${omittedCount} memories omitted to fit token budget]`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction formatPlain(\n\tmemories: readonly MemoryWithScore[],\n\tquery: string,\n\tomittedCount: number,\n): string {\n\tconst lines = [\n\t\t\"MEMORY CONTEXT\",\n\t\t\"\",\n\t\t`QUERY: ${query}`,\n\t\t\"\",\n\t\t\"RELEVANT MEMORIES\",\n\t];\n\tfor (const [index, memory] of memories.entries()) {\n\t\tlines.push(\n\t\t\t\"\",\n\t\t\t`--- MEMORY ${index + 1} START ---`,\n\t\t\tformatMetadata(memory),\n\t\t\tmemory.content,\n\t\t\t`--- MEMORY ${index + 1} END ---`,\n\t\t);\n\t}\n\tif (omittedCount > 0) {\n\t\tlines.push(\"\", `[${omittedCount} memories omitted to fit token budget]`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction formatXml(\n\tmemories: readonly MemoryWithScore[],\n\tquery: string,\n\tomittedCount: number,\n): string {\n\tconst lines = [`<memory_context query=\"${escapeXml(query)}\">`];\n\tfor (const memory of memories) {\n\t\tlines.push(\n\t\t\t` <memory id=\"${escapeXml(memory.id)}\" type=\"${escapeXml(memory.type)}\" importance=\"${escapeXml(memory.importance)}\" score=\"${memory.score.toFixed(3)}\">`,\n\t\t\t` <content>${escapeXml(memory.content)}</content>`,\n\t\t\t` <metadata>${escapeXml(formatMetadata(memory))}</metadata>`,\n\t\t\t\" </memory>\",\n\t\t);\n\t}\n\tif (omittedCount > 0) {\n\t\tlines.push(` <omitted count=\"${omittedCount}\" reason=\"token_budget\" />`);\n\t}\n\tlines.push(\"</memory_context>\");\n\treturn lines.join(\"\\n\");\n}\n\nexport function formatContext(\n\tmemories: readonly MemoryWithScore[],\n\tquery: string,\n\tformat: ContextFormat,\n\tomittedCount = 0,\n): string {\n\tswitch (format) {\n\t\tcase \"markdown\":\n\t\t\treturn formatMarkdown(memories, query, omittedCount);\n\t\tcase \"plain\":\n\t\t\treturn formatPlain(memories, query, omittedCount);\n\t\tcase \"xml\":\n\t\t\treturn formatXml(memories, query, omittedCount);\n\t}\n}\n","import type { TokenCounter } from \"../types.js\";\n\nexport const heuristicTokenCounter: TokenCounter = {\n\tcount(text) {\n\t\treturn Math.ceil(text.length / 4);\n\t},\n};\n\nexport function trimToTokenBudget(\n\ttext: string,\n\tmaxTokens: number,\n\ttokenCounter: TokenCounter,\n): string {\n\tif (maxTokens < 1 || tokenCounter.count(text) <= maxTokens) {\n\t\treturn text;\n\t}\n\tlet low = 0;\n\tlet high = text.length;\n\tlet best = \"\";\n\twhile (low <= high) {\n\t\tconst mid = Math.floor((low + high) / 2);\n\t\tconst candidate = text.slice(0, mid).trimEnd();\n\t\tconst output = `${candidate}\\n[truncated to fit token budget]`;\n\t\tif (tokenCounter.count(output) <= maxTokens) {\n\t\t\tbest = output;\n\t\t\tlow = mid + 1;\n\t\t} else {\n\t\t\thigh = mid - 1;\n\t\t}\n\t}\n\treturn best || \"[truncated to fit token budget]\";\n}\n","import type { BuildContextInput, MemoryWithScore } from \"../types.js\";\nimport { formatContext } from \"./formatter.js\";\nimport { heuristicTokenCounter, trimToTokenBudget } from \"./tokens.js\";\n\nexport interface BuildContextOptions {\n\tinput: BuildContextInput;\n\trecall(input: BuildContextInput): Promise<MemoryWithScore[]>;\n}\n\nexport async function buildContext(\n\toptions: BuildContextOptions,\n): Promise<string> {\n\tconst format = options.input.format ?? \"markdown\";\n\tconst maxTokens = options.input.maxTokens ?? 1200;\n\tconst tokenCounter = options.input.tokenCounter ?? heuristicTokenCounter;\n\tconst memories = await options.recall(options.input);\n\tfor (let count = memories.length; count >= 0; count -= 1) {\n\t\tconst omittedCount = memories.length - count;\n\t\tconst context = formatContext(\n\t\t\tmemories.slice(0, count),\n\t\t\toptions.input.query,\n\t\t\tformat,\n\t\t\tomittedCount,\n\t\t);\n\t\tif (tokenCounter.count(context) <= maxTokens) {\n\t\t\treturn context;\n\t\t}\n\t}\n\treturn trimToTokenBudget(\n\t\tformatContext([], options.input.query, format, memories.length),\n\t\tmaxTokens,\n\t\ttokenCounter,\n\t);\n}\n","import type {\n\tMnemocyteBackend,\n\tMnemocyteConfig,\n\tMnemocyteObservation,\n\tMnemocyteOperation,\n} from \"./types.js\";\n\ninterface ObservationMetadata {\n\tentityId?: string;\n\tmemoryId?: string;\n\tcount?: number;\n}\n\nfunction withMetadata(\n\tevent: MnemocyteObservation,\n\tmetadata: ObservationMetadata,\n): MnemocyteObservation {\n\treturn {\n\t\t...event,\n\t\t...(metadata.entityId === undefined ? {} : { entityId: metadata.entityId }),\n\t\t...(metadata.memoryId === undefined ? {} : { memoryId: metadata.memoryId }),\n\t\t...(metadata.count === undefined ? {} : { count: metadata.count }),\n\t};\n}\n\nasync function emitObservation(\n\tconfig: MnemocyteConfig,\n\tevent: MnemocyteObservation,\n): Promise<void> {\n\ttry {\n\t\tawait config.observability?.onEvent?.(event);\n\t} catch {\n\t\treturn;\n\t}\n}\n\nexport async function observe<T>(\n\tconfig: MnemocyteConfig,\n\tbackend: MnemocyteBackend,\n\toperation: MnemocyteOperation,\n\tmetadata: ObservationMetadata,\n\taction: () => Promise<T>,\n\tsuccessMetadata?: (result: T) => ObservationMetadata,\n): Promise<T> {\n\tconst startedAt = Date.now();\n\tawait emitObservation(\n\t\tconfig,\n\t\twithMetadata(\n\t\t\t{\n\t\t\t\toperation,\n\t\t\t\tphase: \"start\",\n\t\t\t\tbackend,\n\t\t\t\ttimestamp: new Date(startedAt),\n\t\t\t},\n\t\t\tmetadata,\n\t\t),\n\t);\n\ttry {\n\t\tconst result = await action();\n\t\tawait emitObservation(\n\t\t\tconfig,\n\t\t\twithMetadata(\n\t\t\t\t{\n\t\t\t\t\toperation,\n\t\t\t\t\tphase: \"success\",\n\t\t\t\t\tbackend,\n\t\t\t\t\ttimestamp: new Date(),\n\t\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t\t},\n\t\t\t\t{ ...metadata, ...successMetadata?.(result) },\n\t\t\t),\n\t\t);\n\t\treturn result;\n\t} catch (error) {\n\t\tawait emitObservation(\n\t\t\tconfig,\n\t\t\twithMetadata(\n\t\t\t\t{\n\t\t\t\t\toperation,\n\t\t\t\t\tphase: \"error\",\n\t\t\t\t\tbackend,\n\t\t\t\t\ttimestamp: new Date(),\n\t\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t\t\terror,\n\t\t\t\t},\n\t\t\t\tmetadata,\n\t\t\t),\n\t\t);\n\t\tthrow error;\n\t}\n}\n","import { MnemocyteError } from \"./errors.js\";\nimport type { ProviderResilienceConfig } from \"./types.js\";\n\n/**\n * Default per-provider-call timeout. Disabled by default so that callers\n * who do not configure {@link ProviderResilienceConfig.timeoutMs} are\n * unaffected.\n */\nconst DEFAULT_TIMEOUT_MS = 0;\n/** Default number of retry attempts on transient provider failures. */\nconst DEFAULT_RETRIES = 0;\n/** Default base backoff delay used between retry attempts. */\nconst DEFAULT_BASE_DELAY_MS = 100;\n/** Default ceiling for retry backoff delay. */\nconst DEFAULT_MAX_DELAY_MS = 2000;\n\n/**\n * Internal helper: returns the AbortSignal as a typed value if available,\n * otherwise `undefined`. Used so call sites can stay narrow.\n */\nexport function getSignal(\n\tsource: { signal?: AbortSignal } | undefined,\n): AbortSignal | undefined {\n\treturn source?.signal;\n}\n\n/**\n * Throw a {@link MnemocyteError} with code `\"ABORTED\"` if `signal` is\n * already aborted. Safe to call with `undefined`.\n */\nexport function throwIfAborted(signal: AbortSignal | undefined): void {\n\tif (signal?.aborted) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"Operation was aborted.\",\n\t\t\t\"ABORTED\",\n\t\t\tsignal.reason,\n\t\t);\n\t}\n}\n\n/**\n * Heuristic default for whether an error should be retried.\n *\n * Conservative by design: only retries on common transient failure\n * indicators (network errors, 5xx-ish messages, `ECONN*` etc.). Never\n * retries on validation, configuration, or {@link MnemocyteError} of\n * code `\"VALIDATION\"` / `\"CONFIG\"` / `\"ABORTED\"`.\n */\nexport function defaultShouldRetry(error: unknown): boolean {\n\tif (error instanceof MnemocyteError) {\n\t\tif (\n\t\t\terror.code === \"VALIDATION\" ||\n\t\t\terror.code === \"CONFIG\" ||\n\t\t\terror.code === \"ABORTED\"\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\tif (error instanceof Error) {\n\t\tconst message = error.message.toLowerCase();\n\t\tif (\n\t\t\tmessage.includes(\"econn\") ||\n\t\t\tmessage.includes(\"etimedout\") ||\n\t\t\tmessage.includes(\"network\") ||\n\t\t\tmessage.includes(\"timeout\") ||\n\t\t\tmessage.includes(\"temporarily\") ||\n\t\t\tmessage.includes(\"rate limit\") ||\n\t\t\tmessage.includes(\"503\") ||\n\t\t\tmessage.includes(\"502\") ||\n\t\t\tmessage.includes(\"504\") ||\n\t\t\tmessage.includes(\"500\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Compute the backoff delay for the given retry attempt, using exponential\n * growth capped at {@link ProviderResilienceConfig.maxDelayMs}.\n *\n * `attempt` is 1-indexed: the delay before the first retry uses\n * `attempt = 1`, before the second retry `attempt = 2`, etc.\n */\nfunction computeDelayMs(\n\tattempt: number,\n\tbaseDelayMs: number,\n\tmaxDelayMs: number,\n): number {\n\tconst exponential = baseDelayMs * 2 ** (attempt - 1);\n\treturn Math.max(0, Math.min(maxDelayMs, exponential));\n}\n\n/**\n * Promise-based `setTimeout` that rejects with an `\"ABORTED\"`\n * {@link MnemocyteError} if `signal` aborts while waiting.\n */\nfunction delay(ms: number, signal: AbortSignal | undefined): Promise<void> {\n\tif (ms <= 0) {\n\t\tthrowIfAborted(signal);\n\t\treturn Promise.resolve();\n\t}\n\treturn new Promise<void>((resolve, reject) => {\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = (): void => {\n\t\t\tclearTimeout(timer);\n\t\t\treject(\n\t\t\t\tnew MnemocyteError(\"Operation was aborted.\", \"ABORTED\", signal?.reason),\n\t\t\t);\n\t\t};\n\t\tif (signal) {\n\t\t\tif (signal.aborted) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(\n\t\t\t\t\tnew MnemocyteError(\n\t\t\t\t\t\t\"Operation was aborted.\",\n\t\t\t\t\t\t\"ABORTED\",\n\t\t\t\t\t\tsignal.reason,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t});\n}\n\n/**\n * Race `promise` against the configured `timeoutMs` and the caller's\n * `signal`. Rejects with `\"TIMEOUT\"` or `\"ABORTED\"` respectively. Resolves\n * with the original promise value if it settles first.\n */\nfunction withTimeout<T>(\n\tpromise: Promise<T>,\n\ttimeoutMs: number,\n\tsignal: AbortSignal | undefined,\n): Promise<T> {\n\tif (timeoutMs <= 0 && !signal) {\n\t\treturn promise;\n\t}\n\treturn new Promise<T>((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst timer =\n\t\t\ttimeoutMs > 0\n\t\t\t\t? setTimeout(() => {\n\t\t\t\t\t\tif (settled) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\treject(\n\t\t\t\t\t\t\tnew MnemocyteError(\n\t\t\t\t\t\t\t\t`Provider call timed out after ${timeoutMs}ms.`,\n\t\t\t\t\t\t\t\t\"TIMEOUT\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}, timeoutMs)\n\t\t\t\t: undefined;\n\t\tconst onAbort = (): void => {\n\t\t\tif (settled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettled = true;\n\t\t\tif (timer) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t}\n\t\t\treject(\n\t\t\t\tnew MnemocyteError(\"Operation was aborted.\", \"ABORTED\", signal?.reason),\n\t\t\t);\n\t\t};\n\t\tif (signal) {\n\t\t\tif (signal.aborted) {\n\t\t\t\tif (timer) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t}\n\t\t\t\tsettled = true;\n\t\t\t\treject(\n\t\t\t\t\tnew MnemocyteError(\n\t\t\t\t\t\t\"Operation was aborted.\",\n\t\t\t\t\t\t\"ABORTED\",\n\t\t\t\t\t\tsignal.reason,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t\tpromise.then(\n\t\t\t(value) => {\n\t\t\t\tif (settled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsettled = true;\n\t\t\t\tif (timer) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t}\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(error) => {\n\t\t\t\tif (settled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsettled = true;\n\t\t\t\tif (timer) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t}\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\treject(error);\n\t\t\t},\n\t\t);\n\t});\n}\n\n/**\n * Options accepted by {@link withResilience}.\n */\nexport interface ResilienceCallOptions {\n\t/** External cancellation signal forwarded to each attempt. */\n\tsignal?: AbortSignal;\n\t/** Provider-level retry/timeout configuration. */\n\tresilience?: ProviderResilienceConfig;\n}\n\n/**\n * Run `action` with timeout, retry, and abort handling derived from\n * `options.resilience` and `options.signal`. Each retry attempt receives\n * a fresh `AbortSignal` linked to the caller's signal — so callers may\n * abort mid-retry and the in-flight attempt will cancel promptly if the\n * underlying provider honours signals.\n *\n * Errors from {@link MnemocyteError} with code `\"VALIDATION\"` /\n * `\"CONFIG\"` / `\"ABORTED\"` are never retried.\n */\nexport async function withResilience<T>(\n\taction: (signal: AbortSignal | undefined) => Promise<T>,\n\toptions: ResilienceCallOptions = {},\n): Promise<T> {\n\tconst config = options.resilience ?? {};\n\tconst timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst retries = Math.max(0, config.retries ?? DEFAULT_RETRIES);\n\tconst baseDelayMs = Math.max(0, config.baseDelayMs ?? DEFAULT_BASE_DELAY_MS);\n\tconst maxDelayMs = Math.max(\n\t\tbaseDelayMs,\n\t\tconfig.maxDelayMs ?? DEFAULT_MAX_DELAY_MS,\n\t);\n\tconst shouldRetry = config.shouldRetry ?? defaultShouldRetry;\n\tconst externalSignal = options.signal;\n\n\tthrowIfAborted(externalSignal);\n\n\tconst maxAttempts = retries + 1;\n\tlet lastError: unknown;\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n\t\tthrowIfAborted(externalSignal);\n\t\ttry {\n\t\t\treturn await withTimeout(\n\t\t\t\taction(externalSignal),\n\t\t\t\ttimeoutMs,\n\t\t\t\texternalSignal,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tlastError = error;\n\t\t\tif (error instanceof MnemocyteError && error.code === \"ABORTED\") {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (attempt >= maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (!shouldRetry(error, attempt)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst waitMs = computeDelayMs(attempt, baseDelayMs, maxDelayMs);\n\t\t\tawait delay(waitMs, externalSignal);\n\t\t}\n\t}\n\tthrow lastError;\n}\n","import type { MemoryRow } from \"../db/schema.js\";\nimport { MnemocyteError } from \"../errors.js\";\nimport { withResilience } from \"../resilience.js\";\nimport type {\n\tBuildContextInput,\n\tConsolidateInput,\n\tEmbedder,\n\tFindDuplicatesInput,\n\tImportanceLevel,\n\tListAuditLogInput,\n\tMemory,\n\tMemoryType,\n\tProviderResilienceConfig,\n\tPruneInput,\n\tRecallInput,\n\tRememberInput,\n} from \"../types.js\";\n\nexport const DEFAULT_LIMIT = 10;\nexport const DEFAULT_MIN_SCORE = 0;\nexport const DEFAULT_TYPE: MemoryType = \"fact\";\nexport const DEFAULT_IMPORTANCE: ImportanceLevel = \"normal\";\n\n/**\n * Ordering of {@link ImportanceLevel} from least to most important. Used\n * by `prune({ maxImportance })` to compare a memory's importance against\n * the caller-supplied ceiling.\n */\nexport const IMPORTANCE_RANK: Record<ImportanceLevel, number> = {\n\tlow: 0,\n\tnormal: 1,\n\thigh: 2,\n\tcritical: 3,\n};\n\nexport interface StoredMemory extends Memory {\n\tembedding: number[];\n}\n\nexport function assertNonEmptyString(value: string, field: string): void {\n\tif (value.trim().length === 0) {\n\t\tthrow new MnemocyteError(\n\t\t\t`${field} must be a non-empty string.`,\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n}\n\nexport function assertLimit(value: number): void {\n\tif (!Number.isInteger(value) || value < 1) {\n\t\tthrow new MnemocyteError(\"limit must be a positive integer.\", \"VALIDATION\");\n\t}\n}\n\nexport function assertMinScore(value: number): void {\n\tif (!Number.isFinite(value) || value < 0 || value > 1) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"minScore must be a number between 0 and 1.\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n}\n\nexport function assertEmbedder(embedder: Embedder): void {\n\tif (!embedder || typeof embedder.embed !== \"function\") {\n\t\tthrow new MnemocyteError(\n\t\t\t\"embedder with an embed function is required.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n\tassertNonEmptyString(embedder.model, \"embedder.model\");\n\tif (!Number.isInteger(embedder.dimensions) || embedder.dimensions < 1) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"embedder.dimensions must be a positive integer.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n}\n\nexport function normalizeTags(tags: readonly string[] | undefined): string[] {\n\tif (!tags) {\n\t\treturn [];\n\t}\n\treturn [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];\n}\n\nexport function createId(): string {\n\treturn `mem_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/** Generate a unique audit-event id (`evt_*`). */\nexport function createEventId(): string {\n\treturn `evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport function isExpired(memory: Memory, now: Date): boolean {\n\treturn (\n\t\tmemory.expiresAt !== null && memory.expiresAt.getTime() <= now.getTime()\n\t);\n}\n\nexport function cloneMemory(memory: Memory): Memory {\n\treturn {\n\t\t...memory,\n\t\ttags: [...memory.tags],\n\t\tmetadata: { ...memory.metadata },\n\t\tsupersededAt: memory.supersededAt ? new Date(memory.supersededAt) : null,\n\t\texpiresAt: memory.expiresAt ? new Date(memory.expiresAt) : null,\n\t\tlastAccessedAt: memory.lastAccessedAt\n\t\t\t? new Date(memory.lastAccessedAt)\n\t\t\t: null,\n\t\tcreatedAt: new Date(memory.createdAt),\n\t\tupdatedAt: new Date(memory.updatedAt),\n\t};\n}\n\nexport function rowToMemory(row: MemoryRow): Memory {\n\treturn {\n\t\tid: row.id,\n\t\tentityId: row.entityId,\n\t\tcontent: row.content,\n\t\ttype: row.type as MemoryType,\n\t\timportance: row.importance as ImportanceLevel,\n\t\ttags: row.tags,\n\t\tsource: row.source,\n\t\tmetadata: row.metadata as Record<string, unknown>,\n\t\tconfidence: row.confidence,\n\t\tembeddingModel: row.embeddingModel,\n\t\tembeddingDimensions: row.embeddingDimensions,\n\t\tsupersededBy: row.supersededBy,\n\t\tsupersededAt: row.supersededAt,\n\t\texpiresAt: row.expiresAt,\n\t\tlastAccessedAt: row.lastAccessedAt,\n\t\taccessCount: row.accessCount,\n\t\tcreatedAt: row.createdAt,\n\t\tupdatedAt: row.updatedAt,\n\t};\n}\n\nexport async function embedOne(\n\tembedder: Embedder,\n\ttext: string,\n\toptions: {\n\t\tsignal?: AbortSignal;\n\t\tresilience?: ProviderResilienceConfig;\n\t} = {},\n): Promise<number[]> {\n\tlet embeddings: number[][];\n\ttry {\n\t\tembeddings = await withResilience(\n\t\t\t(signal) =>\n\t\t\t\tsignal === undefined\n\t\t\t\t\t? embedder.embed([text])\n\t\t\t\t\t: embedder.embed([text], { signal }),\n\t\t\t{\n\t\t\t\t...(options.signal === undefined ? {} : { signal: options.signal }),\n\t\t\t\t...(options.resilience === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { resilience: options.resilience }),\n\t\t\t},\n\t\t);\n\t} catch (error) {\n\t\tif (\n\t\t\terror instanceof MnemocyteError &&\n\t\t\t(error.code === \"TIMEOUT\" || error.code === \"ABORTED\")\n\t\t) {\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new MnemocyteError(\"Failed to embed text.\", \"EMBEDDING\", error);\n\t}\n\tconst embedding = embeddings[0];\n\tif (!embedding) {\n\t\tthrow new MnemocyteError(\"Embedder returned no embedding.\", \"EMBEDDING\");\n\t}\n\tif (embedding.length !== embedder.dimensions) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"Embedder returned an embedding with unexpected dimensions.\",\n\t\t\t\"EMBEDDING\",\n\t\t);\n\t}\n\treturn embedding;\n}\n\nexport function validateRememberInput(input: RememberInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tassertNonEmptyString(input.content, \"content\");\n\tif (\n\t\tinput.confidence !== undefined &&\n\t\t(!Number.isFinite(input.confidence) ||\n\t\t\tinput.confidence < 0 ||\n\t\t\tinput.confidence > 1)\n\t) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"confidence must be a number between 0 and 1.\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n}\n\nexport function validateRecallInput(input: RecallInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tassertNonEmptyString(input.query, \"query\");\n\tif (input.limit !== undefined) {\n\t\tassertLimit(input.limit);\n\t}\n\tif (input.minScore !== undefined) {\n\t\tassertMinScore(input.minScore);\n\t}\n}\n\nexport function contextInputToRecallInput(\n\tinput: BuildContextInput,\n): RecallInput {\n\treturn {\n\t\tentityId: input.entityId,\n\t\tquery: input.query,\n\t\t...(input.limit === undefined ? {} : { limit: input.limit }),\n\t\t...(input.minScore === undefined ? {} : { minScore: input.minScore }),\n\t\t...(input.types === undefined ? {} : { types: input.types }),\n\t\t...(input.tags === undefined ? {} : { tags: input.tags }),\n\t\t...(input.includeSuperseded === undefined\n\t\t\t? {}\n\t\t\t: { includeSuperseded: input.includeSuperseded }),\n\t\t...(input.includeExpired === undefined\n\t\t\t? {}\n\t\t\t: { includeExpired: input.includeExpired }),\n\t};\n}\n\n/**\n * Validate a {@link PruneInput} and throw a `\"VALIDATION\"`\n * {@link MnemocyteError} when no selector is supplied. Mnemocyte\n * deliberately rejects `prune({})` to avoid surprise full-table deletes.\n */\nexport function validatePruneInput(input: PruneInput): void {\n\tif (input.entityId !== undefined) {\n\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t}\n\tconst hasSelector =\n\t\tinput.entityId !== undefined ||\n\t\tinput.expired === true ||\n\t\tinput.superseded === true ||\n\t\tinput.createdBefore !== undefined ||\n\t\tinput.notAccessedSince !== undefined ||\n\t\t(input.types !== undefined && input.types.length > 0) ||\n\t\t(input.tags !== undefined && input.tags.length > 0) ||\n\t\tinput.maxImportance !== undefined;\n\tif (!hasSelector) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"prune requires at least one selector (entityId, expired, superseded, createdBefore, notAccessedSince, types, tags, or maxImportance).\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n}\n\n/**\n * Test whether `memory` matches a {@link PruneInput}. All specified\n * selectors are AND-combined; unspecified selectors do not restrict.\n *\n * `now` is supplied by the caller so callers can share a consistent\n * timestamp across a batch.\n */\nexport function matchesPruneFilter(\n\tmemory: Memory,\n\tinput: PruneInput,\n\tnow: Date,\n): boolean {\n\tif (input.entityId !== undefined && memory.entityId !== input.entityId) {\n\t\treturn false;\n\t}\n\tif (input.expired === true && !isExpired(memory, now)) {\n\t\treturn false;\n\t}\n\tif (input.superseded === true && memory.supersededBy === null) {\n\t\treturn false;\n\t}\n\tif (\n\t\tinput.createdBefore !== undefined &&\n\t\tmemory.createdAt.getTime() >= input.createdBefore.getTime()\n\t) {\n\t\treturn false;\n\t}\n\tif (input.notAccessedSince !== undefined) {\n\t\tconst last = memory.lastAccessedAt;\n\t\tif (last !== null && last.getTime() >= input.notAccessedSince.getTime()) {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (input.types !== undefined && !input.types.includes(memory.type)) {\n\t\treturn false;\n\t}\n\tif (\n\t\tinput.tags !== undefined &&\n\t\tinput.tags.length > 0 &&\n\t\t!input.tags.every((tag) => memory.tags.includes(tag))\n\t) {\n\t\treturn false;\n\t}\n\tif (\n\t\tinput.maxImportance !== undefined &&\n\t\tIMPORTANCE_RANK[memory.importance] > IMPORTANCE_RANK[input.maxImportance]\n\t) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/** Default cosine-similarity threshold for {@link FindDuplicatesInput}. */\nexport const DEFAULT_DUPLICATE_THRESHOLD = 0.95;\n/** Default cap on the number of duplicate pairs returned. */\nexport const DEFAULT_DUPLICATE_LIMIT = 100;\n\n/**\n * Validate a {@link FindDuplicatesInput} and throw a `\"VALIDATION\"`\n * {@link MnemocyteError} for malformed `threshold` / `limit` values.\n */\nexport function validateFindDuplicatesInput(input: FindDuplicatesInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tif (input.threshold !== undefined) {\n\t\tif (\n\t\t\t!Number.isFinite(input.threshold) ||\n\t\t\tinput.threshold < 0 ||\n\t\t\tinput.threshold > 1\n\t\t) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"threshold must be a number between 0 and 1.\",\n\t\t\t\t\"VALIDATION\",\n\t\t\t);\n\t\t}\n\t}\n\tif (input.limit !== undefined) {\n\t\tassertLimit(input.limit);\n\t}\n}\n\n/**\n * Return `true` when a memory should participate in a duplicate scan,\n * given the filters on `input` and a shared `now` timestamp.\n */\nexport function matchesDuplicateFilter(\n\tmemory: Memory,\n\tinput: FindDuplicatesInput,\n\tnow: Date,\n): boolean {\n\tif (memory.entityId !== input.entityId) {\n\t\treturn false;\n\t}\n\tif (input.includeSuperseded !== true && memory.supersededBy !== null) {\n\t\treturn false;\n\t}\n\tif (input.includeExpired !== true && isExpired(memory, now)) {\n\t\treturn false;\n\t}\n\tif (input.types !== undefined && !input.types.includes(memory.type)) {\n\t\treturn false;\n\t}\n\tif (\n\t\tinput.tags !== undefined &&\n\t\tinput.tags.length > 0 &&\n\t\t!input.tags.every((tag) => memory.tags.includes(tag))\n\t) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/** Default cap on audit-log entries returned per `listAuditLog`. */\nexport const DEFAULT_AUDIT_LOG_LIMIT = 50;\n\n/**\n * Validate a {@link ConsolidateInput} and throw a `\"VALIDATION\"`\n * {@link MnemocyteError} for malformed inputs (empty `supersededIds`\n * or a `survivorId` appearing in `supersededIds`).\n */\nexport function validateConsolidateInput(input: ConsolidateInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tassertNonEmptyString(input.survivorId, \"survivorId\");\n\tif (input.supersededIds.length === 0) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"supersededIds must contain at least one memory id.\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n\tif (input.supersededIds.includes(input.survivorId)) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"survivorId must not appear in supersededIds.\",\n\t\t\t\"VALIDATION\",\n\t\t);\n\t}\n\tfor (const id of input.supersededIds) {\n\t\tassertNonEmptyString(id, \"supersededIds[*]\");\n\t}\n}\n\n/**\n * Validate a {@link ListAuditLogInput} and throw a `\"VALIDATION\"`\n * {@link MnemocyteError} when malformed.\n */\nexport function validateListAuditLogInput(input: ListAuditLogInput): void {\n\tassertNonEmptyString(input.entityId, \"entityId\");\n\tif (input.limit !== undefined) {\n\t\tassertLimit(input.limit);\n\t}\n}\n\nexport function matchesRecallFilter(\n\tmemory: Memory,\n\tinput: RecallInput,\n\tnow: Date,\n): boolean {\n\tif (memory.entityId !== input.entityId) {\n\t\treturn false;\n\t}\n\tif (!input.includeSuperseded && memory.supersededBy !== null) {\n\t\treturn false;\n\t}\n\tif (!input.includeExpired && isExpired(memory, now)) {\n\t\treturn false;\n\t}\n\tif (input.types && !input.types.includes(memory.type)) {\n\t\treturn false;\n\t}\n\tif (input.tags && !input.tags.every((tag) => memory.tags.includes(tag))) {\n\t\treturn false;\n\t}\n\tif (input.before && memory.createdAt >= input.before) {\n\t\treturn false;\n\t}\n\tif (input.after && memory.createdAt <= input.after) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n","import { cloneMemory } from \"../memory/shared.js\";\nimport type {\n\tImportanceLevel,\n\tMemory,\n\tMemoryWithScore,\n\tRecallInput,\n\tRetrievalConfig,\n\tRetrievalScoreWeights,\n} from \"../types.js\";\n\nconst IMPORTANCE_SCORES: Record<ImportanceLevel, number> = {\n\tlow: 0,\n\tnormal: 0.5,\n\thigh: 0.8,\n\tcritical: 1,\n};\n\nconst DEFAULT_WEIGHTS: Required<RetrievalScoreWeights> = {\n\tvector: 0.55,\n\tlexical: 0.2,\n\trecency: 0.1,\n\tconfidence: 0.05,\n\taccess: 0.05,\n\timportance: 0.05,\n};\n\nconst DEFAULT_RECENCY_HALF_LIFE_DAYS = 90;\nconst DEFAULT_ACCESS_SATURATION = 10;\nexport const DEFAULT_CANDIDATE_MULTIPLIER = 3;\n\nexport function cosineSimilarity(\n\ta: readonly number[],\n\tb: readonly number[],\n): number {\n\tlet dot = 0;\n\tlet aMagnitude = 0;\n\tlet bMagnitude = 0;\n\tfor (let i = 0; i < a.length; i += 1) {\n\t\tconst av = a[i] ?? 0;\n\t\tconst bv = b[i] ?? 0;\n\t\tdot += av * bv;\n\t\taMagnitude += av * av;\n\t\tbMagnitude += bv * bv;\n\t}\n\tif (aMagnitude === 0 || bMagnitude === 0) {\n\t\treturn 0;\n\t}\n\treturn dot / (Math.sqrt(aMagnitude) * Math.sqrt(bMagnitude));\n}\n\nexport function lexicalScore(content: string, query: string): number {\n\tconst terms = query.toLowerCase().split(/\\s+/).filter(Boolean);\n\tif (terms.length === 0) {\n\t\treturn 0;\n\t}\n\tconst lowerContent = content.toLowerCase();\n\tconst matches = terms.filter((term) => lowerContent.includes(term)).length;\n\treturn matches / terms.length;\n}\n\nfunction clampScore(value: number): number {\n\tif (!Number.isFinite(value)) {\n\t\treturn 0;\n\t}\n\treturn Math.max(0, Math.min(1, value));\n}\n\nfunction normalizeWeights(\n\tweights: RetrievalScoreWeights | undefined,\n): Required<RetrievalScoreWeights> {\n\tconst merged = { ...DEFAULT_WEIGHTS, ...weights };\n\tconst total =\n\t\tmerged.vector +\n\t\tmerged.lexical +\n\t\tmerged.recency +\n\t\tmerged.confidence +\n\t\tmerged.access +\n\t\tmerged.importance;\n\tif (total <= 0) {\n\t\treturn DEFAULT_WEIGHTS;\n\t}\n\treturn {\n\t\tvector: merged.vector / total,\n\t\tlexical: merged.lexical / total,\n\t\trecency: merged.recency / total,\n\t\tconfidence: merged.confidence / total,\n\t\taccess: merged.access / total,\n\t\timportance: merged.importance / total,\n\t};\n}\n\nfunction recencyScore(createdAt: Date, halfLifeDays: number): number {\n\tconst ageMs = Date.now() - createdAt.getTime();\n\tconst ageDays = Math.max(0, ageMs / 86_400_000);\n\treturn Math.exp((-Math.LN2 * ageDays) / halfLifeDays);\n}\n\nfunction accessScore(accessCount: number, saturation: number): number {\n\tif (accessCount <= 0) {\n\t\treturn 0;\n\t}\n\treturn Math.min(1, Math.log1p(accessCount) / Math.log1p(saturation));\n}\n\nexport function toScoredMemory(\n\tmemory: Memory,\n\tvector: number,\n\tlexical: number,\n\tinput: RecallInput,\n\tconfig?: RetrievalConfig,\n): MemoryWithScore {\n\tconst weights = normalizeWeights(config?.weights);\n\tconst recency = recencyScore(\n\t\tmemory.createdAt,\n\t\tconfig?.recencyHalfLifeDays ?? DEFAULT_RECENCY_HALF_LIFE_DAYS,\n\t);\n\tconst confidence = clampScore(memory.confidence);\n\tconst access = accessScore(\n\t\tmemory.accessCount,\n\t\tconfig?.accessSaturation ?? DEFAULT_ACCESS_SATURATION,\n\t);\n\tconst importance = IMPORTANCE_SCORES[memory.importance];\n\tconst score = Math.max(\n\t\t0,\n\t\tMath.min(\n\t\t\t1,\n\t\t\tclampScore(vector) * weights.vector +\n\t\t\t\tclampScore(lexical) * weights.lexical +\n\t\t\t\trecency * weights.recency +\n\t\t\t\tconfidence * weights.confidence +\n\t\t\t\taccess * weights.access +\n\t\t\t\timportance * weights.importance,\n\t\t),\n\t);\n\treturn {\n\t\t...cloneMemory(memory),\n\t\tscore,\n\t\tscores: {\n\t\t\tvector: clampScore(vector),\n\t\t\tlexical: clampScore(lexical),\n\t\t\trecency,\n\t\t\tconfidence,\n\t\t\taccess,\n\t\t\timportance,\n\t\t},\n\t\texplanation: input.explain\n\t\t\t? {\n\t\t\t\t\tvectorScore: clampScore(vector),\n\t\t\t\t\tlexicalScore: clampScore(lexical),\n\t\t\t\t\trecencyScore: recency,\n\t\t\t\t\tconfidenceScore: confidence,\n\t\t\t\t\taccessScore: access,\n\t\t\t\t\timportanceScore: importance,\n\t\t\t\t\timportanceBoost: importance * weights.importance,\n\t\t\t\t\tweights,\n\t\t\t\t\tfinalScore: score,\n\t\t\t\t}\n\t\t\t: null,\n\t};\n}\n","import { buildContext } from \"../context/builder.js\";\nimport { MnemocyteError } from \"../errors.js\";\nimport { observe } from \"../observability.js\";\nimport {\n\tcosineSimilarity,\n\tlexicalScore,\n\ttoScoredMemory,\n} from \"../retrieval/scorer.js\";\nimport type {\n\tAuditEvent,\n\tConsolidateInput,\n\tConsolidateResult,\n\tDuplicatePair,\n\tEntityStats,\n\tExperimentalMnemocyteClient,\n\tFindDuplicatesInput,\n\tGlobalStats,\n\tListAuditLogInput,\n\tMemory,\n\tMnemocyteClient,\n\tMnemocyteConfig,\n\tPruneInput,\n\tPruneResult,\n\tRememberInput,\n} from \"../types.js\";\nimport {\n\tassertLimit,\n\tassertMinScore,\n\tassertNonEmptyString,\n\tcloneMemory,\n\tcontextInputToRecallInput,\n\tcreateEventId,\n\tcreateId,\n\tDEFAULT_DUPLICATE_LIMIT,\n\tDEFAULT_DUPLICATE_THRESHOLD,\n\tDEFAULT_IMPORTANCE,\n\tDEFAULT_LIMIT,\n\tDEFAULT_MIN_SCORE,\n\tDEFAULT_TYPE,\n\tembedOne,\n\tisExpired,\n\tmatchesDuplicateFilter,\n\tmatchesPruneFilter,\n\tmatchesRecallFilter,\n\tnormalizeTags,\n\ttype StoredMemory,\n\tvalidateConsolidateInput,\n\tvalidateFindDuplicatesInput,\n\tvalidateListAuditLogInput,\n\tvalidatePruneInput,\n\tvalidateRecallInput,\n\tvalidateRememberInput,\n} from \"./shared.js\";\n\nexport function createInMemoryClient(config: MnemocyteConfig): MnemocyteClient {\n\tconst memories = new Map<string, StoredMemory>();\n\tconst auditLog: AuditEvent[] = [];\n\tlet closed = false;\n\n\tfunction assertOpen(): void {\n\t\tif (closed) {\n\t\t\tthrow new MnemocyteError(\"Mnemocyte client is closed.\", \"DB\");\n\t\t}\n\t}\n\n\tfunction recordAudit(\n\t\tentityId: string,\n\t\tdescription: string,\n\t\tmetadata: Record<string, unknown>,\n\t): void {\n\t\tif (config.audit?.enabled !== true) {\n\t\t\treturn;\n\t\t}\n\t\tauditLog.push({\n\t\t\tid: createEventId(),\n\t\t\tentityId,\n\t\t\tdescription,\n\t\t\tmetadata,\n\t\t\ttimestamp: new Date(),\n\t\t});\n\t}\n\n\tfunction cloneAuditEvent(event: AuditEvent): AuditEvent {\n\t\treturn {\n\t\t\tid: event.id,\n\t\t\tentityId: event.entityId,\n\t\t\tdescription: event.description,\n\t\t\tmetadata: { ...event.metadata },\n\t\t\ttimestamp: new Date(event.timestamp),\n\t\t};\n\t}\n\n\tasync function remember(input: RememberInput): Promise<Memory> {\n\t\treturn observe(\n\t\t\tconfig,\n\t\t\t\"in-memory\",\n\t\t\t\"remember\",\n\t\t\t{ entityId: input.entityId },\n\t\t\tasync () => {\n\t\t\t\tassertOpen();\n\t\t\t\tvalidateRememberInput(input);\n\t\t\t\tconst embedding = await embedOne(config.embedder, input.content, {\n\t\t\t\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t\t\t\t...(config.provider === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { resilience: config.provider }),\n\t\t\t\t});\n\t\t\t\tconst now = new Date();\n\t\t\t\tconst memory: StoredMemory = {\n\t\t\t\t\tid: createId(),\n\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\tcontent: input.content,\n\t\t\t\t\ttype: input.type ?? DEFAULT_TYPE,\n\t\t\t\t\timportance: input.importance ?? DEFAULT_IMPORTANCE,\n\t\t\t\t\ttags: normalizeTags(input.tags),\n\t\t\t\t\tsource: input.source ?? null,\n\t\t\t\t\tmetadata: input.metadata ?? {},\n\t\t\t\t\tconfidence: input.confidence ?? 1,\n\t\t\t\t\tembeddingModel: config.embedder.model,\n\t\t\t\t\tembeddingDimensions: config.embedder.dimensions,\n\t\t\t\t\tsupersededBy: null,\n\t\t\t\t\tsupersededAt: null,\n\t\t\t\t\texpiresAt: input.expiresAt ?? null,\n\t\t\t\t\tlastAccessedAt: null,\n\t\t\t\t\taccessCount: 0,\n\t\t\t\t\tcreatedAt: now,\n\t\t\t\t\tupdatedAt: now,\n\t\t\t\t\tembedding,\n\t\t\t\t};\n\t\t\t\tmemories.set(memory.id, memory);\n\t\t\t\trecordAudit(memory.entityId, \"memory.created\", {\n\t\t\t\t\tmemoryId: memory.id,\n\t\t\t\t\ttype: memory.type,\n\t\t\t\t\timportance: memory.importance,\n\t\t\t\t});\n\t\t\t\treturn cloneMemory(memory);\n\t\t\t},\n\t\t\t(memory) => ({ memoryId: memory.id, count: 1 }),\n\t\t);\n\t}\n\n\treturn {\n\t\tremember,\n\t\tasync rememberMany(inputs) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"rememberMany\",\n\t\t\t\t{ count: inputs.length },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tconst result: Memory[] = [];\n\t\t\t\t\tfor (const input of inputs) {\n\t\t\t\t\t\tresult.push(await remember(input));\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync recall(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"recall\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateRecallInput(input);\n\t\t\t\t\tconst limit = input.limit ?? config.defaults?.limit ?? DEFAULT_LIMIT;\n\t\t\t\t\tconst minScore =\n\t\t\t\t\t\tinput.minScore ?? config.defaults?.minScore ?? DEFAULT_MIN_SCORE;\n\t\t\t\t\tassertLimit(limit);\n\t\t\t\t\tassertMinScore(minScore);\n\t\t\t\t\tconst queryEmbedding = await embedOne(config.embedder, input.query, {\n\t\t\t\t\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t\t\t\t\t...(config.provider === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { resilience: config.provider }),\n\t\t\t\t\t});\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tconst scored = Array.from(memories.values())\n\t\t\t\t\t\t.filter((memory) => matchesRecallFilter(memory, input, now))\n\t\t\t\t\t\t.map((memory) =>\n\t\t\t\t\t\t\ttoScoredMemory(\n\t\t\t\t\t\t\t\tmemory,\n\t\t\t\t\t\t\t\tMath.max(0, cosineSimilarity(memory.embedding, queryEmbedding)),\n\t\t\t\t\t\t\t\tlexicalScore(memory.content, input.query),\n\t\t\t\t\t\t\t\tinput,\n\t\t\t\t\t\t\t\tconfig.retrieval,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.filter((memory) => memory.score >= minScore)\n\t\t\t\t\t\t.sort((a, b) => b.score - a.score)\n\t\t\t\t\t\t.slice(0, limit);\n\t\t\t\t\tfor (const memory of scored) {\n\t\t\t\t\t\tconst stored = memories.get(memory.id);\n\t\t\t\t\t\tif (stored) {\n\t\t\t\t\t\t\tstored.lastAccessedAt = now;\n\t\t\t\t\t\t\tstored.accessCount += 1;\n\t\t\t\t\t\t\tstored.updatedAt = now;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn scored;\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync buildContext(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"buildContext\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\treturn buildContext({\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\trecall: (contextInput) => {\n\t\t\t\t\t\t\tconst recallInput = contextInputToRecallInput(contextInput);\n\t\t\t\t\t\t\treturn this.recall(\n\t\t\t\t\t\t\t\tinput.signal === undefined\n\t\t\t\t\t\t\t\t\t? recallInput\n\t\t\t\t\t\t\t\t\t: { ...recallInput, signal: input.signal },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\tasync forget(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"forget\",\n\t\t\t\t{ entityId: input.entityId, memoryId: input.memoryId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t\t\t\t\tassertNonEmptyString(input.memoryId, \"memoryId\");\n\t\t\t\t\tconst memory = memories.get(input.memoryId);\n\t\t\t\t\tif (!memory || memory.entityId !== input.entityId) {\n\t\t\t\t\t\tthrow new MnemocyteError(\"Memory was not found.\", \"NOT_FOUND\");\n\t\t\t\t\t}\n\t\t\t\t\tmemories.delete(input.memoryId);\n\t\t\t\t\trecordAudit(memory.entityId, \"memory.deleted\", {\n\t\t\t\t\t\tmemoryId: memory.id,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\tasync forgetAll(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"forgetAll\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t\t\t\t\tlet deleted = 0;\n\t\t\t\t\tfor (const [id, memory] of memories) {\n\t\t\t\t\t\tif (memory.entityId === input.entityId) {\n\t\t\t\t\t\t\tmemories.delete(id);\n\t\t\t\t\t\t\tdeleted += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\trecordAudit(input.entityId, \"entity.cleared\", { count: deleted });\n\t\t\t\t\treturn deleted;\n\t\t\t\t},\n\t\t\t\t(count) => ({ count }),\n\t\t\t).then(() => undefined);\n\t\t},\n\t\tasync prune(input: PruneInput): Promise<PruneResult> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"prune\",\n\t\t\t\tinput.entityId === undefined ? {} : { entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidatePruneInput(input);\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tconst matched: string[] = [];\n\t\t\t\t\tfor (const memory of memories.values()) {\n\t\t\t\t\t\tif (matchesPruneFilter(memory, input, now)) {\n\t\t\t\t\t\t\tmatched.push(memory.id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst dryRun = input.dryRun === true;\n\t\t\t\t\tif (!dryRun) {\n\t\t\t\t\t\tfor (const id of matched) {\n\t\t\t\t\t\t\tmemories.delete(id);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (matched.length > 0 && input.entityId !== undefined) {\n\t\t\t\t\t\t\trecordAudit(input.entityId, \"memory.pruned\", {\n\t\t\t\t\t\t\t\tcount: matched.length,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tmatchedCount: matched.length,\n\t\t\t\t\t\tdeletedCount: dryRun ? 0 : matched.length,\n\t\t\t\t\t\tdryRun,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.deletedCount }),\n\t\t\t);\n\t\t},\n\t\tasync findDuplicates(input: FindDuplicatesInput): Promise<DuplicatePair[]> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"findDuplicates\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateFindDuplicatesInput(input);\n\t\t\t\t\tconst threshold = input.threshold ?? DEFAULT_DUPLICATE_THRESHOLD;\n\t\t\t\t\tconst limit = input.limit ?? DEFAULT_DUPLICATE_LIMIT;\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tconst candidates = Array.from(memories.values()).filter((memory) =>\n\t\t\t\t\t\tmatchesDuplicateFilter(memory, input, now),\n\t\t\t\t\t);\n\t\t\t\t\tconst pairs: DuplicatePair[] = [];\n\t\t\t\t\tfor (let i = 0; i < candidates.length; i += 1) {\n\t\t\t\t\t\tconst a = candidates[i];\n\t\t\t\t\t\tif (a === undefined) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (let j = i + 1; j < candidates.length; j += 1) {\n\t\t\t\t\t\t\tconst b = candidates[j];\n\t\t\t\t\t\t\tif (b === undefined) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst similarity = Math.max(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tMath.min(1, cosineSimilarity(a.embedding, b.embedding)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (similarity >= threshold) {\n\t\t\t\t\t\t\t\tpairs.push({\n\t\t\t\t\t\t\t\t\ta: cloneMemory(a),\n\t\t\t\t\t\t\t\t\tb: cloneMemory(b),\n\t\t\t\t\t\t\t\t\tsimilarity,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpairs.sort((x, y) => y.similarity - x.similarity);\n\t\t\t\t\treturn pairs.slice(0, limit);\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync listAuditLog(input: ListAuditLogInput): Promise<AuditEvent[]> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"listAuditLog\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateListAuditLogInput(input);\n\t\t\t\t\tconst limit = input.limit ?? 50;\n\t\t\t\t\t// Tag with the insertion index so events sharing a millisecond\n\t\t\t\t\t// timestamp still sort in causal (insertion) order.\n\t\t\t\t\tconst indexed = auditLog.map((event, idx) => ({ event, idx }));\n\t\t\t\t\tconst filtered = indexed\n\t\t\t\t\t\t.filter(({ event }) => {\n\t\t\t\t\t\t\tif (event.entityId !== input.entityId) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tinput.before !== undefined &&\n\t\t\t\t\t\t\t\tevent.timestamp.getTime() >= input.before.getTime()\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tinput.after !== undefined &&\n\t\t\t\t\t\t\t\tevent.timestamp.getTime() <= input.after.getTime()\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.sort((a, b) => {\n\t\t\t\t\t\t\tconst dt =\n\t\t\t\t\t\t\t\tb.event.timestamp.getTime() - a.event.timestamp.getTime();\n\t\t\t\t\t\t\tif (dt !== 0) {\n\t\t\t\t\t\t\t\treturn dt;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn b.idx - a.idx;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.slice(0, limit)\n\t\t\t\t\t\t.map(({ event }) => cloneAuditEvent(event));\n\t\t\t\t\treturn filtered;\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync stats(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"in-memory\",\n\t\t\t\t\"stats\",\n\t\t\t\tinput?.entityId ? { entityId: input.entityId } : {},\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tconst allMemories = Array.from(memories.values());\n\t\t\t\t\tconst selected = input?.entityId\n\t\t\t\t\t\t? allMemories.filter((memory) => memory.entityId === input.entityId)\n\t\t\t\t\t\t: allMemories;\n\t\t\t\t\tconst activeMemoryCount = selected.filter(\n\t\t\t\t\t\t(memory) => !isExpired(memory, now) && memory.supersededBy === null,\n\t\t\t\t\t).length;\n\t\t\t\t\tconst expiredMemoryCount = selected.filter((memory) =>\n\t\t\t\t\t\tisExpired(memory, now),\n\t\t\t\t\t).length;\n\t\t\t\t\tconst supersededMemoryCount = selected.filter(\n\t\t\t\t\t\t(memory) => memory.supersededBy !== null,\n\t\t\t\t\t).length;\n\t\t\t\t\tif (input?.entityId) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\tmemoryCount: selected.length,\n\t\t\t\t\t\t\tactiveMemoryCount,\n\t\t\t\t\t\t\texpiredMemoryCount,\n\t\t\t\t\t\t\tsupersededMemoryCount,\n\t\t\t\t\t\t} satisfies EntityStats;\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tentityCount: new Set(allMemories.map((memory) => memory.entityId))\n\t\t\t\t\t\t\t.size,\n\t\t\t\t\t\tmemoryCount: selected.length,\n\t\t\t\t\t\tactiveMemoryCount,\n\t\t\t\t\t\texpiredMemoryCount,\n\t\t\t\t\t\tsupersededMemoryCount,\n\t\t\t\t\t} satisfies GlobalStats;\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\texperimental: createExperimental(),\n\t\tasync close() {\n\t\t\treturn observe(config, \"in-memory\", \"close\", {}, async () => {\n\t\t\t\tclosed = true;\n\t\t\t\tmemories.clear();\n\t\t\t});\n\t\t},\n\t};\n\n\tfunction createExperimental(): ExperimentalMnemocyteClient {\n\t\treturn {\n\t\t\tasync consolidate(input: ConsolidateInput): Promise<ConsolidateResult> {\n\t\t\t\treturn observe(\n\t\t\t\t\tconfig,\n\t\t\t\t\t\"in-memory\",\n\t\t\t\t\t\"consolidate\",\n\t\t\t\t\t{ entityId: input.entityId, memoryId: input.survivorId },\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\tassertOpen();\n\t\t\t\t\t\tvalidateConsolidateInput(input);\n\t\t\t\t\t\tconst survivor = memories.get(input.survivorId);\n\t\t\t\t\t\tif (!survivor || survivor.entityId !== input.entityId) {\n\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\"Survivor memory was not found.\",\n\t\t\t\t\t\t\t\t\"NOT_FOUND\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (survivor.supersededBy !== null) {\n\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\"Survivor memory is itself superseded.\",\n\t\t\t\t\t\t\t\t\"VALIDATION\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst losers: StoredMemory[] = [];\n\t\t\t\t\t\tfor (const id of input.supersededIds) {\n\t\t\t\t\t\t\tconst memory = memories.get(id);\n\t\t\t\t\t\t\tif (!memory || memory.entityId !== input.entityId) {\n\t\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\t\"Superseded memory was not found.\",\n\t\t\t\t\t\t\t\t\t\"NOT_FOUND\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (memory.supersededBy !== null) {\n\t\t\t\t\t\t\t\t// Idempotent skip: already superseded.\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlosers.push(memory);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst now = new Date();\n\t\t\t\t\t\tconst newSupersededIds: string[] = [];\n\t\t\t\t\t\tfor (const loser of losers) {\n\t\t\t\t\t\t\tloser.supersededBy = survivor.id;\n\t\t\t\t\t\t\tloser.supersededAt = now;\n\t\t\t\t\t\t\tloser.updatedAt = now;\n\t\t\t\t\t\t\tnewSupersededIds.push(loser.id);\n\t\t\t\t\t\t\trecordAudit(input.entityId, \"memory.superseded\", {\n\t\t\t\t\t\t\t\tmemoryId: loser.id,\n\t\t\t\t\t\t\t\tsupersededBy: survivor.id,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst shouldMergeTags =\n\t\t\t\t\t\t\tinput.mergeTags !== false && losers.length > 0;\n\t\t\t\t\t\tif (shouldMergeTags) {\n\t\t\t\t\t\t\tconst mergedTags = new Set(survivor.tags);\n\t\t\t\t\t\t\tfor (const loser of losers) {\n\t\t\t\t\t\t\t\tfor (const tag of loser.tags) {\n\t\t\t\t\t\t\t\t\tmergedTags.add(tag);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (mergedTags.size !== survivor.tags.length) {\n\t\t\t\t\t\t\t\tsurvivor.tags = [...mergedTags];\n\t\t\t\t\t\t\t\tsurvivor.updatedAt = now;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsurvivorId: survivor.id,\n\t\t\t\t\t\t\tsupersededCount: newSupersededIds.length,\n\t\t\t\t\t\t\tsupersededIds: newSupersededIds,\n\t\t\t\t\t\t} satisfies ConsolidateResult;\n\t\t\t\t\t},\n\t\t\t\t\t(result) => ({ count: result.supersededCount }),\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t}\n}\n","import { and, desc, eq, gt, lt } from \"drizzle-orm\";\nimport type { MnemocyteDatabase } from \"../index.js\";\nimport { type EventRow, eventsTable, type NewEventRow } from \"../schema.js\";\n\nexport interface EventFilter {\n\tentityId: string;\n\tlimit?: number;\n\tbefore?: Date;\n\tafter?: Date;\n}\n\nexport async function insertEvent(\n\tdb: MnemocyteDatabase,\n\trow: NewEventRow,\n): Promise<EventRow> {\n\tconst result = await db.insert(eventsTable).values(row).returning();\n\tconst inserted = result[0];\n\tif (!inserted) {\n\t\tthrow new Error(\"Event insert returned no rows.\");\n\t}\n\treturn inserted;\n}\n\nexport async function listEvents(\n\tdb: MnemocyteDatabase,\n\tfilter: EventFilter,\n): Promise<EventRow[]> {\n\treturn db\n\t\t.select()\n\t\t.from(eventsTable)\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(eventsTable.entityId, filter.entityId),\n\t\t\t\tfilter.before ? lt(eventsTable.timestamp, filter.before) : undefined,\n\t\t\t\tfilter.after ? gt(eventsTable.timestamp, filter.after) : undefined,\n\t\t\t),\n\t\t)\n\t\t.orderBy(desc(eventsTable.timestamp))\n\t\t.limit(filter.limit ?? 50);\n}\n\nexport async function deleteEventsForEntity(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n): Promise<number> {\n\tconst result = await db\n\t\t.delete(eventsTable)\n\t\t.where(eq(eventsTable.entityId, entityId))\n\t\t.returning({ id: eventsTable.id });\n\treturn result.length;\n}\n","import {\n\tand,\n\teq,\n\tgt,\n\tinArray,\n\tisNotNull,\n\tisNull,\n\tlt,\n\tor,\n\tsql,\n} from \"drizzle-orm\";\nimport type { ImportanceLevel, MemoryType } from \"../../types.js\";\nimport type { MnemocyteDatabase } from \"../index.js\";\nimport { type MemoryRow, memoriesTable, type NewMemoryRow } from \"../schema.js\";\n\nexport interface MemoryFilter {\n\tentityId: string;\n\ttypes?: readonly MemoryType[];\n\ttags?: readonly string[];\n\tbefore?: Date;\n\tafter?: Date;\n\tincludeSuperseded?: boolean;\n\tincludeExpired?: boolean;\n}\n\nexport interface VectorSearchInput extends MemoryFilter {\n\tembedding: readonly number[];\n\tlimit: number;\n\tminScore?: number;\n}\n\nexport interface LexicalSearchInput extends MemoryFilter {\n\tquery: string;\n\tlimit: number;\n}\n\nfunction vectorLiteral(embedding: readonly number[]): string {\n\treturn `[${embedding.map(formatVectorComponent).join(\",\")}]`;\n}\n\nfunction formatVectorComponent(value: number): string {\n\tif (!Number.isFinite(value)) {\n\t\tthrow new Error(\"Vector values must be finite numbers.\");\n\t}\n\treturn Object.is(value, -0) ? \"0\" : value.toFixed(17);\n}\n\nfunction filterConditions(filter: MemoryFilter) {\n\treturn and(\n\t\teq(memoriesTable.entityId, filter.entityId),\n\t\tfilter.includeSuperseded ? undefined : isNull(memoriesTable.supersededBy),\n\t\tfilter.includeExpired\n\t\t\t? undefined\n\t\t\t: sql`(${memoriesTable.expiresAt} IS NULL OR ${memoriesTable.expiresAt} > now())`,\n\t\tfilter.types && filter.types.length > 0\n\t\t\t? inArray(memoriesTable.type, [...filter.types])\n\t\t\t: undefined,\n\t\tfilter.tags && filter.tags.length > 0\n\t\t\t? sql`${memoriesTable.tags} @> ${filter.tags}`\n\t\t\t: undefined,\n\t\tfilter.before ? lt(memoriesTable.createdAt, filter.before) : undefined,\n\t\tfilter.after ? gt(memoriesTable.createdAt, filter.after) : undefined,\n\t);\n}\n\nexport async function insertMemory(\n\tdb: MnemocyteDatabase,\n\trow: NewMemoryRow,\n): Promise<MemoryRow> {\n\tconst result = await db.insert(memoriesTable).values(row).returning();\n\tconst inserted = result[0];\n\tif (!inserted) {\n\t\tthrow new Error(\"Memory insert returned no rows.\");\n\t}\n\treturn inserted;\n}\n\nexport async function getMemoryById(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n\tmemoryId: string,\n): Promise<MemoryRow | null> {\n\tconst result = await db\n\t\t.select()\n\t\t.from(memoriesTable)\n\t\t.where(\n\t\t\tand(eq(memoriesTable.entityId, entityId), eq(memoriesTable.id, memoryId)),\n\t\t)\n\t\t.limit(1);\n\treturn result[0] ?? null;\n}\n\nexport async function listMemories(\n\tdb: MnemocyteDatabase,\n\tfilter: MemoryFilter,\n): Promise<MemoryRow[]> {\n\treturn db.select().from(memoriesTable).where(filterConditions(filter));\n}\n\nexport async function deleteMemory(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n\tmemoryId: string,\n): Promise<boolean> {\n\tconst result = await db\n\t\t.delete(memoriesTable)\n\t\t.where(\n\t\t\tand(eq(memoriesTable.entityId, entityId), eq(memoriesTable.id, memoryId)),\n\t\t)\n\t\t.returning({ id: memoriesTable.id });\n\treturn result.length > 0;\n}\n\nexport async function deleteMemoriesForEntity(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n): Promise<number> {\n\tconst result = await db\n\t\t.delete(memoriesTable)\n\t\t.where(eq(memoriesTable.entityId, entityId))\n\t\t.returning({ id: memoriesTable.id });\n\treturn result.length;\n}\n\nexport interface PruneFilter {\n\tentityId?: string;\n\texpired?: boolean;\n\tsuperseded?: boolean;\n\tcreatedBefore?: Date;\n\tnotAccessedSince?: Date;\n\ttypes?: readonly MemoryType[];\n\ttags?: readonly string[];\n\tmaxImportanceLevels?: readonly ImportanceLevel[];\n}\n\nfunction pruneConditions(filter: PruneFilter) {\n\treturn and(\n\t\tfilter.entityId !== undefined\n\t\t\t? eq(memoriesTable.entityId, filter.entityId)\n\t\t\t: undefined,\n\t\tfilter.expired\n\t\t\t? and(\n\t\t\t\t\tisNotNull(memoriesTable.expiresAt),\n\t\t\t\t\tsql`${memoriesTable.expiresAt} <= now()`,\n\t\t\t\t)\n\t\t\t: undefined,\n\t\tfilter.superseded ? isNotNull(memoriesTable.supersededBy) : undefined,\n\t\tfilter.createdBefore\n\t\t\t? lt(memoriesTable.createdAt, filter.createdBefore)\n\t\t\t: undefined,\n\t\tfilter.notAccessedSince\n\t\t\t? or(\n\t\t\t\t\tisNull(memoriesTable.lastAccessedAt),\n\t\t\t\t\tlt(memoriesTable.lastAccessedAt, filter.notAccessedSince),\n\t\t\t\t)\n\t\t\t: undefined,\n\t\tfilter.types && filter.types.length > 0\n\t\t\t? inArray(memoriesTable.type, [...filter.types])\n\t\t\t: undefined,\n\t\tfilter.tags && filter.tags.length > 0\n\t\t\t? sql`${memoriesTable.tags} @> ${filter.tags}`\n\t\t\t: undefined,\n\t\tfilter.maxImportanceLevels && filter.maxImportanceLevels.length > 0\n\t\t\t? inArray(memoriesTable.importance, [...filter.maxImportanceLevels])\n\t\t\t: undefined,\n\t);\n}\n\nexport async function countPruneMatches(\n\tdb: MnemocyteDatabase,\n\tfilter: PruneFilter,\n): Promise<number> {\n\tconst result = await db\n\t\t.select({ count: sql<number>`count(*)::int` })\n\t\t.from(memoriesTable)\n\t\t.where(pruneConditions(filter));\n\treturn result[0]?.count ?? 0;\n}\n\nexport async function pruneMemories(\n\tdb: MnemocyteDatabase,\n\tfilter: PruneFilter,\n): Promise<number> {\n\tconst result = await db\n\t\t.delete(memoriesTable)\n\t\t.where(pruneConditions(filter))\n\t\t.returning({ id: memoriesTable.id });\n\treturn result.length;\n}\n\nexport interface DuplicateSearchInput {\n\tentityId: string;\n\tthreshold: number;\n\tlimit: number;\n\ttypes?: readonly string[];\n\ttags?: readonly string[];\n\tincludeSuperseded?: boolean;\n\tincludeExpired?: boolean;\n}\n\nexport async function findDuplicatePairs(\n\tdb: MnemocyteDatabase,\n\tinput: DuplicateSearchInput,\n): Promise<Array<{ a: MemoryRow; b: MemoryRow; similarity: number }>> {\n\tconst rows = await db.execute(sql`\n\t\tSELECT\n\t\t\ta.id AS \"aId\",\n\t\t\ta.entity_id AS \"aEntityId\",\n\t\t\ta.content AS \"aContent\",\n\t\t\ta.type AS \"aType\",\n\t\t\ta.importance AS \"aImportance\",\n\t\t\ta.tags AS \"aTags\",\n\t\t\ta.source AS \"aSource\",\n\t\t\ta.metadata AS \"aMetadata\",\n\t\t\ta.confidence AS \"aConfidence\",\n\t\t\ta.embedding AS \"aEmbedding\",\n\t\t\ta.embedding_model AS \"aEmbeddingModel\",\n\t\t\ta.embedding_dimensions AS \"aEmbeddingDimensions\",\n\t\t\ta.superseded_by AS \"aSupersededBy\",\n\t\t\ta.superseded_at AS \"aSupersededAt\",\n\t\t\ta.expires_at AS \"aExpiresAt\",\n\t\t\ta.last_accessed_at AS \"aLastAccessedAt\",\n\t\t\ta.access_count AS \"aAccessCount\",\n\t\t\ta.created_at AS \"aCreatedAt\",\n\t\t\ta.updated_at AS \"aUpdatedAt\",\n\t\t\tb.id AS \"bId\",\n\t\t\tb.entity_id AS \"bEntityId\",\n\t\t\tb.content AS \"bContent\",\n\t\t\tb.type AS \"bType\",\n\t\t\tb.importance AS \"bImportance\",\n\t\t\tb.tags AS \"bTags\",\n\t\t\tb.source AS \"bSource\",\n\t\t\tb.metadata AS \"bMetadata\",\n\t\t\tb.confidence AS \"bConfidence\",\n\t\t\tb.embedding AS \"bEmbedding\",\n\t\t\tb.embedding_model AS \"bEmbeddingModel\",\n\t\t\tb.embedding_dimensions AS \"bEmbeddingDimensions\",\n\t\t\tb.superseded_by AS \"bSupersededBy\",\n\t\t\tb.superseded_at AS \"bSupersededAt\",\n\t\t\tb.expires_at AS \"bExpiresAt\",\n\t\t\tb.last_accessed_at AS \"bLastAccessedAt\",\n\t\t\tb.access_count AS \"bAccessCount\",\n\t\t\tb.created_at AS \"bCreatedAt\",\n\t\t\tb.updated_at AS \"bUpdatedAt\",\n\t\t\t1 - (a.embedding <=> b.embedding) AS \"similarity\"\n\t\tFROM mnemocyte_memories a\n\t\tJOIN mnemocyte_memories b\n\t\t\tON b.entity_id = a.entity_id\n\t\t\tAND a.id < b.id\n\t\t\tAND a.embedding IS NOT NULL\n\t\t\tAND b.embedding IS NOT NULL\n\t\tWHERE\n\t\t\ta.entity_id = ${input.entityId}\n\t\t\t${input.includeSuperseded ? sql`` : sql`AND a.superseded_by IS NULL AND b.superseded_by IS NULL`}\n\t\t\t${input.includeExpired ? sql`` : sql`AND (a.expires_at IS NULL OR a.expires_at > now()) AND (b.expires_at IS NULL OR b.expires_at > now())`}\n\t\t\t${\n\t\t\t\tinput.types && input.types.length > 0\n\t\t\t\t\t? sql`AND a.type IN (${sql.join(\n\t\t\t\t\t\t\tinput.types.map((type) => sql`${type}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)}) AND b.type IN (${sql.join(\n\t\t\t\t\t\t\tinput.types.map((type) => sql`${type}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)})`\n\t\t\t\t\t: sql``\n\t\t\t}\n\t\t\t${\n\t\t\t\tinput.tags && input.tags.length > 0\n\t\t\t\t\t? sql`AND a.tags @> ${input.tags} AND b.tags @> ${input.tags}`\n\t\t\t\t\t: sql``\n\t\t\t}\n\t\t\tAND 1 - (a.embedding <=> b.embedding) >= ${input.threshold}\n\t\tORDER BY \"similarity\" DESC\n\t\tLIMIT ${input.limit}\n\t`);\n\tconst records = rows as unknown as Array<Record<string, unknown>>;\n\treturn records.map((row) => {\n\t\tconst a = {\n\t\t\tid: row.aId,\n\t\t\tentityId: row.aEntityId,\n\t\t\tcontent: row.aContent,\n\t\t\ttype: row.aType,\n\t\t\timportance: row.aImportance,\n\t\t\ttags: row.aTags,\n\t\t\tsource: row.aSource,\n\t\t\tmetadata: row.aMetadata,\n\t\t\tconfidence: row.aConfidence,\n\t\t\tembedding: row.aEmbedding,\n\t\t\tembeddingModel: row.aEmbeddingModel,\n\t\t\tembeddingDimensions: row.aEmbeddingDimensions,\n\t\t\tsupersededBy: row.aSupersededBy,\n\t\t\tsupersededAt: row.aSupersededAt,\n\t\t\texpiresAt: row.aExpiresAt,\n\t\t\tlastAccessedAt: row.aLastAccessedAt,\n\t\t\taccessCount: row.aAccessCount,\n\t\t\tcreatedAt: row.aCreatedAt,\n\t\t\tupdatedAt: row.aUpdatedAt,\n\t\t} as unknown as MemoryRow;\n\t\tconst b = {\n\t\t\tid: row.bId,\n\t\t\tentityId: row.bEntityId,\n\t\t\tcontent: row.bContent,\n\t\t\ttype: row.bType,\n\t\t\timportance: row.bImportance,\n\t\t\ttags: row.bTags,\n\t\t\tsource: row.bSource,\n\t\t\tmetadata: row.bMetadata,\n\t\t\tconfidence: row.bConfidence,\n\t\t\tembedding: row.bEmbedding,\n\t\t\tembeddingModel: row.bEmbeddingModel,\n\t\t\tembeddingDimensions: row.bEmbeddingDimensions,\n\t\t\tsupersededBy: row.bSupersededBy,\n\t\t\tsupersededAt: row.bSupersededAt,\n\t\t\texpiresAt: row.bExpiresAt,\n\t\t\tlastAccessedAt: row.bLastAccessedAt,\n\t\t\taccessCount: row.bAccessCount,\n\t\t\tcreatedAt: row.bCreatedAt,\n\t\t\tupdatedAt: row.bUpdatedAt,\n\t\t} as unknown as MemoryRow;\n\t\treturn {\n\t\t\ta,\n\t\t\tb,\n\t\t\tsimilarity: Number(row.similarity) || 0,\n\t\t};\n\t});\n}\n\nexport interface SupersedeRow {\n\tid: string;\n\ttags: string[];\n}\n\nexport async function loadConsolidationTargets(\n\tdb: MnemocyteDatabase,\n\tentityId: string,\n\tids: readonly string[],\n): Promise<Array<{ id: string; tags: string[]; supersededBy: string | null }>> {\n\tif (ids.length === 0) {\n\t\treturn [];\n\t}\n\tconst rows = await db\n\t\t.select({\n\t\t\tid: memoriesTable.id,\n\t\t\ttags: memoriesTable.tags,\n\t\t\tsupersededBy: memoriesTable.supersededBy,\n\t\t})\n\t\t.from(memoriesTable)\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(memoriesTable.entityId, entityId),\n\t\t\t\tinArray(memoriesTable.id, [...ids]),\n\t\t\t),\n\t\t);\n\treturn rows;\n}\n\nexport async function markMemoriesSuperseded(\n\tdb: MnemocyteDatabase,\n\tparams: {\n\t\tsurvivorId: string;\n\t\tentityId: string;\n\t\tids: readonly string[];\n\t\tnow: Date;\n\t},\n): Promise<SupersedeRow[]> {\n\tif (params.ids.length === 0) {\n\t\treturn [];\n\t}\n\tconst result = await db\n\t\t.update(memoriesTable)\n\t\t.set({\n\t\t\tsupersededBy: params.survivorId,\n\t\t\tsupersededAt: params.now,\n\t\t\tupdatedAt: params.now,\n\t\t})\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(memoriesTable.entityId, params.entityId),\n\t\t\t\tinArray(memoriesTable.id, [...params.ids]),\n\t\t\t\tisNull(memoriesTable.supersededBy),\n\t\t\t),\n\t\t)\n\t\t.returning({ id: memoriesTable.id, tags: memoriesTable.tags });\n\treturn result;\n}\n\nexport async function setMemoryTags(\n\tdb: MnemocyteDatabase,\n\tparams: {\n\t\tentityId: string;\n\t\tmemoryId: string;\n\t\ttags: readonly string[];\n\t\tnow: Date;\n\t},\n): Promise<void> {\n\tawait db\n\t\t.update(memoriesTable)\n\t\t.set({ tags: [...params.tags], updatedAt: params.now })\n\t\t.where(\n\t\t\tand(\n\t\t\t\teq(memoriesTable.entityId, params.entityId),\n\t\t\t\teq(memoriesTable.id, params.memoryId),\n\t\t\t),\n\t\t);\n}\n\nexport async function markMemoryAccessed(\n\tdb: MnemocyteDatabase,\n\tmemoryIds: readonly string[],\n): Promise<void> {\n\tif (memoryIds.length === 0) {\n\t\treturn;\n\t}\n\tawait db\n\t\t.update(memoriesTable)\n\t\t.set({\n\t\t\tlastAccessedAt: new Date(),\n\t\t\taccessCount: sql`${memoriesTable.accessCount} + 1`,\n\t\t\tupdatedAt: new Date(),\n\t\t})\n\t\t.where(inArray(memoriesTable.id, [...memoryIds]));\n}\n\nexport async function vectorSearch(\n\tdb: MnemocyteDatabase,\n\tinput: VectorSearchInput,\n): Promise<Array<MemoryRow & { vectorScore: number }>> {\n\tconst embedding = vectorLiteral(input.embedding);\n\tconst minScore = input.minScore ?? 0;\n\tconst rows = await db.execute(sql`\n\t\tSELECT\n\t\t\tid,\n\t\t\tentity_id AS \"entityId\",\n\t\t\tcontent,\n\t\t\ttype,\n\t\t\timportance,\n\t\t\ttags,\n\t\t\tsource,\n\t\t\tmetadata,\n\t\t\tconfidence,\n\t\t\tembedding,\n\t\t\tembedding_model AS \"embeddingModel\",\n\t\t\tembedding_dimensions AS \"embeddingDimensions\",\n\t\t\tsuperseded_by AS \"supersededBy\",\n\t\t\tsuperseded_at AS \"supersededAt\",\n\t\t\texpires_at AS \"expiresAt\",\n\t\t\tlast_accessed_at AS \"lastAccessedAt\",\n\t\t\taccess_count AS \"accessCount\",\n\t\t\tcreated_at AS \"createdAt\",\n\t\t\tupdated_at AS \"updatedAt\",\n\t\t\t1 - (embedding <=> ${embedding}::vector) AS \"vectorScore\"\n\t\tFROM mnemocyte_memories\n\t\tWHERE\n\t\t\tentity_id = ${input.entityId}\n\t\t\tAND embedding IS NOT NULL\n\t\t\t${input.includeSuperseded ? sql`` : sql`AND superseded_by IS NULL`}\n\t\t\t${input.includeExpired ? sql`` : sql`AND (expires_at IS NULL OR expires_at > now())`}\n\t\t\t${\n\t\t\t\tinput.types && input.types.length > 0\n\t\t\t\t\t? sql`AND type IN (${sql.join(\n\t\t\t\t\t\t\tinput.types.map((type) => sql`${type}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)})`\n\t\t\t\t\t: sql``\n\t\t\t}\n\t\t\t${input.tags && input.tags.length > 0 ? sql`AND tags @> ${input.tags}` : sql``}\n\t\t\t${input.before ? sql`AND created_at < ${input.before}` : sql``}\n\t\t\t${input.after ? sql`AND created_at > ${input.after}` : sql``}\n\t\t\tAND 1 - (embedding <=> ${embedding}::vector) >= ${minScore}\n\t\tORDER BY embedding <=> ${embedding}::vector\n\t\tLIMIT ${input.limit}\n\t`);\n\treturn rows as unknown as Array<MemoryRow & { vectorScore: number }>;\n}\n\nexport async function lexicalSearch(\n\tdb: MnemocyteDatabase,\n\tinput: LexicalSearchInput,\n): Promise<Array<MemoryRow & { lexicalScore: number }>> {\n\tconst rows = await db.execute(sql`\n\t\tSELECT\n\t\t\tid,\n\t\t\tentity_id AS \"entityId\",\n\t\t\tcontent,\n\t\t\ttype,\n\t\t\timportance,\n\t\t\ttags,\n\t\t\tsource,\n\t\t\tmetadata,\n\t\t\tconfidence,\n\t\t\tembedding,\n\t\t\tembedding_model AS \"embeddingModel\",\n\t\t\tembedding_dimensions AS \"embeddingDimensions\",\n\t\t\tsuperseded_by AS \"supersededBy\",\n\t\t\tsuperseded_at AS \"supersededAt\",\n\t\t\texpires_at AS \"expiresAt\",\n\t\t\tlast_accessed_at AS \"lastAccessedAt\",\n\t\t\taccess_count AS \"accessCount\",\n\t\t\tcreated_at AS \"createdAt\",\n\t\t\tupdated_at AS \"updatedAt\",\n\t\t\tts_rank(to_tsvector('english', content), websearch_to_tsquery('english', ${input.query})) AS \"lexicalScore\"\n\t\tFROM mnemocyte_memories\n\t\tWHERE\n\t\t\tentity_id = ${input.entityId}\n\t\t\t${input.includeSuperseded ? sql`` : sql`AND superseded_by IS NULL`}\n\t\t\t${input.includeExpired ? sql`` : sql`AND (expires_at IS NULL OR expires_at > now())`}\n\t\t\t${\n\t\t\t\tinput.types && input.types.length > 0\n\t\t\t\t\t? sql`AND type IN (${sql.join(\n\t\t\t\t\t\t\tinput.types.map((type) => sql`${type}`),\n\t\t\t\t\t\t\tsql`, `,\n\t\t\t\t\t\t)})`\n\t\t\t\t\t: sql``\n\t\t\t}\n\t\t\t${input.tags && input.tags.length > 0 ? sql`AND tags @> ${input.tags}` : sql``}\n\t\t\t${input.before ? sql`AND created_at < ${input.before}` : sql``}\n\t\t\t${input.after ? sql`AND created_at > ${input.after}` : sql``}\n\t\t\tAND to_tsvector('english', content) @@ websearch_to_tsquery('english', ${input.query})\n\t\tORDER BY \"lexicalScore\" DESC\n\t\tLIMIT ${input.limit}\n\t`);\n\treturn rows as unknown as Array<MemoryRow & { lexicalScore: number }>;\n}\n","import type { MnemocyteDatabase } from \"../db/index.js\";\nimport {\n\tlexicalSearch,\n\tmarkMemoryAccessed,\n\tvectorSearch,\n} from \"../db/queries/memories.js\";\nimport type { MemoryRow } from \"../db/schema.js\";\nimport { embedOne, rowToMemory } from \"../memory/shared.js\";\nimport type {\n\tEmbedder,\n\tMemoryWithScore,\n\tProviderResilienceConfig,\n\tRecallInput,\n\tRetrievalConfig,\n} from \"../types.js\";\nimport { DEFAULT_CANDIDATE_MULTIPLIER, toScoredMemory } from \"./scorer.js\";\n\ninterface HybridRecallInput {\n\tdb: MnemocyteDatabase;\n\tembedder: Embedder;\n\tinput: RecallInput;\n\tlimit: number;\n\tminScore: number;\n\tretrieval: RetrievalConfig | undefined;\n\tsignal?: AbortSignal;\n\tresilience?: ProviderResilienceConfig;\n}\n\ninterface ScoredRow {\n\trow: MemoryRow;\n\tvectorScore: number;\n\tlexicalScore: number;\n}\n\nexport async function hybridRecall(\n\tinput: HybridRecallInput,\n): Promise<MemoryWithScore[]> {\n\tconst queryEmbedding = await embedOne(input.embedder, input.input.query, {\n\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t...(input.resilience === undefined ? {} : { resilience: input.resilience }),\n\t});\n\tconst candidateMultiplier =\n\t\tinput.retrieval?.candidateMultiplier ?? DEFAULT_CANDIDATE_MULTIPLIER;\n\tconst candidateLimit = Math.max(\n\t\tinput.limit,\n\t\tinput.limit * candidateMultiplier,\n\t);\n\tconst [vectorRows, lexicalRows] = await Promise.all([\n\t\tvectorSearch(input.db, {\n\t\t\t...input.input,\n\t\t\tembedding: queryEmbedding,\n\t\t\tlimit: candidateLimit,\n\t\t\tminScore: 0,\n\t\t}),\n\t\tlexicalSearch(input.db, { ...input.input, limit: candidateLimit }),\n\t]);\n\tconst merged = new Map<string, ScoredRow>();\n\tfor (const row of vectorRows) {\n\t\tmerged.set(row.id, {\n\t\t\trow,\n\t\t\tvectorScore: row.vectorScore,\n\t\t\tlexicalScore: 0,\n\t\t});\n\t}\n\tfor (const row of lexicalRows) {\n\t\tconst existing = merged.get(row.id);\n\t\tif (existing) {\n\t\t\texisting.lexicalScore = row.lexicalScore;\n\t\t} else {\n\t\t\tmerged.set(row.id, {\n\t\t\t\trow,\n\t\t\t\tvectorScore: 0,\n\t\t\t\tlexicalScore: row.lexicalScore,\n\t\t\t});\n\t\t}\n\t}\n\tconst scored = Array.from(merged.values())\n\t\t.map((entry) =>\n\t\t\ttoScoredMemory(\n\t\t\t\trowToMemory(entry.row),\n\t\t\t\tMath.max(0, entry.vectorScore),\n\t\t\t\tMath.max(0, entry.lexicalScore),\n\t\t\t\tinput.input,\n\t\t\t\tinput.retrieval,\n\t\t\t),\n\t\t)\n\t\t.filter((memory) => memory.score >= input.minScore)\n\t\t.sort((a, b) => b.score - a.score)\n\t\t.slice(0, input.limit);\n\tawait markMemoryAccessed(\n\t\tinput.db,\n\t\tscored.map((memory) => memory.id),\n\t);\n\treturn scored;\n}\n","import { buildContext } from \"../context/builder.js\";\nimport type { DatabaseHandle } from \"../db/index.js\";\nimport { insertEvent, listEvents } from \"../db/queries/events.js\";\nimport {\n\tcountPruneMatches,\n\tdeleteMemoriesForEntity,\n\tdeleteMemory,\n\tfindDuplicatePairs,\n\tgetMemoryById,\n\tinsertMemory,\n\tlistMemories,\n\tloadConsolidationTargets,\n\tmarkMemoriesSuperseded,\n\ttype PruneFilter,\n\tpruneMemories,\n\tsetMemoryTags,\n} from \"../db/queries/memories.js\";\nimport { type EventRow, memoriesTable } from \"../db/schema.js\";\nimport { MnemocyteError } from \"../errors.js\";\nimport { observe } from \"../observability.js\";\nimport { hybridRecall } from \"../retrieval/index.js\";\nimport type {\n\tAuditEvent,\n\tConsolidateInput,\n\tConsolidateResult,\n\tDuplicatePair,\n\tEntityStats,\n\tExperimentalMnemocyteClient,\n\tFindDuplicatesInput,\n\tGlobalStats,\n\tImportanceLevel,\n\tListAuditLogInput,\n\tMemory,\n\tMnemocyteClient,\n\tMnemocyteConfig,\n\tPruneInput,\n\tPruneResult,\n\tRememberInput,\n} from \"../types.js\";\nimport {\n\tassertLimit,\n\tassertMinScore,\n\tassertNonEmptyString,\n\tcontextInputToRecallInput,\n\tcreateEventId,\n\tcreateId,\n\tDEFAULT_AUDIT_LOG_LIMIT,\n\tDEFAULT_DUPLICATE_LIMIT,\n\tDEFAULT_DUPLICATE_THRESHOLD,\n\tDEFAULT_IMPORTANCE,\n\tDEFAULT_LIMIT,\n\tDEFAULT_MIN_SCORE,\n\tDEFAULT_TYPE,\n\tembedOne,\n\tIMPORTANCE_RANK,\n\tisExpired,\n\tnormalizeTags,\n\trowToMemory,\n\tvalidateConsolidateInput,\n\tvalidateFindDuplicatesInput,\n\tvalidateListAuditLogInput,\n\tvalidatePruneInput,\n\tvalidateRecallInput,\n\tvalidateRememberInput,\n} from \"./shared.js\";\n\nfunction rowToAuditEvent(row: EventRow): AuditEvent {\n\treturn {\n\t\tid: row.id,\n\t\tentityId: row.entityId,\n\t\tdescription: row.description,\n\t\tmetadata: row.metadata as Record<string, unknown>,\n\t\ttimestamp: row.timestamp,\n\t};\n}\n\nconst IMPORTANCE_LEVELS: readonly ImportanceLevel[] = [\n\t\"low\",\n\t\"normal\",\n\t\"high\",\n\t\"critical\",\n];\n\nfunction importanceCeilingLevels(\n\tmax: ImportanceLevel,\n): readonly ImportanceLevel[] {\n\treturn IMPORTANCE_LEVELS.filter(\n\t\t(level) => IMPORTANCE_RANK[level] <= IMPORTANCE_RANK[max],\n\t);\n}\n\nfunction toPruneFilter(input: PruneInput): PruneFilter {\n\tconst filter: PruneFilter = {};\n\tif (input.entityId !== undefined) {\n\t\tfilter.entityId = input.entityId;\n\t}\n\tif (input.expired === true) {\n\t\tfilter.expired = true;\n\t}\n\tif (input.superseded === true) {\n\t\tfilter.superseded = true;\n\t}\n\tif (input.createdBefore !== undefined) {\n\t\tfilter.createdBefore = input.createdBefore;\n\t}\n\tif (input.notAccessedSince !== undefined) {\n\t\tfilter.notAccessedSince = input.notAccessedSince;\n\t}\n\tif (input.types !== undefined && input.types.length > 0) {\n\t\tfilter.types = input.types;\n\t}\n\tif (input.tags !== undefined && input.tags.length > 0) {\n\t\tfilter.tags = input.tags;\n\t}\n\tif (input.maxImportance !== undefined) {\n\t\tfilter.maxImportanceLevels = importanceCeilingLevels(input.maxImportance);\n\t}\n\treturn filter;\n}\n\nexport function createPostgresClient(\n\tconfig: MnemocyteConfig,\n\thandle: DatabaseHandle,\n): MnemocyteClient {\n\tlet closed = false;\n\n\tfunction assertOpen(): void {\n\t\tif (closed) {\n\t\t\tthrow new MnemocyteError(\"Mnemocyte client is closed.\", \"DB\");\n\t\t}\n\t}\n\n\tasync function recordAudit(\n\t\tentityId: string,\n\t\tdescription: string,\n\t\tmetadata: Record<string, unknown>,\n\t): Promise<void> {\n\t\tif (config.audit?.enabled !== true) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tawait insertEvent(handle.db, {\n\t\t\t\tid: createEventId(),\n\t\t\t\tentityId,\n\t\t\t\tdescription,\n\t\t\t\tmetadata,\n\t\t\t\ttimestamp: new Date(),\n\t\t\t});\n\t\t} catch {\n\t\t\t// Audit writes must not break the primary operation.\n\t\t}\n\t}\n\n\tasync function remember(input: RememberInput): Promise<Memory> {\n\t\treturn observe(\n\t\t\tconfig,\n\t\t\t\"postgres\",\n\t\t\t\"remember\",\n\t\t\t{ entityId: input.entityId },\n\t\t\tasync () => {\n\t\t\t\tassertOpen();\n\t\t\t\tvalidateRememberInput(input);\n\t\t\t\tconst embedding = await embedOne(config.embedder, input.content, {\n\t\t\t\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t\t\t\t...(config.provider === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { resilience: config.provider }),\n\t\t\t\t});\n\t\t\t\tconst now = new Date();\n\t\t\t\tconst row = await insertMemory(handle.db, {\n\t\t\t\t\tid: createId(),\n\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\tcontent: input.content,\n\t\t\t\t\ttype: input.type ?? DEFAULT_TYPE,\n\t\t\t\t\timportance: input.importance ?? DEFAULT_IMPORTANCE,\n\t\t\t\t\ttags: normalizeTags(input.tags),\n\t\t\t\t\tsource: input.source ?? null,\n\t\t\t\t\tmetadata: input.metadata ?? {},\n\t\t\t\t\tconfidence: input.confidence ?? 1,\n\t\t\t\t\tembedding,\n\t\t\t\t\tembeddingModel: config.embedder.model,\n\t\t\t\t\tembeddingDimensions: config.embedder.dimensions,\n\t\t\t\t\tsupersededBy: null,\n\t\t\t\t\tsupersededAt: null,\n\t\t\t\t\texpiresAt: input.expiresAt ?? null,\n\t\t\t\t\tlastAccessedAt: null,\n\t\t\t\t\taccessCount: 0,\n\t\t\t\t\tcreatedAt: now,\n\t\t\t\t\tupdatedAt: now,\n\t\t\t\t});\n\t\t\t\tconst memory = rowToMemory(row);\n\t\t\t\tawait recordAudit(memory.entityId, \"memory.created\", {\n\t\t\t\t\tmemoryId: memory.id,\n\t\t\t\t\ttype: memory.type,\n\t\t\t\t\timportance: memory.importance,\n\t\t\t\t});\n\t\t\t\treturn memory;\n\t\t\t},\n\t\t\t(memory) => ({ memoryId: memory.id, count: 1 }),\n\t\t);\n\t}\n\n\treturn {\n\t\tremember,\n\t\tasync rememberMany(inputs) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"rememberMany\",\n\t\t\t\t{ count: inputs.length },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tconst result: Memory[] = [];\n\t\t\t\t\tfor (const input of inputs) {\n\t\t\t\t\t\tresult.push(await remember(input));\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync recall(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"recall\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateRecallInput(input);\n\t\t\t\t\tconst limit = input.limit ?? config.defaults?.limit ?? DEFAULT_LIMIT;\n\t\t\t\t\tconst minScore =\n\t\t\t\t\t\tinput.minScore ?? config.defaults?.minScore ?? DEFAULT_MIN_SCORE;\n\t\t\t\t\tassertLimit(limit);\n\t\t\t\t\tassertMinScore(minScore);\n\t\t\t\t\treturn hybridRecall({\n\t\t\t\t\t\tdb: handle.db,\n\t\t\t\t\t\tembedder: config.embedder,\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\tlimit,\n\t\t\t\t\t\tminScore,\n\t\t\t\t\t\tretrieval: config.retrieval,\n\t\t\t\t\t\t...(input.signal === undefined ? {} : { signal: input.signal }),\n\t\t\t\t\t\t...(config.provider === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { resilience: config.provider }),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync buildContext(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"buildContext\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\treturn buildContext({\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\trecall: (contextInput) => {\n\t\t\t\t\t\t\tconst recallInput = contextInputToRecallInput(contextInput);\n\t\t\t\t\t\t\treturn this.recall(\n\t\t\t\t\t\t\t\tinput.signal === undefined\n\t\t\t\t\t\t\t\t\t? recallInput\n\t\t\t\t\t\t\t\t\t: { ...recallInput, signal: input.signal },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\tasync forget(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"forget\",\n\t\t\t\t{ entityId: input.entityId, memoryId: input.memoryId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t\t\t\t\tassertNonEmptyString(input.memoryId, \"memoryId\");\n\t\t\t\t\tconst deleted = await deleteMemory(\n\t\t\t\t\t\thandle.db,\n\t\t\t\t\t\tinput.entityId,\n\t\t\t\t\t\tinput.memoryId,\n\t\t\t\t\t);\n\t\t\t\t\tif (!deleted) {\n\t\t\t\t\t\tthrow new MnemocyteError(\"Memory was not found.\", \"NOT_FOUND\");\n\t\t\t\t\t}\n\t\t\t\t\tawait recordAudit(input.entityId, \"memory.deleted\", {\n\t\t\t\t\t\tmemoryId: input.memoryId,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\tasync forgetAll(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"forgetAll\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tassertNonEmptyString(input.entityId, \"entityId\");\n\t\t\t\t\tconst deletedCount = await deleteMemoriesForEntity(\n\t\t\t\t\t\thandle.db,\n\t\t\t\t\t\tinput.entityId,\n\t\t\t\t\t);\n\t\t\t\t\tawait recordAudit(input.entityId, \"entity.cleared\", {\n\t\t\t\t\t\tcount: deletedCount,\n\t\t\t\t\t});\n\t\t\t\t\treturn deletedCount;\n\t\t\t\t},\n\t\t\t\t(count) => ({ count }),\n\t\t\t).then(() => undefined);\n\t\t},\n\t\tasync prune(input: PruneInput): Promise<PruneResult> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"prune\",\n\t\t\t\tinput.entityId === undefined ? {} : { entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidatePruneInput(input);\n\t\t\t\t\tconst filter = toPruneFilter(input);\n\t\t\t\t\tconst dryRun = input.dryRun === true;\n\t\t\t\t\tif (dryRun) {\n\t\t\t\t\t\tconst matchedCount = await countPruneMatches(handle.db, filter);\n\t\t\t\t\t\treturn { matchedCount, deletedCount: 0, dryRun: true };\n\t\t\t\t\t}\n\t\t\t\t\tconst deletedCount = await pruneMemories(handle.db, filter);\n\t\t\t\t\tif (deletedCount > 0 && input.entityId !== undefined) {\n\t\t\t\t\t\tawait recordAudit(input.entityId, \"memory.pruned\", {\n\t\t\t\t\t\t\tcount: deletedCount,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tmatchedCount: deletedCount,\n\t\t\t\t\t\tdeletedCount,\n\t\t\t\t\t\tdryRun: false,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.deletedCount }),\n\t\t\t);\n\t\t},\n\t\tasync findDuplicates(input: FindDuplicatesInput): Promise<DuplicatePair[]> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"findDuplicates\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateFindDuplicatesInput(input);\n\t\t\t\t\tconst threshold = input.threshold ?? DEFAULT_DUPLICATE_THRESHOLD;\n\t\t\t\t\tconst limit = input.limit ?? DEFAULT_DUPLICATE_LIMIT;\n\t\t\t\t\tconst rows = await findDuplicatePairs(handle.db, {\n\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\tthreshold,\n\t\t\t\t\t\tlimit,\n\t\t\t\t\t\t...(input.types === undefined ? {} : { types: input.types }),\n\t\t\t\t\t\t...(input.tags === undefined ? {} : { tags: input.tags }),\n\t\t\t\t\t\t...(input.includeSuperseded === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { includeSuperseded: input.includeSuperseded }),\n\t\t\t\t\t\t...(input.includeExpired === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { includeExpired: input.includeExpired }),\n\t\t\t\t\t});\n\t\t\t\t\treturn rows.map((row) => ({\n\t\t\t\t\t\ta: rowToMemory(row.a),\n\t\t\t\t\t\tb: rowToMemory(row.b),\n\t\t\t\t\t\tsimilarity: Math.max(0, Math.min(1, row.similarity)),\n\t\t\t\t\t}));\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync listAuditLog(input: ListAuditLogInput): Promise<AuditEvent[]> {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"listAuditLog\",\n\t\t\t\t{ entityId: input.entityId },\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tvalidateListAuditLogInput(input);\n\t\t\t\t\tconst rows = await listEvents(handle.db, {\n\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\tlimit: input.limit ?? DEFAULT_AUDIT_LOG_LIMIT,\n\t\t\t\t\t\t...(input.before === undefined ? {} : { before: input.before }),\n\t\t\t\t\t\t...(input.after === undefined ? {} : { after: input.after }),\n\t\t\t\t\t});\n\t\t\t\t\treturn rows.map(rowToAuditEvent);\n\t\t\t\t},\n\t\t\t\t(result) => ({ count: result.length }),\n\t\t\t);\n\t\t},\n\t\tasync stats(input) {\n\t\t\treturn observe(\n\t\t\t\tconfig,\n\t\t\t\t\"postgres\",\n\t\t\t\t\"stats\",\n\t\t\t\tinput?.entityId ? { entityId: input.entityId } : {},\n\t\t\t\tasync () => {\n\t\t\t\t\tassertOpen();\n\t\t\t\t\tconst now = new Date();\n\t\t\t\t\tif (input?.entityId) {\n\t\t\t\t\t\tconst selected = await listMemories(handle.db, {\n\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\tincludeExpired: true,\n\t\t\t\t\t\t\tincludeSuperseded: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\tmemoryCount: selected.length,\n\t\t\t\t\t\t\tactiveMemoryCount: selected.filter(\n\t\t\t\t\t\t\t\t(memory) =>\n\t\t\t\t\t\t\t\t\t!isExpired(rowToMemory(memory), now) &&\n\t\t\t\t\t\t\t\t\tmemory.supersededBy === null,\n\t\t\t\t\t\t\t).length,\n\t\t\t\t\t\t\texpiredMemoryCount: selected.filter((memory) =>\n\t\t\t\t\t\t\t\tisExpired(rowToMemory(memory), now),\n\t\t\t\t\t\t\t).length,\n\t\t\t\t\t\t\tsupersededMemoryCount: selected.filter(\n\t\t\t\t\t\t\t\t(memory) => memory.supersededBy !== null,\n\t\t\t\t\t\t\t).length,\n\t\t\t\t\t\t} satisfies EntityStats;\n\t\t\t\t\t}\n\t\t\t\t\tconst allMemories = await handle.db.select().from(memoriesTable);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tentityCount: new Set(allMemories.map((memory) => memory.entityId))\n\t\t\t\t\t\t\t.size,\n\t\t\t\t\t\tmemoryCount: allMemories.length,\n\t\t\t\t\t\tactiveMemoryCount: allMemories.filter(\n\t\t\t\t\t\t\t(memory) =>\n\t\t\t\t\t\t\t\t!isExpired(rowToMemory(memory), now) &&\n\t\t\t\t\t\t\t\tmemory.supersededBy === null,\n\t\t\t\t\t\t).length,\n\t\t\t\t\t\texpiredMemoryCount: allMemories.filter((memory) =>\n\t\t\t\t\t\t\tisExpired(rowToMemory(memory), now),\n\t\t\t\t\t\t).length,\n\t\t\t\t\t\tsupersededMemoryCount: allMemories.filter(\n\t\t\t\t\t\t\t(memory) => memory.supersededBy !== null,\n\t\t\t\t\t\t).length,\n\t\t\t\t\t} satisfies GlobalStats;\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\texperimental: createExperimental(),\n\t\tasync close() {\n\t\t\treturn observe(config, \"postgres\", \"close\", {}, async () => {\n\t\t\t\tclosed = true;\n\t\t\t\tawait handle.close();\n\t\t\t});\n\t\t},\n\t};\n\n\tfunction createExperimental(): ExperimentalMnemocyteClient {\n\t\treturn {\n\t\t\tasync consolidate(input: ConsolidateInput): Promise<ConsolidateResult> {\n\t\t\t\treturn observe(\n\t\t\t\t\tconfig,\n\t\t\t\t\t\"postgres\",\n\t\t\t\t\t\"consolidate\",\n\t\t\t\t\t{ entityId: input.entityId, memoryId: input.survivorId },\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\tassertOpen();\n\t\t\t\t\t\tvalidateConsolidateInput(input);\n\t\t\t\t\t\tconst survivor = await getMemoryById(\n\t\t\t\t\t\t\thandle.db,\n\t\t\t\t\t\t\tinput.entityId,\n\t\t\t\t\t\t\tinput.survivorId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!survivor) {\n\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\"Survivor memory was not found.\",\n\t\t\t\t\t\t\t\t\"NOT_FOUND\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (survivor.supersededBy !== null) {\n\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\"Survivor memory is itself superseded.\",\n\t\t\t\t\t\t\t\t\"VALIDATION\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst targets = await loadConsolidationTargets(\n\t\t\t\t\t\t\thandle.db,\n\t\t\t\t\t\t\tinput.entityId,\n\t\t\t\t\t\t\tinput.supersededIds,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst foundIds = new Set(targets.map((t) => t.id));\n\t\t\t\t\t\tfor (const id of input.supersededIds) {\n\t\t\t\t\t\t\tif (!foundIds.has(id)) {\n\t\t\t\t\t\t\t\tthrow new MnemocyteError(\n\t\t\t\t\t\t\t\t\t\"Superseded memory was not found.\",\n\t\t\t\t\t\t\t\t\t\"NOT_FOUND\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst losers = targets.filter(\n\t\t\t\t\t\t\t(target) => target.supersededBy === null,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (losers.length === 0) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tsurvivorId: survivor.id,\n\t\t\t\t\t\t\t\tsupersededCount: 0,\n\t\t\t\t\t\t\t\tsupersededIds: [],\n\t\t\t\t\t\t\t} satisfies ConsolidateResult;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst now = new Date();\n\t\t\t\t\t\tconst updated = await markMemoriesSuperseded(handle.db, {\n\t\t\t\t\t\t\tsurvivorId: survivor.id,\n\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\tids: losers.map((loser) => loser.id),\n\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst newSupersededIds = updated.map((row) => row.id);\n\t\t\t\t\t\tfor (const id of newSupersededIds) {\n\t\t\t\t\t\t\tawait recordAudit(input.entityId, \"memory.superseded\", {\n\t\t\t\t\t\t\t\tmemoryId: id,\n\t\t\t\t\t\t\t\tsupersededBy: survivor.id,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (input.mergeTags !== false && updated.length > 0) {\n\t\t\t\t\t\t\tconst mergedTags = new Set(survivor.tags);\n\t\t\t\t\t\t\tfor (const row of updated) {\n\t\t\t\t\t\t\t\tfor (const tag of row.tags) {\n\t\t\t\t\t\t\t\t\tmergedTags.add(tag);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (mergedTags.size !== survivor.tags.length) {\n\t\t\t\t\t\t\t\tawait setMemoryTags(handle.db, {\n\t\t\t\t\t\t\t\t\tentityId: input.entityId,\n\t\t\t\t\t\t\t\t\tmemoryId: survivor.id,\n\t\t\t\t\t\t\t\t\ttags: [...mergedTags],\n\t\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsurvivorId: survivor.id,\n\t\t\t\t\t\t\tsupersededCount: newSupersededIds.length,\n\t\t\t\t\t\t\tsupersededIds: newSupersededIds,\n\t\t\t\t\t\t} satisfies ConsolidateResult;\n\t\t\t\t\t},\n\t\t\t\t\t(result) => ({ count: result.supersededCount }),\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t}\n}\n","import { createDatabase } from \"./db/index.js\";\nimport { MnemocyteError } from \"./errors.js\";\nimport { createInMemoryClient } from \"./memory/in-memory.js\";\nimport { createPostgresClient } from \"./memory/postgres.js\";\nimport { assertEmbedder, assertNonEmptyString } from \"./memory/shared.js\";\nimport type { MnemocyteClient, MnemocyteConfig } from \"./types.js\";\n\n/** Embedding dimensionality pinned by `migrations/0000_initial.sql`. */\nconst POSTGRES_EMBEDDING_DIMENSIONS = 1536;\n\n/**\n * Create a Mnemocyte client.\n *\n * When {@link MnemocyteConfig.databaseUrl} is provided, a Postgres-backed\n * client is returned (requires the `pgvector` extension and the bundled\n * migration applied). Otherwise an in-memory client is returned, intended\n * for tests, demos, and short-lived processes.\n *\n * The returned client owns any underlying resources (e.g. the Postgres\n * connection pool). Call {@link MnemocyteClient.close} when finished to\n * release them.\n *\n * @param config - Client configuration. {@link MnemocyteConfig.embedder} is required.\n * @returns A {@link MnemocyteClient} instance.\n * @throws {MnemocyteError} With code `\"CONFIG\"` if `embedder` is missing or\n * invalid (including when `databaseUrl` is set and `embedder.dimensions`\n * is not 1536 — the dimensionality pinned by the bundled migration), or\n * `\"VALIDATION\"` if `databaseUrl` is provided but empty.\n *\n * @example Postgres-backed client\n * ```ts\n * const client = createMnemocyte({\n * databaseUrl: process.env.DATABASE_URL,\n * embedder, // embedder.dimensions MUST be 1536 for the Postgres backend\n * });\n * ```\n */\nexport function createMnemocyte(config: MnemocyteConfig): MnemocyteClient {\n\tassertEmbedder(config.embedder);\n\tif (config.databaseUrl) {\n\t\tassertNonEmptyString(config.databaseUrl, \"databaseUrl\");\n\t\tif (config.embedder.dimensions !== POSTGRES_EMBEDDING_DIMENSIONS) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t`embedder.dimensions must be ${POSTGRES_EMBEDDING_DIMENSIONS} for the Postgres backend (got ${config.embedder.dimensions}). The bundled migration pins the vector column to vector(${POSTGRES_EMBEDDING_DIMENSIONS}).`,\n\t\t\t\t\"CONFIG\",\n\t\t\t);\n\t\t}\n\t\treturn createPostgresClient(config, createDatabase(config.databaseUrl));\n\t}\n\treturn createInMemoryClient(config);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnemocyte",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Persistent memory for TypeScript AI apps.",
5
5
  "type": "module",
6
6
  "sideEffects": false,