mnemocyte 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +266 -22
- package/dist/embedders/openai.d.mts +1 -1
- package/dist/embedders/openai.d.mts.map +1 -1
- package/dist/embedders/openai.mjs +24 -9
- package/dist/embedders/openai.mjs.map +1 -1
- package/dist/{errors-B_7ZdjEO.mjs → errors-DIPysVWl.mjs} +1 -1
- package/dist/errors-DIPysVWl.mjs.map +1 -0
- package/dist/index.d.mts +16 -12
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +155 -1699
- package/dist/index.mjs.map +1 -1
- package/dist/postgres-BHQ1pj16.mjs +913 -0
- package/dist/postgres-BHQ1pj16.mjs.map +1 -0
- package/dist/postgres-runtime-DxJxns07.mjs +9 -0
- package/dist/postgres-runtime-DxJxns07.mjs.map +1 -0
- package/dist/store-config-BFFTm1sj.mjs +1255 -0
- package/dist/store-config-BFFTm1sj.mjs.map +1 -0
- package/dist/stores/drizzle.d.mts +18 -0
- package/dist/stores/drizzle.d.mts.map +1 -0
- package/dist/stores/drizzle.mjs +20 -0
- package/dist/stores/drizzle.mjs.map +1 -0
- package/dist/{types-gOPLre4V.d.mts → types-XUWYDoXM.d.mts} +136 -34
- package/dist/types-XUWYDoXM.d.mts.map +1 -0
- package/migrations/0000_initial.sql.template +2 -1
- package/migrations/0002_add_embedding_model.sql +15 -0
- package/migrations/meta/0002_snapshot.json +315 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +7 -3
- package/dist/errors-B_7ZdjEO.mjs.map +0 -1
- package/dist/types-gOPLre4V.d.mts.map +0 -1
package/README.md
CHANGED
|
@@ -12,6 +12,8 @@ logs, and duplicate-consolidation tools on top of your existing infrastructure.
|
|
|
12
12
|
|
|
13
13
|
- In-memory backend for tests and demos.
|
|
14
14
|
- Postgres + pgvector backend for persistent storage.
|
|
15
|
+
- Caller-owned postgres.js Drizzle instances through
|
|
16
|
+
`mnemocyte/stores/drizzle`.
|
|
15
17
|
- User-supplied `Embedder` interface.
|
|
16
18
|
- Hybrid recall with vector similarity, lexical matching, recency, confidence,
|
|
17
19
|
access count, and importance.
|
|
@@ -65,14 +67,17 @@ const context = await client.buildContext({
|
|
|
65
67
|
await client.close();
|
|
66
68
|
```
|
|
67
69
|
|
|
68
|
-
When `databaseUrl`
|
|
70
|
+
When both `databaseUrl` and `store` are omitted, Mnemocyte uses the in-memory
|
|
71
|
+
backend. That backend is intended for development, tests, and prototyping. For
|
|
72
|
+
persistent or larger workloads, use Postgres.
|
|
69
73
|
|
|
70
74
|
## Embedder
|
|
71
75
|
|
|
72
76
|
Mnemocyte accepts any embedder that returns one vector per input text.
|
|
73
|
-
Each vector must match `embedder.dimensions
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
Each vector must match `embedder.dimensions`, contain only finite numbers, and
|
|
78
|
+
have at least one nonzero component. Invalid provider output, including an
|
|
79
|
+
exact zero-norm vector, fails with `MnemocyteError` code `"EMBEDDING"` before
|
|
80
|
+
storage or vector comparison. Tiny nonzero vectors remain valid.
|
|
76
81
|
|
|
77
82
|
```ts
|
|
78
83
|
const client = createMnemocyte({
|
|
@@ -102,7 +107,11 @@ const embedder = openaiEmbedder({
|
|
|
102
107
|
explicitly when you use a different key source. The helper uses `fetch`
|
|
103
108
|
directly and does not depend on the OpenAI SDK; plain `import "mnemocyte"` also
|
|
104
109
|
stays provider-free. The direct subpath `mnemocyte/embedders/openai` is also
|
|
105
|
-
supported for consumers that prefer provider-specific imports.
|
|
110
|
+
supported for consumers that prefer provider-specific imports. Provider
|
|
111
|
+
responses must contain exactly one uniquely indexed array embedding per input;
|
|
112
|
+
malformed response shapes fail with `MnemocyteError` code `"EMBEDDING"`.
|
|
113
|
+
Dimension and numeric-component validation remains at the shared embedder
|
|
114
|
+
boundary.
|
|
106
115
|
|
|
107
116
|
## Postgres
|
|
108
117
|
|
|
@@ -116,11 +125,52 @@ const client = createMnemocyte({
|
|
|
116
125
|
});
|
|
117
126
|
```
|
|
118
127
|
|
|
128
|
+
Applications that already own a postgres.js Drizzle instance can pass it
|
|
129
|
+
through the `mnemocyte/stores/drizzle` subpath:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { createMnemocyte } from "mnemocyte";
|
|
133
|
+
import { drizzleStore } from "mnemocyte/stores/drizzle";
|
|
134
|
+
import { drizzle } from "drizzle-orm/postgres-js";
|
|
135
|
+
import postgres from "postgres";
|
|
136
|
+
import * as applicationSchema from "./db/schema.js";
|
|
137
|
+
|
|
138
|
+
const sql = postgres(process.env.DATABASE_URL!);
|
|
139
|
+
const db = drizzle(sql, { schema: applicationSchema });
|
|
140
|
+
|
|
141
|
+
const client = createMnemocyte({
|
|
142
|
+
store: drizzleStore(db),
|
|
143
|
+
embedder,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
await client.remember({
|
|
148
|
+
entityId: "user_123",
|
|
149
|
+
content: "Uses the application's existing Drizzle connection.",
|
|
150
|
+
});
|
|
151
|
+
} finally {
|
|
152
|
+
await client.close(); // does not close db or sql
|
|
153
|
+
await sql.end(); // the caller retains connection ownership
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`drizzleStore(db)` v1 accepts only Drizzle instances backed by postgres.js. It
|
|
158
|
+
uses Mnemocyte's fixed tables in the `public` schema; the bundled migrations
|
|
159
|
+
must already have been applied, and the adapter does not create or migrate
|
|
160
|
+
tables. The caller's Drizzle schema map does not need to include Mnemocyte's
|
|
161
|
+
tables. Supplying both `databaseUrl` and `store` is ambiguous and throws
|
|
162
|
+
synchronously with `MnemocyteError` code `"CONFIG"`.
|
|
163
|
+
|
|
164
|
+
`databaseUrl` must use the `postgres:` or `postgresql:` protocol. Other URL
|
|
165
|
+
protocols reject synchronously with `MnemocyteError` code `"CONFIG"`; detailed
|
|
166
|
+
host, database, and credential validation remains the driver's responsibility.
|
|
167
|
+
|
|
119
168
|
The package includes:
|
|
120
169
|
|
|
121
170
|
```txt
|
|
122
171
|
migrations/0000_initial.sql
|
|
123
172
|
migrations/0001_add_mnemocyte_meta.sql
|
|
173
|
+
migrations/0002_add_embedding_model.sql
|
|
124
174
|
migrations/0000_initial.sql.template
|
|
125
175
|
migrations/render-initial.mjs
|
|
126
176
|
```
|
|
@@ -131,16 +181,19 @@ order:
|
|
|
131
181
|
```txt
|
|
132
182
|
migrations/0000_initial.sql
|
|
133
183
|
migrations/0001_add_mnemocyte_meta.sql
|
|
184
|
+
migrations/0002_add_embedding_model.sql
|
|
134
185
|
```
|
|
135
186
|
|
|
136
187
|
For an existing 0.1.x Postgres install, apply
|
|
137
|
-
`migrations/0001_add_mnemocyte_meta.sql`
|
|
138
|
-
|
|
188
|
+
`migrations/0001_add_mnemocyte_meta.sql` and then
|
|
189
|
+
`migrations/0002_add_embedding_model.sql`. Existing 0.2.x or 0.3.x installs
|
|
190
|
+
only need `0002_add_embedding_model.sql`.
|
|
139
191
|
|
|
140
192
|
For a different embedding dimension on a fresh installation, render an explicit
|
|
141
193
|
initial migration from the template and apply that rendered file instead of the
|
|
142
194
|
default `0000_initial.sql`. The rendered initial migration includes the
|
|
143
|
-
matching `mnemocyte_meta`
|
|
195
|
+
matching `mnemocyte_meta` dimensions and the installation-model column, so it
|
|
196
|
+
does not also need `0001` or `0002`.
|
|
144
197
|
|
|
145
198
|
```bash
|
|
146
199
|
node node_modules/mnemocyte/migrations/render-initial.mjs --dimensions 768 --out migrations/0000_initial.768.sql
|
|
@@ -152,14 +205,41 @@ Inside this repository, the equivalent development shortcut is:
|
|
|
152
205
|
pnpm migration:render -- --dimensions 768 --out migrations/0000_initial.768.sql
|
|
153
206
|
```
|
|
154
207
|
|
|
155
|
-
The Postgres backend supports one embedding dimension per
|
|
156
|
-
|
|
157
|
-
`mnemocyte_meta` and validates
|
|
158
|
-
|
|
159
|
-
|
|
208
|
+
The Postgres backend supports one embedding model and dimension per
|
|
209
|
+
installation. Before writes, recall, or duplicate scans, Mnemocyte reads
|
|
210
|
+
`mnemocyte_meta` and validates both values before calling the embedder or
|
|
211
|
+
comparing vectors. An empty installation atomically records the configured
|
|
212
|
+
model on its first embedding-dependent operation. Migration `0002` records the
|
|
213
|
+
single model already present in historical rows when that value is
|
|
214
|
+
unambiguous.
|
|
215
|
+
|
|
216
|
+
A configured model or dimension mismatch throws `MnemocyteError` code
|
|
217
|
+
`"CONFIG"`. If historical rows contain multiple model values, the installation
|
|
218
|
+
model remains unset and embedding-dependent operations throw `"MIGRATION"`
|
|
219
|
+
until an operator re-embeds or removes the mixed rows and explicitly records
|
|
220
|
+
the intended installation model. Non-embedding recovery operations such as
|
|
221
|
+
`stats`, `forget`, and pruning remain available.
|
|
222
|
+
|
|
223
|
+
Inspect mixed history before repairing it:
|
|
224
|
+
|
|
225
|
+
```sql
|
|
226
|
+
SELECT embedding_model, count(*)
|
|
227
|
+
FROM mnemocyte_memories
|
|
228
|
+
GROUP BY embedding_model;
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Only after every retained row belongs to the intended vector space, record that
|
|
232
|
+
model explicitly:
|
|
160
233
|
|
|
161
|
-
|
|
162
|
-
|
|
234
|
+
```sql
|
|
235
|
+
UPDATE mnemocyte_meta
|
|
236
|
+
SET embedding_model = 'your-model-id'
|
|
237
|
+
WHERE key = 'installation';
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Use the model identifier and embedding dimension documented for your embedder,
|
|
241
|
+
render or apply a matching schema, and keep one vector space per Mnemocyte
|
|
242
|
+
installation.
|
|
163
243
|
|
|
164
244
|
The migration creates the bundled HNSW pgvector index
|
|
165
245
|
`mnemocyte_memories_embedding_hnsw_idx` for cosine search. HNSW is approximate:
|
|
@@ -200,6 +280,19 @@ bigints, non-finite numbers, class instances, or cyclic objects are rejected
|
|
|
200
280
|
with `MnemocyteError` code `"VALIDATION"`. Mnemocyte deep-clones metadata when
|
|
201
281
|
writing and reading, so later mutations do not change stored state.
|
|
202
282
|
|
|
283
|
+
JavaScript callers receive the same runtime domain checks as TypeScript
|
|
284
|
+
callers: `type` and `importance` must be known values, tags must be an array of
|
|
285
|
+
strings, `source` must be a string when supplied, and `expiresAt` must be a
|
|
286
|
+
valid `Date`. Invalid values reject with `"VALIDATION"` before embedding or
|
|
287
|
+
storage. Mutable tags, metadata, and expiration dates are snapshotted when
|
|
288
|
+
`remember` or `rememberMany` is invoked, so later caller mutations cannot
|
|
289
|
+
change the pending write.
|
|
290
|
+
|
|
291
|
+
When observability is configured, snapshot and validation failures follow the
|
|
292
|
+
same operation lifecycle as provider or storage failures: one `"start"` event
|
|
293
|
+
and one `"error"` event carrying the thrown value. Snapshotting remains
|
|
294
|
+
synchronous before any awaited `onEvent` hook.
|
|
295
|
+
|
|
203
296
|
For batches, cancellation belongs to the whole operation:
|
|
204
297
|
|
|
205
298
|
```ts
|
|
@@ -230,6 +323,11 @@ const memories = await client.recall({
|
|
|
230
323
|
});
|
|
231
324
|
```
|
|
232
325
|
|
|
326
|
+
Successful recall results include the access metadata written by that call:
|
|
327
|
+
`accessCount`, `lastAccessedAt`, and `updatedAt` match stored state when the
|
|
328
|
+
promise resolves. Ranking and score explanations use the count from before the
|
|
329
|
+
current recall so the access update cannot change its own ordering.
|
|
330
|
+
|
|
233
331
|
### `buildContext`
|
|
234
332
|
|
|
235
333
|
```ts
|
|
@@ -241,8 +339,35 @@ const context = await client.buildContext({
|
|
|
241
339
|
});
|
|
242
340
|
```
|
|
243
341
|
|
|
342
|
+
Plain-text context uses a deterministic `=` fence longer than any `=` run in
|
|
343
|
+
the query, rendered metadata, or included memory content. The resulting
|
|
344
|
+
`MEMORY N START/END` boundaries cannot be reproduced by untrusted content.
|
|
345
|
+
Markdown continues to choose a content-safe backtick fence, and XML continues
|
|
346
|
+
to escape content.
|
|
347
|
+
|
|
244
348
|
When supplied, `maxTokens` must be a positive integer or `buildContext` rejects
|
|
245
|
-
with `"VALIDATION"`. Omitting it keeps the default token-budget path.
|
|
349
|
+
with `"VALIDATION"`. Omitting it keeps the default token-budget path. Returned
|
|
350
|
+
context always fits the supplied counter and budget; when an extremely small
|
|
351
|
+
budget cannot fit the full truncation marker, the result is the longest marker
|
|
352
|
+
fragment that fits or an empty string.
|
|
353
|
+
|
|
354
|
+
### `forget` and `forgetAll`
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
await client.forget({
|
|
358
|
+
entityId: "user_123",
|
|
359
|
+
memoryId: "mem_old",
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
await client.forgetAll({ entityId: "user_123" });
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
A memory cannot be deleted while another memory's `supersededBy` still points
|
|
366
|
+
to it as a consolidation survivor. `forget` and `forgetAll` reject with
|
|
367
|
+
`"CONFLICT"` before deleting anything in that case. This also applies when
|
|
368
|
+
`forgetAll` selects both the survivor and its superseded dependent. Delete the
|
|
369
|
+
superseded memories first; deleting a loser, or any memory with no dependents,
|
|
370
|
+
continues to work normally.
|
|
246
371
|
|
|
247
372
|
### `prune`
|
|
248
373
|
|
|
@@ -259,6 +384,23 @@ await client.prune({
|
|
|
259
384
|
});
|
|
260
385
|
```
|
|
261
386
|
|
|
387
|
+
Prune selectors are validated and normalized before either backend is called.
|
|
388
|
+
Dates must be valid `Date` instances, enum values must be known, arrays must
|
|
389
|
+
contain valid values, and boolean fields must be actual booleans. `false`
|
|
390
|
+
selector flags and empty selector arrays do not count toward the required
|
|
391
|
+
selector; malformed or selector-free input rejects with `"VALIDATION"` without
|
|
392
|
+
deleting anything. Tag selectors are trimmed and deduplicated.
|
|
393
|
+
|
|
394
|
+
A dry run may preview a survivor among its matches. A non-dry-run prune rejects
|
|
395
|
+
with `"CONFLICT"` if any matching memory still has consolidation dependents,
|
|
396
|
+
and the entire prune batch remains unchanged; unrelated matching rows are not
|
|
397
|
+
partially deleted.
|
|
398
|
+
|
|
399
|
+
When audit logging is enabled, every successful non-dry prune writes one
|
|
400
|
+
best-effort `"memory.pruned"` event per affected entity, including global
|
|
401
|
+
prunes without an `entityId`. Dry runs and zero-deletion runs do not write prune
|
|
402
|
+
events.
|
|
403
|
+
|
|
262
404
|
### `findDuplicates`
|
|
263
405
|
|
|
264
406
|
```ts
|
|
@@ -269,6 +411,10 @@ const pairs = await client.findDuplicates({
|
|
|
269
411
|
});
|
|
270
412
|
```
|
|
271
413
|
|
|
414
|
+
The in-memory implementation compares memory pairs quadratically. It degrades
|
|
415
|
+
noticeably once an entity grows beyond roughly a few thousand memories, so use
|
|
416
|
+
the Postgres backend for duplicate detection beyond that scale.
|
|
417
|
+
|
|
272
418
|
### `listAuditLog`
|
|
273
419
|
|
|
274
420
|
```ts
|
|
@@ -281,8 +427,24 @@ const events = await client.listAuditLog({
|
|
|
281
427
|
entityId: "user_123",
|
|
282
428
|
limit: 100,
|
|
283
429
|
});
|
|
430
|
+
|
|
431
|
+
const last = events.at(-1);
|
|
432
|
+
const nextPage = last
|
|
433
|
+
? await client.listAuditLog({
|
|
434
|
+
entityId: "user_123",
|
|
435
|
+
limit: 100,
|
|
436
|
+
beforeCursor: { timestamp: last.timestamp, id: last.id },
|
|
437
|
+
})
|
|
438
|
+
: [];
|
|
284
439
|
```
|
|
285
440
|
|
|
441
|
+
Audit entries are ordered newest first by timestamp and event ID. The
|
|
442
|
+
experimental composite `beforeCursor` / `afterCursor` fields provide stable
|
|
443
|
+
pagination when multiple events share a timestamp. The existing `before` and
|
|
444
|
+
`after` fields remain strict timestamp filters; they exclude all events at the
|
|
445
|
+
boundary timestamp and should not be used as the sole cursor when complete
|
|
446
|
+
tie-safe pagination is required.
|
|
447
|
+
|
|
286
448
|
Ordinary audit writes are best-effort: an audit storage failure does not fail
|
|
287
449
|
the primary client operation, so `listAuditLog` returns only events that were
|
|
288
450
|
successfully persisted. Postgres consolidation is the exception; its
|
|
@@ -299,6 +461,26 @@ await client.experimental.consolidate({
|
|
|
299
461
|
});
|
|
300
462
|
```
|
|
301
463
|
|
|
464
|
+
Consolidation records each loser's `supersededBy` reference to the survivor.
|
|
465
|
+
Retrying the same loser with that same survivor is an idempotent no-op. If any
|
|
466
|
+
requested loser already points to a different survivor, the call rejects with
|
|
467
|
+
`"CONFLICT"`. Mixed batches are atomic: no newly eligible loser is changed, no
|
|
468
|
+
tags are merged, and no consolidation audit event is written when any item
|
|
469
|
+
conflicts. Concurrent calls follow the same target-specific rule in both
|
|
470
|
+
backends. `supersededIds` must contain distinct IDs; duplicates reject with
|
|
471
|
+
`"VALIDATION"` before either store is accessed.
|
|
472
|
+
|
|
473
|
+
The store re-reads and protects the survivor in the same atomic boundary as
|
|
474
|
+
the loser updates, tag merge, and enabled audit events. If the survivor is
|
|
475
|
+
deleted or becomes superseded after initial validation but before that
|
|
476
|
+
boundary, the call rejects with `"CONFLICT"` without a partial mutation. Tag
|
|
477
|
+
merges start from the survivor's state inside that boundary, so concurrent
|
|
478
|
+
successful consolidations preserve every committed tag.
|
|
479
|
+
|
|
480
|
+
The survivor cannot later be deleted while any such reference remains:
|
|
481
|
+
`forget`, `forgetAll`, and matching non-dry-run `prune` calls reject with
|
|
482
|
+
`"CONFLICT"`. Deleting a superseded loser remains allowed.
|
|
483
|
+
|
|
302
484
|
The `experimental` namespace may change before v1.0.
|
|
303
485
|
|
|
304
486
|
## Provider Resilience
|
|
@@ -315,6 +497,12 @@ const client = createMnemocyte({
|
|
|
315
497
|
});
|
|
316
498
|
```
|
|
317
499
|
|
|
500
|
+
Provider resilience values are validated synchronously when the client is
|
|
501
|
+
created. Timeouts and delays must be finite non-negative numbers, retries must
|
|
502
|
+
be a non-negative integer, and `shouldRetry` must be a function when supplied;
|
|
503
|
+
invalid values throw `"CONFIG"`. A `maxDelayMs` below `baseDelayMs` remains
|
|
504
|
+
valid and is normalized up to the base delay.
|
|
505
|
+
|
|
318
506
|
Pass `signal` to cancel an operation:
|
|
319
507
|
|
|
320
508
|
```ts
|
|
@@ -327,6 +515,17 @@ await client.remember({
|
|
|
327
515
|
});
|
|
328
516
|
```
|
|
329
517
|
|
|
518
|
+
Pre-aborted signals reject with `"ABORTED"` before storage work begins.
|
|
519
|
+
In-memory maintenance scans check cancellation cooperatively. For Postgres,
|
|
520
|
+
standalone prune, duplicate-search, and audit-log queries request postgres.js
|
|
521
|
+
query cancellation while they are in flight.
|
|
522
|
+
|
|
523
|
+
Postgres consolidation has a transaction-specific boundary: cancellation is
|
|
524
|
+
checked between mutation steps and immediately before the transaction callback
|
|
525
|
+
returns. If a statement is already in flight, it may finish before the next
|
|
526
|
+
check throws and rolls the transaction back. An abort after the final check,
|
|
527
|
+
including while commit is in flight, may still leave the mutation committed.
|
|
528
|
+
|
|
330
529
|
Common `MnemocyteError` codes:
|
|
331
530
|
|
|
332
531
|
```txt
|
|
@@ -337,6 +536,7 @@ VALIDATION
|
|
|
337
536
|
CONFIG
|
|
338
537
|
DB
|
|
339
538
|
NOT_FOUND
|
|
539
|
+
CONFLICT
|
|
340
540
|
MIGRATION
|
|
341
541
|
```
|
|
342
542
|
|
|
@@ -367,12 +567,51 @@ must be positive finite numbers, and `candidateMultiplier` must be an integer
|
|
|
367
567
|
of at least 1. Invalid tuning is rejected at client construction with
|
|
368
568
|
`MnemocyteError` code `"CONFIG"`.
|
|
369
569
|
|
|
570
|
+
## Storage Adapter Contract
|
|
571
|
+
|
|
572
|
+
`MemoryStore` is still an internal boundary rather than a public package
|
|
573
|
+
export, but its future-adapter contract is now documented directly in
|
|
574
|
+
[`src/memory/store.ts`](./src/memory/store.ts). The contract is based on
|
|
575
|
+
postconditions, not identical implementation mechanics: every method is
|
|
576
|
+
mandatory, and no capability-flag surface exists or is currently planned.
|
|
577
|
+
|
|
578
|
+
For adapter implementers, the main rules are:
|
|
579
|
+
|
|
580
|
+
- `ensureSchema` is a readiness hook, not permission for hidden schema
|
|
581
|
+
creation. `ensureEmbeddingCompatibility` unconditionally enforces whatever
|
|
582
|
+
compatibility is meaningful to the persistence model; a store without
|
|
583
|
+
persistent installation state may no-op.
|
|
584
|
+
- `insertMemories` takes ownership of prepared rows and returns exactly one
|
|
585
|
+
detached record per prepared ID. Store return order is untrusted; shared
|
|
586
|
+
orchestration rejects missing, duplicate, or unknown IDs and restores input
|
|
587
|
+
order. `getMemoryEmbeddings`, `getMemory`, and `stats` use the exact keyed,
|
|
588
|
+
detached, and count postconditions described in the source comments.
|
|
589
|
+
- `markMemoriesAccessed` requires distinct IDs and returns the committed
|
|
590
|
+
post-update access fields. Duplicate-ID behavior is intentionally not a
|
|
591
|
+
portable contract. Ordinary `addAuditEvents` calls are best-effort, and a
|
|
592
|
+
rejected batch may have partially persisted on some backends.
|
|
593
|
+
- `listAuditLog` uses stable event IDs, comparable timestamps, strict tuple
|
|
594
|
+
filters, and matching newest-first `(timestamp, id)` order. Tuple pagination
|
|
595
|
+
needs no transaction. Cancellation may be cooperative or active depending on
|
|
596
|
+
the implementation.
|
|
597
|
+
- `vectorSearch` may scan or use an approximate, planner-dependent index.
|
|
598
|
+
`lexicalSearch` may legitimately return different candidates and rankings
|
|
599
|
+
across implementations. `findDuplicatePairs` compares qualifying memories
|
|
600
|
+
pairwise and does not imply indexed nearest-neighbor pair generation.
|
|
601
|
+
- `deleteMemory`, `deleteMemoriesForEntity`, and non-dry-run `prune` must
|
|
602
|
+
protect referenced consolidation survivors with one atomic,
|
|
603
|
+
non-interleavable check-and-mutate operation and reject with `"CONFLICT"`
|
|
604
|
+
before any deletion. Other cancellation boundaries remain method- and
|
|
605
|
+
implementation-specific as documented by the public operations.
|
|
606
|
+
- `close` releases or destroys only implementation-owned state and resources.
|
|
607
|
+
A future adapter around a caller-supplied connection must not close that
|
|
608
|
+
connection.
|
|
609
|
+
|
|
370
610
|
## Roadmap
|
|
371
611
|
|
|
372
612
|
Planned larger milestones:
|
|
373
613
|
|
|
374
614
|
- public `MemoryStore` adapter surface
|
|
375
|
-
- `drizzleStore(db)` for caller-owned Drizzle clients
|
|
376
615
|
- `@mnemocyte/mcp`
|
|
377
616
|
|
|
378
617
|
See [ROADMAP.md](./docs/ROADMAP.md).
|
|
@@ -381,11 +620,15 @@ See [ROADMAP.md](./docs/ROADMAP.md).
|
|
|
381
620
|
|
|
382
621
|
Current behavior:
|
|
383
622
|
|
|
384
|
-
- `createMnemocyte()` selects
|
|
385
|
-
Postgres/pgvector backend
|
|
623
|
+
- `createMnemocyte()` selects an explicitly supplied `store`, the URL-owned
|
|
624
|
+
Postgres/pgvector backend, or the in-memory backend; supplying both `store`
|
|
625
|
+
and `databaseUrl` rejects instead of selecting a precedence.
|
|
386
626
|
- Both backends run through an internal `MemoryStore` boundary and shared
|
|
387
627
|
client orchestration; `MemoryStore` is not exported as a public adapter API
|
|
388
628
|
yet.
|
|
629
|
+
- `mnemocyte/stores/drizzle` exposes the first supported public adapter factory
|
|
630
|
+
for a caller-owned postgres.js Drizzle instance without exporting the full
|
|
631
|
+
`MemoryStore` contract.
|
|
389
632
|
- Postgres schema setup is explicit; the client does not create tables or
|
|
390
633
|
indexes for you.
|
|
391
634
|
- `findDuplicates`, audit-log workflows, and `experimental.consolidate` are
|
|
@@ -394,12 +637,13 @@ Current behavior:
|
|
|
394
637
|
Known limitations before v1:
|
|
395
638
|
|
|
396
639
|
- The internal `MemoryStore` boundary is not a public adapter API yet.
|
|
397
|
-
`drizzleStore(db)`
|
|
640
|
+
`drizzleStore(db)` returns an opaque config value and currently supports only
|
|
641
|
+
postgres.js, the `public` schema, and pre-applied Mnemocyte migrations.
|
|
398
642
|
- Configured provider timeouts abort the per-attempt `AbortSignal`; the
|
|
399
643
|
underlying provider request only stops promptly when the embedder honors that
|
|
400
644
|
signal.
|
|
401
|
-
- Postgres dimension metadata
|
|
402
|
-
in one database are intentionally
|
|
645
|
+
- Postgres model and dimension metadata are installation-wide. Mixed embedding
|
|
646
|
+
vector spaces in one database are intentionally unsupported.
|
|
403
647
|
|
|
404
648
|
Planned v1 direction:
|
|
405
649
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.d.mts","names":[],"sources":["../../src/embedders/openai.ts"],"mappings":";;;UAciB,qBAAA;;AAAjB;;WAIU,MAAA;EAJ4B;;;EAAA,SAQ5B,KAAA;EAUA;;AAAO;
|
|
1
|
+
{"version":3,"file":"openai.d.mts","names":[],"sources":["../../src/embedders/openai.ts"],"mappings":";;;UAciB,qBAAA;;AAAjB;;WAIU,MAAA;EAJ4B;;;EAAA,SAQ5B,KAAA;EAUA;;AAAO;AAoIjB;EApIU,SALA,UAAA;;;;;WAKA,OAAA;AAAA;AAoI8D;;;;AAAA,iBAAxD,cAAA,CAAe,OAAA,EAAS,qBAAA,GAAwB,QAAQ"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as MnemocyteError } from "../errors-
|
|
1
|
+
import { t as MnemocyteError } from "../errors-DIPysVWl.mjs";
|
|
2
2
|
//#region src/embedders/openai.ts
|
|
3
3
|
const KNOWN_MODEL_DIMENSIONS = {
|
|
4
4
|
"text-embedding-3-small": 1536,
|
|
@@ -6,6 +6,28 @@ const KNOWN_MODEL_DIMENSIONS = {
|
|
|
6
6
|
"text-embedding-ada-002": 1536
|
|
7
7
|
};
|
|
8
8
|
const CONFIGURABLE_DIMENSION_MODELS = new Set(["text-embedding-3-small", "text-embedding-3-large"]);
|
|
9
|
+
function isRecord(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
function validateEmbeddingResponse(body, expectedCount) {
|
|
13
|
+
if (!isRecord(body) || !Array.isArray(body.data)) throw new MnemocyteError("OpenAI returned malformed embedding response data.", "EMBEDDING");
|
|
14
|
+
if (body.data.length !== expectedCount) throw new MnemocyteError("OpenAI returned an unexpected number of embeddings.", "EMBEDDING");
|
|
15
|
+
const indices = /* @__PURE__ */ new Set();
|
|
16
|
+
const items = [];
|
|
17
|
+
for (const item of body.data) {
|
|
18
|
+
if (!isRecord(item)) throw new MnemocyteError("OpenAI returned a malformed embedding item.", "EMBEDDING");
|
|
19
|
+
const { embedding, index } = item;
|
|
20
|
+
if (typeof index !== "number" || !Number.isInteger(index) || index < 0 || index >= expectedCount) throw new MnemocyteError("OpenAI returned an embedding with an invalid index.", "EMBEDDING");
|
|
21
|
+
if (indices.has(index)) throw new MnemocyteError("OpenAI returned a duplicate embedding index.", "EMBEDDING");
|
|
22
|
+
if (!Array.isArray(embedding)) throw new MnemocyteError("OpenAI returned an embedding that is not an array.", "EMBEDDING");
|
|
23
|
+
indices.add(index);
|
|
24
|
+
items.push({
|
|
25
|
+
embedding,
|
|
26
|
+
index
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return items;
|
|
30
|
+
}
|
|
9
31
|
function assertDimensions(dimensions) {
|
|
10
32
|
if (!Number.isInteger(dimensions) || dimensions < 1) throw new MnemocyteError("openaiEmbedder dimensions must be a positive integer.", "CONFIG");
|
|
11
33
|
}
|
|
@@ -61,14 +83,7 @@ function openaiEmbedder(options) {
|
|
|
61
83
|
...embedOptions?.signal === void 0 ? {} : { signal: embedOptions.signal }
|
|
62
84
|
});
|
|
63
85
|
if (!response.ok) throw Object.assign(/* @__PURE__ */ new Error(`OpenAI embeddings request failed with status ${response.status}.`), { status: response.status });
|
|
64
|
-
|
|
65
|
-
const embeddings = Array.from({ length: texts.length });
|
|
66
|
-
for (const item of body.data) {
|
|
67
|
-
if (!Number.isInteger(item.index) || item.index < 0 || item.index >= texts.length) throw new MnemocyteError("OpenAI returned an embedding with an invalid index.", "EMBEDDING");
|
|
68
|
-
embeddings[item.index] = item.embedding;
|
|
69
|
-
}
|
|
70
|
-
if (embeddings.some((embedding) => embedding === void 0)) throw new MnemocyteError("OpenAI returned fewer embeddings than requested.", "EMBEDDING");
|
|
71
|
-
return embeddings;
|
|
86
|
+
return validateEmbeddingResponse(await response.json(), texts.length).sort((left, right) => left.index - right.index).map((item) => item.embedding);
|
|
72
87
|
}
|
|
73
88
|
};
|
|
74
89
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.mjs","names":[],"sources":["../../src/embedders/openai.ts"],"sourcesContent":["import { MnemocyteError } from \"../errors.js\";\nimport type { Embedder } from \"../types.js\";\n\nconst KNOWN_MODEL_DIMENSIONS: Record<string, number> = {\n\t\"text-embedding-3-small\": 1536,\n\t\"text-embedding-3-large\": 3072,\n\t\"text-embedding-ada-002\": 1536,\n};\n\nconst CONFIGURABLE_DIMENSION_MODELS = new Set([\n\t\"text-embedding-3-small\",\n\t\"text-embedding-3-large\",\n]);\n\nexport interface OpenAIEmbedderOptions {\n\t/**\n\t * OpenAI API key. Defaults to `process.env.OPENAI_API_KEY`.\n\t */\n\treadonly apiKey?: string;\n\t/**\n\t * OpenAI embedding model name.\n\t */\n\treadonly model: string;\n\t/**\n\t * Output dimensions. Required for unknown/future model names and accepted\n\t * only for OpenAI models that support configurable dimensions.\n\t */\n\treadonly dimensions?: number;\n\t/**\n\t * Override the OpenAI API base URL. Intended for tests and compatible\n\t * deployments; defaults to `https://api.openai.com/v1`.\n\t */\n\treadonly baseUrl?: string;\n}\n\ninterface OpenAIEmbeddingItem {\n\treadonly embedding: number[];\n\treadonly index: number;\n}\n\
|
|
1
|
+
{"version":3,"file":"openai.mjs","names":[],"sources":["../../src/embedders/openai.ts"],"sourcesContent":["import { MnemocyteError } from \"../errors.js\";\nimport type { Embedder } from \"../types.js\";\n\nconst KNOWN_MODEL_DIMENSIONS: Record<string, number> = {\n\t\"text-embedding-3-small\": 1536,\n\t\"text-embedding-3-large\": 3072,\n\t\"text-embedding-ada-002\": 1536,\n};\n\nconst CONFIGURABLE_DIMENSION_MODELS = new Set([\n\t\"text-embedding-3-small\",\n\t\"text-embedding-3-large\",\n]);\n\nexport interface OpenAIEmbedderOptions {\n\t/**\n\t * OpenAI API key. Defaults to `process.env.OPENAI_API_KEY`.\n\t */\n\treadonly apiKey?: string;\n\t/**\n\t * OpenAI embedding model name.\n\t */\n\treadonly model: string;\n\t/**\n\t * Output dimensions. Required for unknown/future model names and accepted\n\t * only for OpenAI models that support configurable dimensions.\n\t */\n\treadonly dimensions?: number;\n\t/**\n\t * Override the OpenAI API base URL. Intended for tests and compatible\n\t * deployments; defaults to `https://api.openai.com/v1`.\n\t */\n\treadonly baseUrl?: string;\n}\n\ninterface OpenAIEmbeddingItem {\n\treadonly embedding: number[];\n\treadonly index: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateEmbeddingResponse(\n\tbody: unknown,\n\texpectedCount: number,\n): OpenAIEmbeddingItem[] {\n\tif (!isRecord(body) || !Array.isArray(body.data)) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"OpenAI returned malformed embedding response data.\",\n\t\t\t\"EMBEDDING\",\n\t\t);\n\t}\n\tif (body.data.length !== expectedCount) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"OpenAI returned an unexpected number of embeddings.\",\n\t\t\t\"EMBEDDING\",\n\t\t);\n\t}\n\n\tconst indices = new Set<number>();\n\tconst items: OpenAIEmbeddingItem[] = [];\n\tfor (const item of body.data) {\n\t\tif (!isRecord(item)) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned a malformed embedding item.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tconst { embedding, index } = item;\n\t\tif (\n\t\t\ttypeof index !== \"number\" ||\n\t\t\t!Number.isInteger(index) ||\n\t\t\tindex < 0 ||\n\t\t\tindex >= expectedCount\n\t\t) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned an embedding with an invalid index.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tif (indices.has(index)) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned a duplicate embedding index.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tif (!Array.isArray(embedding)) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t\"OpenAI returned an embedding that is not an array.\",\n\t\t\t\t\"EMBEDDING\",\n\t\t\t);\n\t\t}\n\t\tindices.add(index);\n\t\titems.push({ embedding: embedding as number[], index });\n\t}\n\treturn items;\n}\n\nfunction assertDimensions(dimensions: number): void {\n\tif (!Number.isInteger(dimensions) || dimensions < 1) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"openaiEmbedder dimensions must be a positive integer.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n}\n\nfunction resolveApiKey(apiKey: string | undefined): string {\n\tconst resolved = apiKey ?? process.env.OPENAI_API_KEY;\n\tif (!resolved || resolved.trim().length === 0) {\n\t\tthrow new MnemocyteError(\n\t\t\t\"openaiEmbedder requires an API key. Pass apiKey or set OPENAI_API_KEY.\",\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n\treturn resolved;\n}\n\nfunction resolveDimensions(options: OpenAIEmbedderOptions): {\n\tembedderDimensions: number;\n\trequestDimensions?: number;\n} {\n\tconst defaultDimensions = KNOWN_MODEL_DIMENSIONS[options.model];\n\tif (defaultDimensions === undefined) {\n\t\tif (options.dimensions === undefined) {\n\t\t\tthrow new MnemocyteError(\n\t\t\t\t`openaiEmbedder requires dimensions for unknown model \"${options.model}\".`,\n\t\t\t\t\"CONFIG\",\n\t\t\t);\n\t\t}\n\t\tassertDimensions(options.dimensions);\n\t\treturn {\n\t\t\tembedderDimensions: options.dimensions,\n\t\t\trequestDimensions: options.dimensions,\n\t\t};\n\t}\n\n\tif (\n\t\toptions.dimensions !== undefined &&\n\t\t!CONFIGURABLE_DIMENSION_MODELS.has(options.model)\n\t) {\n\t\tthrow new MnemocyteError(\n\t\t\t`openaiEmbedder does not support a dimensions override for \"${options.model}\".`,\n\t\t\t\"CONFIG\",\n\t\t);\n\t}\n\n\tif (options.dimensions !== undefined) {\n\t\tassertDimensions(options.dimensions);\n\t\treturn {\n\t\t\tembedderDimensions: options.dimensions,\n\t\t\trequestDimensions: options.dimensions,\n\t\t};\n\t}\n\n\treturn { embedderDimensions: defaultDimensions };\n}\n\n/**\n * Create an OpenAI-backed {@link Embedder}. This adapter uses `fetch`\n * directly so provider SDKs never become part of Mnemocyte's dependency graph.\n */\nexport function openaiEmbedder(options: OpenAIEmbedderOptions): Embedder {\n\tconst apiKey = resolveApiKey(options.apiKey);\n\tconst { embedderDimensions, requestDimensions } = resolveDimensions(options);\n\tconst baseUrl = options.baseUrl ?? \"https://api.openai.com/v1\";\n\n\treturn {\n\t\tmodel: options.model,\n\t\tdimensions: embedderDimensions,\n\t\tasync embed(texts, embedOptions) {\n\t\t\tconst response = await fetch(`${baseUrl}/embeddings`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${apiKey}`,\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel: options.model,\n\t\t\t\t\tinput: [...texts],\n\t\t\t\t\tencoding_format: \"float\",\n\t\t\t\t\t...(requestDimensions === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { dimensions: requestDimensions }),\n\t\t\t\t}),\n\t\t\t\t...(embedOptions?.signal === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { signal: embedOptions.signal }),\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow Object.assign(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`OpenAI embeddings request failed with status ${response.status}.`,\n\t\t\t\t\t),\n\t\t\t\t\t{ status: response.status },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst items = validateEmbeddingResponse(\n\t\t\t\tawait response.json(),\n\t\t\t\ttexts.length,\n\t\t\t);\n\t\t\treturn items\n\t\t\t\t.sort((left, right) => left.index - right.index)\n\t\t\t\t.map((item) => item.embedding);\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-DIPysVWl.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\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 * - `\"CONFLICT\"` — the requested mutation conflicts with stored relationships.\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| \"CONFLICT\"\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 * This guard uses `instanceof` and recognizes errors created by the same loaded\n * Mnemocyte class. It does not recognize structurally similar errors or errors\n * created by another installed copy of the package.\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AA2CA,IAAa,iBAAb,cAAoC,MAAM;;CAEzC;;CAEA;;;;;;CAOA,YAAY,SAAiB,MAA0B,OAAiB;EACvE,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,QAAQ;CACd;AACD;;;;;;;;;;;AAYA,SAAgB,iBAAiB,OAAyC;CACzE,OAAO,iBAAiB;AACzB"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as PruneInput, C as MnemocyteConfig, D as MnemocyteStoreConfig, E as MnemocyteOperation, F as RetrievalConfig, I as RetrievalExplanation, L as RetrievalScoreWeights, M as RecallInput, N as RememberInput, O as ObservabilityConfig, P as RememberManyInput, R as RetrievalScores, S as MnemocyteClient, T as MnemocyteObservationPhase, _ as ListAuditLogInput, a as ConsolidateInput, b as MemoryWithScore, c as DuplicatePair, d as ExperimentalMnemocyteClient, f as FindDuplicatesInput, g as JsonValue, h as JsonObject, i as BuildContextInput, j as PruneResult, k as ProviderResilienceConfig, l as Embedder, m as ImportanceLevel, n as AuditEvent, o as ConsolidateResult, p as GlobalStats, r as AuditLogCursor, s as ContextFormat, t as AuditConfig, u as EntityStats, v as Memory, w as MnemocyteObservation, x as MnemocyteBackend, y as MemoryType, z as TokenCounter } from "./types-XUWYDoXM.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/client.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Create a Mnemocyte client.
|
|
6
6
|
*
|
|
7
|
-
* When {@link MnemocyteConfig.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* for tests, demos,
|
|
7
|
+
* When {@link MnemocyteConfig.store} is provided, that adapter is used. When
|
|
8
|
+
* {@link MnemocyteConfig.databaseUrl} is provided, a URL-owned Postgres client
|
|
9
|
+
* is used (requires the `pgvector` extension and the bundled migrations).
|
|
10
|
+
* When neither is supplied, an in-memory client is returned for tests, demos,
|
|
11
|
+
* and short-lived processes.
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* Call {@link MnemocyteClient.close} when finished. URL-created database
|
|
14
|
+
* resources are owned and closed by Mnemocyte; resources behind a supplied
|
|
15
|
+
* store retain the ownership policy documented by that adapter.
|
|
15
16
|
*
|
|
16
17
|
* @param config - Client configuration. {@link MnemocyteConfig.embedder} is required.
|
|
17
18
|
* @returns A {@link MnemocyteClient} instance.
|
|
18
19
|
* @throws {MnemocyteError} With code `"CONFIG"` if `embedder`, retrieval
|
|
19
|
-
* tuning, or the database URL is malformed
|
|
20
|
-
* `
|
|
20
|
+
* tuning, provider resilience, or the database URL is malformed or does not
|
|
21
|
+
* use the `postgres:` / `postgresql:` protocol, or if `databaseUrl` and
|
|
22
|
+
* `store` are both provided; or `"VALIDATION"` if `databaseUrl` is explicitly
|
|
23
|
+
* empty.
|
|
21
24
|
*
|
|
22
25
|
* @example Postgres-backed client
|
|
23
26
|
* ```ts
|
|
@@ -38,11 +41,12 @@ declare function createMnemocyte(config: MnemocyteConfig): MnemocyteClient;
|
|
|
38
41
|
* - `"DB"` — Postgres or driver-level failure.
|
|
39
42
|
* - `"EMBEDDING"` — embedder threw or returned an invalid vector.
|
|
40
43
|
* - `"NOT_FOUND"` — referenced memory or entity does not exist.
|
|
44
|
+
* - `"CONFLICT"` — the requested mutation conflicts with stored relationships.
|
|
41
45
|
* - `"MIGRATION"` — schema/migration check failed against the target database.
|
|
42
46
|
* - `"TIMEOUT"` — a provider call exceeded its configured timeout.
|
|
43
47
|
* - `"ABORTED"` — the operation was cancelled via an `AbortSignal`.
|
|
44
48
|
*/
|
|
45
|
-
type MnemocyteErrorCode = "CONFIG" | "VALIDATION" | "DB" | "EMBEDDING" | "NOT_FOUND" | "MIGRATION" | "TIMEOUT" | "ABORTED";
|
|
49
|
+
type MnemocyteErrorCode = "CONFIG" | "VALIDATION" | "DB" | "EMBEDDING" | "NOT_FOUND" | "CONFLICT" | "MIGRATION" | "TIMEOUT" | "ABORTED";
|
|
46
50
|
/**
|
|
47
51
|
* Error type thrown by every public Mnemocyte API.
|
|
48
52
|
*
|
|
@@ -86,5 +90,5 @@ declare class MnemocyteError extends Error {
|
|
|
86
90
|
*/
|
|
87
91
|
declare function isMnemocyteError(error: unknown): error is MnemocyteError;
|
|
88
92
|
//#endregion
|
|
89
|
-
export { type AuditConfig, type AuditEvent, type BuildContextInput, type ConsolidateInput, type ConsolidateResult, type ContextFormat, type DuplicatePair, type Embedder, type EntityStats, type ExperimentalMnemocyteClient, type FindDuplicatesInput, type GlobalStats, type ImportanceLevel, type JsonObject, type JsonValue, type ListAuditLogInput, type Memory, type MemoryType, type MemoryWithScore, type MnemocyteBackend, type MnemocyteClient, type MnemocyteConfig, MnemocyteError, type MnemocyteErrorCode, type MnemocyteObservation, type MnemocyteObservationPhase, type MnemocyteOperation, type ObservabilityConfig, type ProviderResilienceConfig, type PruneInput, type PruneResult, type RecallInput, type RememberInput, type RememberManyInput, type RetrievalConfig, type RetrievalExplanation, type RetrievalScoreWeights, type RetrievalScores, type TokenCounter, createMnemocyte, isMnemocyteError };
|
|
93
|
+
export { type AuditConfig, type AuditEvent, type AuditLogCursor, type BuildContextInput, type ConsolidateInput, type ConsolidateResult, type ContextFormat, type DuplicatePair, type Embedder, type EntityStats, type ExperimentalMnemocyteClient, type FindDuplicatesInput, type GlobalStats, type ImportanceLevel, type JsonObject, type JsonValue, type ListAuditLogInput, type Memory, type MemoryType, type MemoryWithScore, type MnemocyteBackend, type MnemocyteClient, type MnemocyteConfig, MnemocyteError, type MnemocyteErrorCode, type MnemocyteObservation, type MnemocyteObservationPhase, type MnemocyteOperation, type MnemocyteStoreConfig, type ObservabilityConfig, type ProviderResilienceConfig, type PruneInput, type PruneResult, type RecallInput, type RememberInput, type RememberManyInput, type RetrievalConfig, type RetrievalExplanation, type RetrievalScoreWeights, type RetrievalScores, type TokenCounter, createMnemocyte, isMnemocyteError };
|
|
90
94
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/client.ts","../src/errors.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/client.ts","../src/errors.ts"],"mappings":";;;;;AA2CA;;;;;;;;AAAyE;;;;AC9BzE;;;;AAA8B;AA8B9B;;;;;;;;;;iBDAgB,eAAA,CAAgB,MAAA,EAAQ,eAAA,GAAkB,eAAe;;;;;;AAAzE;;;;;;;;AAAyE;;KC9B7D,kBAAA;;AAAZ;;;;AAA8B;AA8B9B;;;;;;;;;;;;;cAAa,cAAA,SAAuB,KAAA;EAWA;EAAA,SAT1B,IAAA,EAAM,kBAAA;EASwC;EAAA,SAPrC,KAAA;EAOoD;AAkBvE;;;;cAlBa,OAAA,UAAiB,IAAA,EAAM,kBAAA,EAAoB,KAAA;AAAA;;;AAkBiB;;;;;;;;iBAAzD,gBAAA,CAAiB,KAAA,YAAiB,KAAA,IAAS,cAAc"}
|