mnemocyte 0.1.5 → 0.2.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 +72 -9
- package/dist/embedders/openai.d.mts +1 -1
- package/dist/index.d.mts +3 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +48 -9
- package/dist/index.mjs.map +1 -1
- package/dist/{types-QK_43oKJ.d.mts → types-DXEGcc47.d.mts} +3 -2
- package/dist/types-DXEGcc47.d.mts.map +1 -0
- package/migrations/0000_initial.sql.template +42 -0
- package/migrations/0001_add_mnemocyte_meta.sql +6 -0
- package/migrations/meta/0001_snapshot.json +309 -0
- package/migrations/meta/_journal.json +7 -0
- package/migrations/render-initial.mjs +36 -0
- package/package.json +2 -1
- package/dist/types-QK_43oKJ.d.mts.map +0 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ logs, and duplicate-consolidation tools on top of your existing infrastructure.
|
|
|
16
16
|
- Hybrid recall with vector similarity, lexical matching, recency, confidence,
|
|
17
17
|
access count, and importance.
|
|
18
18
|
- Prompt-ready context output in Markdown, plain text, or XML.
|
|
19
|
-
- Provider
|
|
19
|
+
- Provider retries, operation timeouts, and caller `AbortSignal` cancellation.
|
|
20
20
|
- Pruning, duplicate detection, audit logs, and experimental consolidation.
|
|
21
21
|
|
|
22
22
|
Mnemocyte is ESM-only. Use `import`, not CommonJS `require`.
|
|
@@ -103,8 +103,8 @@ supported for consumers that prefer provider-specific imports.
|
|
|
103
103
|
|
|
104
104
|
## Postgres
|
|
105
105
|
|
|
106
|
-
For persistent storage,
|
|
107
|
-
|
|
106
|
+
For persistent storage, enable pgvector in your Postgres database, apply the
|
|
107
|
+
bundled migrations, then pass `databaseUrl`.
|
|
108
108
|
|
|
109
109
|
```ts
|
|
110
110
|
const client = createMnemocyte({
|
|
@@ -117,13 +117,46 @@ The package includes:
|
|
|
117
117
|
|
|
118
118
|
```txt
|
|
119
119
|
migrations/0000_initial.sql
|
|
120
|
+
migrations/0001_add_mnemocyte_meta.sql
|
|
121
|
+
migrations/0000_initial.sql.template
|
|
122
|
+
migrations/render-initial.mjs
|
|
120
123
|
```
|
|
121
124
|
|
|
122
|
-
|
|
123
|
-
|
|
125
|
+
For the default 1536-dimensional schema on a fresh install, apply these in
|
|
126
|
+
order:
|
|
124
127
|
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
```txt
|
|
129
|
+
migrations/0000_initial.sql
|
|
130
|
+
migrations/0001_add_mnemocyte_meta.sql
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
For an existing 0.1.x Postgres install, apply
|
|
134
|
+
`migrations/0001_add_mnemocyte_meta.sql` to record the current 1536-dimensional
|
|
135
|
+
installation metadata.
|
|
136
|
+
|
|
137
|
+
For a different embedding dimension on a fresh installation, render an explicit
|
|
138
|
+
initial migration from the template and apply that rendered file instead of the
|
|
139
|
+
default `0000_initial.sql`. The rendered initial migration includes the
|
|
140
|
+
matching `mnemocyte_meta` row.
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
node node_modules/mnemocyte/migrations/render-initial.mjs --dimensions 768 --out migrations/0000_initial.768.sql
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Inside this repository, the equivalent development shortcut is:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
pnpm migration:render -- --dimensions 768 --out migrations/0000_initial.768.sql
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The Postgres backend supports one embedding dimension per installation. On the
|
|
153
|
+
first Postgres operation, Mnemocyte reads `mnemocyte_meta` and validates it
|
|
154
|
+
against `embedder.dimensions` before calling the embedder. A mismatch throws a
|
|
155
|
+
`MnemocyteError` with code `"CONFIG"`; missing v0.2.0 metadata throws code
|
|
156
|
+
`"MIGRATION"`.
|
|
157
|
+
|
|
158
|
+
Use the embedding dimension documented for your chosen model, render or apply a
|
|
159
|
+
matching schema, and keep one dimension per Mnemocyte installation.
|
|
127
160
|
|
|
128
161
|
The migration creates the bundled HNSW pgvector index
|
|
129
162
|
`mnemocyte_memories_embedding_hnsw_idx` for cosine search. HNSW is approximate:
|
|
@@ -141,7 +174,8 @@ add full-text or tag-specific GIN indexes yet; add and benchmark expression
|
|
|
141
174
|
indexes such as `to_tsvector('english', content)` or tag-oriented indexes only
|
|
142
175
|
when your workload needs them.
|
|
143
176
|
|
|
144
|
-
|
|
177
|
+
Existing 0.1.x deployments remain on 1536 unless you plan and run your own
|
|
178
|
+
Postgres migration to a different pgvector dimension.
|
|
145
179
|
|
|
146
180
|
## API
|
|
147
181
|
|
|
@@ -266,6 +300,7 @@ VALIDATION
|
|
|
266
300
|
CONFIG
|
|
267
301
|
DB
|
|
268
302
|
NOT_FOUND
|
|
303
|
+
MIGRATION
|
|
269
304
|
```
|
|
270
305
|
|
|
271
306
|
## Retrieval Tuning
|
|
@@ -293,13 +328,41 @@ const client = createMnemocyte({
|
|
|
293
328
|
|
|
294
329
|
Planned larger milestones:
|
|
295
330
|
|
|
296
|
-
- configurable embedding dimensions with `mnemocyte_meta`
|
|
297
331
|
- `MemoryStore` abstraction
|
|
298
332
|
- `drizzleStore(db)` for caller-owned Drizzle clients
|
|
299
333
|
- `@mnemocyte/mcp`
|
|
300
334
|
|
|
301
335
|
See [ROADMAP.md](./ROADMAP.md).
|
|
302
336
|
|
|
337
|
+
## Pre-v1 Notes
|
|
338
|
+
|
|
339
|
+
Current behavior:
|
|
340
|
+
|
|
341
|
+
- `createMnemocyte()` selects either the in-memory backend or the
|
|
342
|
+
Postgres/pgvector backend.
|
|
343
|
+
- Postgres schema setup is explicit; the client does not create tables or
|
|
344
|
+
indexes for you.
|
|
345
|
+
- `findDuplicates`, audit-log workflows, and `experimental.consolidate` are
|
|
346
|
+
available before v1 but still subject to API refinement.
|
|
347
|
+
|
|
348
|
+
Known limitations before v1:
|
|
349
|
+
|
|
350
|
+
- The two current backends share behavior by convention rather than through a
|
|
351
|
+
formal `MemoryStore` adapter boundary.
|
|
352
|
+
- Configured provider timeouts fail the Mnemocyte operation with `"TIMEOUT"`;
|
|
353
|
+
actively aborting the underlying provider request on timeout remains a
|
|
354
|
+
pre-v1 hardening follow-up.
|
|
355
|
+
- Postgres dimension metadata is installation-wide. Mixed embedding dimensions
|
|
356
|
+
in one database are intentionally out of scope for now.
|
|
357
|
+
|
|
358
|
+
Planned v1 direction:
|
|
359
|
+
|
|
360
|
+
- Extract a `MemoryStore` boundary so storage adapters own persistence while
|
|
361
|
+
shared core code owns validation, embedding, scoring, observability,
|
|
362
|
+
resilience, and context building.
|
|
363
|
+
- Keep root `mnemocyte` imports provider-SDK-free.
|
|
364
|
+
- Keep migrations, dimensions, and production index choices explicit.
|
|
365
|
+
|
|
303
366
|
## Development
|
|
304
367
|
|
|
305
368
|
```bash
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as RetrievalConfig, C as MnemocyteOperation, D as PruneResult, E as PruneInput, M as RetrievalScoreWeights, N as RetrievalScores, O as RecallInput, P as TokenCounter, S as MnemocyteObservationPhase, T as ProviderResilienceConfig, _ as MemoryWithScore, a as ConsolidateResult, b as MnemocyteConfig, c as Embedder, d as FindDuplicatesInput, f as GlobalStats, g as MemoryType, h as Memory, i as ConsolidateInput, j as RetrievalExplanation, k as RememberInput, l as EntityStats, m as ListAuditLogInput, n as AuditEvent, o as ContextFormat, p as ImportanceLevel, r as BuildContextInput, s as DuplicatePair, t as AuditConfig, u as ExperimentalMnemocyteClient, v as MnemocyteBackend, w as ObservabilityConfig, x as MnemocyteObservation, y as MnemocyteClient } from "./types-
|
|
1
|
+
import { A as RetrievalConfig, C as MnemocyteOperation, D as PruneResult, E as PruneInput, M as RetrievalScoreWeights, N as RetrievalScores, O as RecallInput, P as TokenCounter, S as MnemocyteObservationPhase, T as ProviderResilienceConfig, _ as MemoryWithScore, a as ConsolidateResult, b as MnemocyteConfig, c as Embedder, d as FindDuplicatesInput, f as GlobalStats, g as MemoryType, h as Memory, i as ConsolidateInput, j as RetrievalExplanation, k as RememberInput, l as EntityStats, m as ListAuditLogInput, n as AuditEvent, o as ContextFormat, p as ImportanceLevel, r as BuildContextInput, s as DuplicatePair, t as AuditConfig, u as ExperimentalMnemocyteClient, v as MnemocyteBackend, w as ObservabilityConfig, x as MnemocyteObservation, y as MnemocyteClient } from "./types-DXEGcc47.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/client.d.ts
|
|
4
4
|
/**
|
|
@@ -16,15 +16,13 @@ import { A as RetrievalConfig, C as MnemocyteOperation, D as PruneResult, E as P
|
|
|
16
16
|
* @param config - Client configuration. {@link MnemocyteConfig.embedder} is required.
|
|
17
17
|
* @returns A {@link MnemocyteClient} instance.
|
|
18
18
|
* @throws {MnemocyteError} With code `"CONFIG"` if `embedder` is missing or
|
|
19
|
-
* invalid
|
|
20
|
-
* is not 1536 — the dimensionality pinned by the bundled migration), or
|
|
21
|
-
* `"VALIDATION"` if `databaseUrl` is provided but empty.
|
|
19
|
+
* invalid, or `"VALIDATION"` if `databaseUrl` is provided but empty.
|
|
22
20
|
*
|
|
23
21
|
* @example Postgres-backed client
|
|
24
22
|
* ```ts
|
|
25
23
|
* const client = createMnemocyte({
|
|
26
24
|
* databaseUrl: process.env.DATABASE_URL,
|
|
27
|
-
* embedder, // embedder.dimensions
|
|
25
|
+
* embedder, // embedder.dimensions must match mnemocyte_meta
|
|
28
26
|
* });
|
|
29
27
|
* ```
|
|
30
28
|
*/
|
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":";;;;;AA+BA;;;;;;;;AAAyE;;;;ACnBzE;;;;AAA8B;AA6B9B;;;;;;iBDVgB,eAAA,CAAgB,MAAA,EAAQ,eAAA,GAAkB,eAAe;;;;;;AAAzE;;;;;;;;AAAyE;KCnB7D,kBAAA;;;AAAZ;;;;AAA8B;AA6B9B;;;;;;;;;;;;cAAa,cAAA,SAAuB,KAAA;EAWvB;EAAA,SATH,IAAA,EAAM,kBAAA;EASc;EAAA,SAPX,KAAA;EAOoD;AAAA;AAiBvE;;;cAjBa,OAAA,UAAiB,IAAA,EAAM,kBAAA,EAAoB,KAAA;AAAA;;;;AAiBiB;;;;;;iBAAzD,gBAAA,CAAiB,KAAA,YAAiB,KAAA,IAAS,cAAc"}
|
package/dist/index.mjs
CHANGED
|
@@ -18,11 +18,12 @@ var __exportAll = (all, no_symbols) => {
|
|
|
18
18
|
//#region src/db/schema.ts
|
|
19
19
|
var schema_exports = /* @__PURE__ */ __exportAll({
|
|
20
20
|
eventsTable: () => eventsTable,
|
|
21
|
-
memoriesTable: () => memoriesTable
|
|
21
|
+
memoriesTable: () => memoriesTable,
|
|
22
|
+
metaTable: () => metaTable
|
|
22
23
|
});
|
|
23
24
|
const vector = customType({
|
|
24
25
|
dataType(config) {
|
|
25
|
-
return `vector(${
|
|
26
|
+
return `vector(${config?.dimensions ?? 1536})`;
|
|
26
27
|
},
|
|
27
28
|
toDriver(value) {
|
|
28
29
|
return `[${value.map(formatVectorComponent$1).join(",")}]`;
|
|
@@ -67,6 +68,10 @@ const eventsTable = pgTable("mnemocyte_events", {
|
|
|
67
68
|
metadata: jsonb("metadata").notNull().default({}),
|
|
68
69
|
timestamp: timestamp("timestamp", { withTimezone: true }).notNull().defaultNow()
|
|
69
70
|
}, (table) => [index("mnemocyte_events_entity_time_idx").on(table.entityId, table.timestamp)]);
|
|
71
|
+
const metaTable = pgTable("mnemocyte_meta", {
|
|
72
|
+
key: text("key").primaryKey(),
|
|
73
|
+
embeddingDimensions: integer("embedding_dimensions").notNull()
|
|
74
|
+
});
|
|
70
75
|
//#endregion
|
|
71
76
|
//#region src/db/index.ts
|
|
72
77
|
function parseSslFromUrl(url) {
|
|
@@ -1393,6 +1398,9 @@ async function lexicalSearch(db, input) {
|
|
|
1393
1398
|
LIMIT ${input.limit}
|
|
1394
1399
|
`);
|
|
1395
1400
|
}
|
|
1401
|
+
async function getInstallationMeta(db) {
|
|
1402
|
+
return (await db.select().from(metaTable).where(eq(metaTable.key, "installation")).limit(1))[0] ?? null;
|
|
1403
|
+
}
|
|
1396
1404
|
//#endregion
|
|
1397
1405
|
//#region src/retrieval/index.ts
|
|
1398
1406
|
async function hybridRecall(input) {
|
|
@@ -1458,6 +1466,9 @@ const IMPORTANCE_LEVELS = [
|
|
|
1458
1466
|
function importanceCeilingLevels(max) {
|
|
1459
1467
|
return IMPORTANCE_LEVELS.filter((level) => IMPORTANCE_RANK[level] <= IMPORTANCE_RANK[max]);
|
|
1460
1468
|
}
|
|
1469
|
+
function hasPostgresErrorCode(error, code) {
|
|
1470
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
1471
|
+
}
|
|
1461
1472
|
function toPruneFilter(input) {
|
|
1462
1473
|
const filter = {};
|
|
1463
1474
|
if (input.entityId !== void 0) filter.entityId = input.entityId;
|
|
@@ -1472,9 +1483,31 @@ function toPruneFilter(input) {
|
|
|
1472
1483
|
}
|
|
1473
1484
|
function createPostgresClient(config, handle) {
|
|
1474
1485
|
let closed = false;
|
|
1486
|
+
let schemaValidated = false;
|
|
1487
|
+
let schemaValidationPromise;
|
|
1475
1488
|
function assertOpen() {
|
|
1476
1489
|
if (closed) throw new MnemocyteError("Mnemocyte client is closed.", "DB");
|
|
1477
1490
|
}
|
|
1491
|
+
async function ensureSchemaMatchesEmbedder() {
|
|
1492
|
+
if (schemaValidated) return;
|
|
1493
|
+
if (!schemaValidationPromise) schemaValidationPromise = validateSchemaMatchesEmbedder().catch((error) => {
|
|
1494
|
+
schemaValidationPromise = void 0;
|
|
1495
|
+
throw error;
|
|
1496
|
+
});
|
|
1497
|
+
await schemaValidationPromise;
|
|
1498
|
+
}
|
|
1499
|
+
async function validateSchemaMatchesEmbedder() {
|
|
1500
|
+
let meta;
|
|
1501
|
+
try {
|
|
1502
|
+
meta = await getInstallationMeta(handle.db);
|
|
1503
|
+
} catch (error) {
|
|
1504
|
+
if (hasPostgresErrorCode(error, "42P01")) throw new MnemocyteError("mnemocyte_meta is missing. Apply the v0.2.0 migration or render a dimension-specific initial migration before using the Postgres backend.", "MIGRATION", error);
|
|
1505
|
+
throw error;
|
|
1506
|
+
}
|
|
1507
|
+
if (!meta) throw new MnemocyteError("mnemocyte_meta is missing the \"installation\" row. Apply the v0.2.0 migration or render a dimension-specific initial migration before using the Postgres backend.", "MIGRATION");
|
|
1508
|
+
if (meta.embeddingDimensions !== config.embedder.dimensions) throw new MnemocyteError(`embedder.dimensions (${config.embedder.dimensions}) must match mnemocyte_meta.embedding_dimensions (${meta.embeddingDimensions}). Render and apply a migration for the selected embedding dimension, or configure an embedder that matches this installation.`, "CONFIG");
|
|
1509
|
+
schemaValidated = true;
|
|
1510
|
+
}
|
|
1478
1511
|
async function recordAudit(entityId, description, metadata) {
|
|
1479
1512
|
if (config.audit?.enabled !== true) return;
|
|
1480
1513
|
try {
|
|
@@ -1491,6 +1524,7 @@ function createPostgresClient(config, handle) {
|
|
|
1491
1524
|
return observe(config, "postgres", "remember", { entityId: input.entityId }, async () => {
|
|
1492
1525
|
assertOpen();
|
|
1493
1526
|
validateRememberInput(input);
|
|
1527
|
+
await ensureSchemaMatchesEmbedder();
|
|
1494
1528
|
const embedding = await embedOne(config.embedder, input.content, {
|
|
1495
1529
|
...input.signal === void 0 ? {} : { signal: input.signal },
|
|
1496
1530
|
...config.provider === void 0 ? {} : { resilience: config.provider }
|
|
@@ -1535,6 +1569,7 @@ function createPostgresClient(config, handle) {
|
|
|
1535
1569
|
assertOpen();
|
|
1536
1570
|
if (inputs.length === 0) return [];
|
|
1537
1571
|
for (const input of inputs) validateRememberInput(input);
|
|
1572
|
+
await ensureSchemaMatchesEmbedder();
|
|
1538
1573
|
const embeddings = await embedMany(config.embedder, inputs.map((i) => i.content), {
|
|
1539
1574
|
...inputs[0]?.signal === void 0 ? {} : { signal: inputs[0].signal },
|
|
1540
1575
|
...config.provider === void 0 ? {} : { resilience: config.provider }
|
|
@@ -1578,6 +1613,7 @@ function createPostgresClient(config, handle) {
|
|
|
1578
1613
|
const minScore = input.minScore ?? config.defaults?.minScore ?? 0;
|
|
1579
1614
|
assertLimit(limit);
|
|
1580
1615
|
assertMinScore(minScore);
|
|
1616
|
+
await ensureSchemaMatchesEmbedder();
|
|
1581
1617
|
return hybridRecall({
|
|
1582
1618
|
db: handle.db,
|
|
1583
1619
|
embedder: config.embedder,
|
|
@@ -1593,6 +1629,7 @@ function createPostgresClient(config, handle) {
|
|
|
1593
1629
|
async buildContext(input) {
|
|
1594
1630
|
return observe(config, "postgres", "buildContext", { entityId: input.entityId }, async () => {
|
|
1595
1631
|
assertOpen();
|
|
1632
|
+
await ensureSchemaMatchesEmbedder();
|
|
1596
1633
|
return buildContext({
|
|
1597
1634
|
input,
|
|
1598
1635
|
recall: (contextInput) => {
|
|
@@ -1613,6 +1650,7 @@ function createPostgresClient(config, handle) {
|
|
|
1613
1650
|
assertOpen();
|
|
1614
1651
|
assertNonEmptyString(input.entityId, "entityId");
|
|
1615
1652
|
assertNonEmptyString(input.memoryId, "memoryId");
|
|
1653
|
+
await ensureSchemaMatchesEmbedder();
|
|
1616
1654
|
if (!await deleteMemory(handle.db, input.entityId, input.memoryId)) throw new MnemocyteError("Memory was not found.", "NOT_FOUND");
|
|
1617
1655
|
await recordAudit(input.entityId, "memory.deleted", { memoryId: input.memoryId });
|
|
1618
1656
|
});
|
|
@@ -1621,6 +1659,7 @@ function createPostgresClient(config, handle) {
|
|
|
1621
1659
|
return observe(config, "postgres", "forgetAll", { entityId: input.entityId }, async () => {
|
|
1622
1660
|
assertOpen();
|
|
1623
1661
|
assertNonEmptyString(input.entityId, "entityId");
|
|
1662
|
+
await ensureSchemaMatchesEmbedder();
|
|
1624
1663
|
const deletedCount = await deleteMemoriesForEntity(handle.db, input.entityId);
|
|
1625
1664
|
await recordAudit(input.entityId, "entity.cleared", { count: deletedCount });
|
|
1626
1665
|
return deletedCount;
|
|
@@ -1630,6 +1669,7 @@ function createPostgresClient(config, handle) {
|
|
|
1630
1669
|
return observe(config, "postgres", "prune", input.entityId === void 0 ? {} : { entityId: input.entityId }, async () => {
|
|
1631
1670
|
assertOpen();
|
|
1632
1671
|
validatePruneInput(input);
|
|
1672
|
+
await ensureSchemaMatchesEmbedder();
|
|
1633
1673
|
const filter = toPruneFilter(input);
|
|
1634
1674
|
if (input.dryRun === true) return {
|
|
1635
1675
|
matchedCount: await countPruneMatches(handle.db, filter),
|
|
@@ -1649,6 +1689,7 @@ function createPostgresClient(config, handle) {
|
|
|
1649
1689
|
return observe(config, "postgres", "findDuplicates", { entityId: input.entityId }, async () => {
|
|
1650
1690
|
assertOpen();
|
|
1651
1691
|
validateFindDuplicatesInput(input);
|
|
1692
|
+
await ensureSchemaMatchesEmbedder();
|
|
1652
1693
|
const threshold = input.threshold ?? .95;
|
|
1653
1694
|
const limit = input.limit ?? 100;
|
|
1654
1695
|
return (await findDuplicatePairs(handle.db, {
|
|
@@ -1670,6 +1711,7 @@ function createPostgresClient(config, handle) {
|
|
|
1670
1711
|
return observe(config, "postgres", "listAuditLog", { entityId: input.entityId }, async () => {
|
|
1671
1712
|
assertOpen();
|
|
1672
1713
|
validateListAuditLogInput(input);
|
|
1714
|
+
await ensureSchemaMatchesEmbedder();
|
|
1673
1715
|
return (await listEvents(handle.db, {
|
|
1674
1716
|
entityId: input.entityId,
|
|
1675
1717
|
limit: input.limit ?? 50,
|
|
@@ -1681,6 +1723,7 @@ function createPostgresClient(config, handle) {
|
|
|
1681
1723
|
async stats(input) {
|
|
1682
1724
|
return observe(config, "postgres", "stats", input?.entityId ? { entityId: input.entityId } : {}, async () => {
|
|
1683
1725
|
assertOpen();
|
|
1726
|
+
await ensureSchemaMatchesEmbedder();
|
|
1684
1727
|
const now = /* @__PURE__ */ new Date();
|
|
1685
1728
|
if (input?.entityId) {
|
|
1686
1729
|
const counts = await getEntityMemoryStatsCounts(handle.db, input.entityId, now);
|
|
@@ -1709,6 +1752,7 @@ function createPostgresClient(config, handle) {
|
|
|
1709
1752
|
}, async () => {
|
|
1710
1753
|
assertOpen();
|
|
1711
1754
|
validateConsolidateInput(input);
|
|
1755
|
+
await ensureSchemaMatchesEmbedder();
|
|
1712
1756
|
const survivor = await getMemoryById(handle.db, input.entityId, input.survivorId);
|
|
1713
1757
|
if (!survivor) throw new MnemocyteError("Survivor memory was not found.", "NOT_FOUND");
|
|
1714
1758
|
if (survivor.supersededBy !== null) throw new MnemocyteError("Survivor memory is itself superseded.", "VALIDATION");
|
|
@@ -1766,8 +1810,6 @@ function createPostgresClient(config, handle) {
|
|
|
1766
1810
|
}
|
|
1767
1811
|
//#endregion
|
|
1768
1812
|
//#region src/client.ts
|
|
1769
|
-
/** Embedding dimensionality pinned by `migrations/0000_initial.sql`. */
|
|
1770
|
-
const POSTGRES_EMBEDDING_DIMENSIONS = 1536;
|
|
1771
1813
|
/**
|
|
1772
1814
|
* Create a Mnemocyte client.
|
|
1773
1815
|
*
|
|
@@ -1783,15 +1825,13 @@ const POSTGRES_EMBEDDING_DIMENSIONS = 1536;
|
|
|
1783
1825
|
* @param config - Client configuration. {@link MnemocyteConfig.embedder} is required.
|
|
1784
1826
|
* @returns A {@link MnemocyteClient} instance.
|
|
1785
1827
|
* @throws {MnemocyteError} With code `"CONFIG"` if `embedder` is missing or
|
|
1786
|
-
* invalid
|
|
1787
|
-
* is not 1536 — the dimensionality pinned by the bundled migration), or
|
|
1788
|
-
* `"VALIDATION"` if `databaseUrl` is provided but empty.
|
|
1828
|
+
* invalid, or `"VALIDATION"` if `databaseUrl` is provided but empty.
|
|
1789
1829
|
*
|
|
1790
1830
|
* @example Postgres-backed client
|
|
1791
1831
|
* ```ts
|
|
1792
1832
|
* const client = createMnemocyte({
|
|
1793
1833
|
* databaseUrl: process.env.DATABASE_URL,
|
|
1794
|
-
* embedder, // embedder.dimensions
|
|
1834
|
+
* embedder, // embedder.dimensions must match mnemocyte_meta
|
|
1795
1835
|
* });
|
|
1796
1836
|
* ```
|
|
1797
1837
|
*/
|
|
@@ -1799,7 +1839,6 @@ function createMnemocyte(config) {
|
|
|
1799
1839
|
assertEmbedder(config.embedder);
|
|
1800
1840
|
if (config.databaseUrl) {
|
|
1801
1841
|
assertNonEmptyString(config.databaseUrl, "databaseUrl");
|
|
1802
|
-
if (config.embedder.dimensions !== POSTGRES_EMBEDDING_DIMENSIONS) throw new MnemocyteError(`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}).`, "CONFIG");
|
|
1803
1842
|
return createPostgresClient(config, createDatabase(config.databaseUrl));
|
|
1804
1843
|
}
|
|
1805
1844
|
return createInMemoryClient(config);
|