mnemocyte 0.0.8 → 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,134 +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
- ## Postgres usage
61
+ When `databaseUrl` is omitted, Mnemocyte uses the in-memory backend.
56
62
 
57
- Run the included migration against a Postgres database with pgvector enabled, then pass `databaseUrl`:
63
+ ## Postgres
64
+
65
+ Apply the bundled migration to a Postgres database with pgvector enabled, then
66
+ pass `databaseUrl`:
58
67
 
59
68
  ```ts
60
69
  const client = createMnemocyte({
61
- databaseUrl: process.env.DATABASE_URL,
62
- embedder,
70
+ databaseUrl: process.env.DATABASE_URL,
71
+ embedder, // embedder.dimensions must be 1536 for the Postgres backend.
63
72
  });
64
73
  ```
65
74
 
66
75
  The published package includes `migrations/0000_initial.sql`.
67
76
 
68
- ## Provider resilience
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.
81
+
82
+ ## Provider Resilience
69
83
 
70
- Mnemocyte applies an optional timeout and retry policy to every outbound
71
- embedder call, and forwards `AbortSignal` cancellation to in-flight
72
- attempts. Defaults disable both retries and timeouts so existing setups
73
- 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.
74
87
 
75
88
  ```ts
76
89
  const client = createMnemocyte({
77
- embedder,
78
- provider: {
79
- timeoutMs: 5_000,
80
- retries: 2,
81
- baseDelayMs: 200,
82
- maxDelayMs: 2_000,
83
- },
90
+ embedder,
91
+ provider: {
92
+ timeoutMs: 5_000,
93
+ retries: 2,
94
+ baseDelayMs: 200,
95
+ maxDelayMs: 2_000,
96
+ },
84
97
  });
85
98
 
86
99
  const controller = new AbortController();
87
100
  setTimeout(() => controller.abort(), 1_000);
88
101
 
89
102
  await client.remember({
90
- entityId: "user_123",
91
- content: "Prefers short answers.",
92
- signal: controller.signal,
103
+ entityId: "user_123",
104
+ content: "Prefers short answers.",
105
+ signal: controller.signal,
93
106
  });
94
107
  ```
95
108
 
96
- Failures surface as `MnemocyteError` with stable `code`s:
109
+ Provider failures surface as `MnemocyteError` values with stable `code`s:
97
110
 
98
- - `"TIMEOUT"` — a single provider attempt exceeded `timeoutMs`.
99
- - `"ABORTED"` — the operation was cancelled via `signal` (never retried).
100
- - `"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.
101
114
 
102
- ## Pruning memories
115
+ ## Pruning
103
116
 
104
- `prune` bulk-deletes memories matching a filter. At least one selector
105
- 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.
106
119
 
107
120
  ```ts
108
- // Drop expired memories for one entity.
109
121
  await client.prune({ entityId: "user_123", expired: true });
110
122
 
111
- // Evict memories not accessed in the last 30 days, but never drop
112
- // "high" or "critical" memories.
113
123
  await client.prune({
114
- notAccessedSince: new Date(Date.now() - 30 * 24 * 3600 * 1000),
115
- maxImportance: "normal",
124
+ notAccessedSince: new Date(Date.now() - 30 * 24 * 3600 * 1000),
125
+ maxImportance: "normal",
116
126
  });
117
127
 
118
- // Count what would be deleted without touching the store.
119
128
  const preview = await client.prune({
120
- entityId: "user_123",
121
- superseded: true,
122
- dryRun: true,
129
+ entityId: "user_123",
130
+ superseded: true,
131
+ dryRun: true,
123
132
  });
124
133
  console.log(preview.matchedCount);
125
134
  ```
126
135
 
127
136
  Available selectors: `entityId`, `expired`, `superseded`, `createdBefore`,
128
- `notAccessedSince`, `types`, `tags`, `maxImportance`. They AND together.
137
+ `notAccessedSince`, `types`, `tags`, `maxImportance`. Selectors are combined
138
+ with AND semantics.
139
+
140
+ ## Duplicate Detection
141
+
142
+ `findDuplicates` is an experimental, read-only scan that surfaces
143
+ near-identical memories for one entity using pairwise cosine similarity.
144
+
145
+ ```ts
146
+ const pairs = await client.findDuplicates({
147
+ entityId: "user_123",
148
+ threshold: 0.95,
149
+ limit: 50,
150
+ });
151
+
152
+ for (const { a, b, similarity } of pairs) {
153
+ console.log(similarity.toFixed(3), a.content, "<>", b.content);
154
+ }
155
+ ```
156
+
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.
160
+
161
+ ## Audit Log
162
+
163
+ When `audit.enabled` is `true`, Mnemocyte records an entry for state-changing
164
+ operations. Read entries with `client.listAuditLog()`.
165
+
166
+ ```ts
167
+ const client = createMnemocyte({
168
+ embedder,
169
+ audit: { enabled: true },
170
+ });
171
+
172
+ await client.remember({ entityId: "user_123", content: "Likes tea." });
173
+ await client.prune({ entityId: "user_123", expired: true });
174
+
175
+ const log = await client.listAuditLog({
176
+ entityId: "user_123",
177
+ limit: 100,
178
+ });
179
+
180
+ for (const event of log) {
181
+ console.log(event.timestamp, event.description, event.metadata);
182
+ }
183
+ ```
184
+
185
+ Recorded `description` slugs:
186
+
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.
192
+
193
+ Audit entries are sticky: `forgetAll` does not erase prior log entries. Disable
194
+ audit by leaving `audit.enabled` unset.
195
+
196
+ ## Consolidation
197
+
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`.
201
+
202
+ ```ts
203
+ const pairs = await client.findDuplicates({
204
+ entityId: "user_123",
205
+ threshold: 0.97,
206
+ });
207
+
208
+ for (const { a, b } of pairs) {
209
+ await client.experimental.consolidate({
210
+ entityId: "user_123",
211
+ survivorId: a.id,
212
+ supersededIds: [b.id],
213
+ });
214
+ }
215
+ ```
216
+
217
+ The `experimental` namespace is intentionally unstable. Members may change or
218
+ move before v1.0.
129
219
 
130
- ## Retrieval tuning
220
+ ## Retrieval Tuning
131
221
 
132
222
  ```ts
133
223
  const client = createMnemocyte({
134
- embedder,
135
- retrieval: {
136
- weights: {
137
- vector: 0.55,
138
- lexical: 0.2,
139
- recency: 0.1,
140
- confidence: 0.05,
141
- access: 0.05,
142
- importance: 0.05,
143
- },
144
- recencyHalfLifeDays: 90,
145
- accessSaturation: 10,
146
- candidateMultiplier: 3,
147
- },
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
+ },
148
238
  });
149
239
  ```
150
240
 
151
- ## Development checks
241
+ ## Development
152
242
 
153
243
  ```bash
154
244
  pnpm checktypes
@@ -162,4 +252,5 @@ pnpm run pack:check
162
252
 
163
253
  ## Architecture
164
254
 
165
- 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.d.mts CHANGED
@@ -40,7 +40,7 @@ type MnemocyteBackend = "in-memory" | "postgres";
40
40
  * The set of public {@link MnemocyteClient} methods that emit
41
41
  * {@link MnemocyteObservation} events through {@link ObservabilityConfig.onEvent}.
42
42
  */
43
- type MnemocyteOperation = "remember" | "rememberMany" | "recall" | "buildContext" | "forget" | "forgetAll" | "prune" | "stats" | "close";
43
+ type MnemocyteOperation = "remember" | "rememberMany" | "recall" | "buildContext" | "forget" | "forgetAll" | "prune" | "findDuplicates" | "listAuditLog" | "consolidate" | "stats" | "close";
44
44
  /**
45
45
  * Lifecycle phase of a {@link MnemocyteObservation}.
46
46
  *
@@ -149,6 +149,30 @@ interface MnemocyteConfig {
149
149
  * {@link ProviderResilienceConfig}.
150
150
  */
151
151
  provider?: ProviderResilienceConfig;
152
+ /**
153
+ * Audit-log configuration. When enabled, Mnemocyte records an
154
+ * {@link AuditEvent} for every state-changing operation
155
+ * (`remember`, `forget`, `forgetAll`, `prune`). Read with
156
+ * {@link MnemocyteClient.listAuditLog}.
157
+ *
158
+ * @experimental Part of Phase 6 (consolidation tooling).
159
+ */
160
+ audit?: AuditConfig;
161
+ }
162
+ /**
163
+ * Audit-log configuration. See {@link MnemocyteConfig.audit}.
164
+ *
165
+ * @experimental Part of Phase 6 (consolidation tooling).
166
+ */
167
+ interface AuditConfig {
168
+ /**
169
+ * Master switch for audit logging. When `false` (default), Mnemocyte
170
+ * neither writes nor relies on the audit log; existing log entries
171
+ * remain readable via {@link MnemocyteClient.listAuditLog}.
172
+ *
173
+ * @defaultValue `false`
174
+ */
175
+ enabled?: boolean;
152
176
  }
153
177
  /**
154
178
  * Pluggable embedding provider. Wraps an external embedding API
@@ -184,7 +208,7 @@ interface Embedder {
184
208
  * new memory and link the previous one via {@link Memory.supersededBy}.
185
209
  */
186
210
  interface Memory {
187
- /** Unique identifier (UUID for Postgres backend). */
211
+ /** Unique identifier (`mem_*` prefixed string). */
188
212
  id: string;
189
213
  /** Owning entity — typically a user, agent, or session ID. */
190
214
  entityId: string;
@@ -208,6 +232,13 @@ interface Memory {
208
232
  embeddingDimensions: number;
209
233
  /** ID of the memory that supersedes this one, or `null` if active. */
210
234
  supersededBy: string | null;
235
+ /**
236
+ * Wall-clock time when this memory was superseded, or `null` if it
237
+ * has not been superseded. Set together with
238
+ * {@link Memory.supersededBy} by
239
+ * {@link ExperimentalMnemocyteClient.consolidate}.
240
+ */
241
+ supersededAt: Date | null;
211
242
  /** Optional expiry; expired memories are filtered out by default. */
212
243
  expiresAt: Date | null;
213
244
  /** Last time this memory was returned by {@link MnemocyteClient.recall}. */
@@ -476,6 +507,142 @@ interface PruneResult {
476
507
  /** `true` when {@link PruneInput.dryRun} was set. */
477
508
  dryRun: boolean;
478
509
  }
510
+ /**
511
+ * Input for {@link MnemocyteClient.findDuplicates}.
512
+ *
513
+ * Performs a pairwise cosine-similarity scan of stored memories for a
514
+ * single entity and returns pairs whose similarity meets
515
+ * {@link FindDuplicatesInput.threshold}. The scan is read-only — no
516
+ * memories are modified or deleted.
517
+ *
518
+ * @experimental Part of Phase 6 (consolidation tooling). API may change.
519
+ */
520
+ interface FindDuplicatesInput {
521
+ /** Entity whose memories should be scanned for duplicates. */
522
+ entityId: string;
523
+ /**
524
+ * Cosine-similarity cutoff in `[0, 1]`. Pairs whose similarity is at
525
+ * or above this value are returned. @defaultValue `0.95`
526
+ */
527
+ threshold?: number;
528
+ /**
529
+ * Maximum number of duplicate pairs to return, ordered by descending
530
+ * similarity. @defaultValue `100`
531
+ */
532
+ limit?: number;
533
+ /** Restrict the scan to these memory types. */
534
+ types?: readonly MemoryType[];
535
+ /** Require both memories in the pair to include all of these tags. */
536
+ tags?: readonly string[];
537
+ /** Include superseded memories in the scan. @defaultValue `false` */
538
+ includeSuperseded?: boolean;
539
+ /** Include expired memories in the scan. @defaultValue `false` */
540
+ includeExpired?: boolean;
541
+ /** Optional cancellation signal. */
542
+ signal?: AbortSignal;
543
+ }
544
+ /**
545
+ * A pair of memories that are likely duplicates.
546
+ *
547
+ * The pair is unordered (i.e. `{a, b}` is the same logical result as
548
+ * `{b, a}`); Mnemocyte returns each pair only once.
549
+ *
550
+ * @experimental Part of Phase 6 (consolidation tooling). Shape may change.
551
+ */
552
+ interface DuplicatePair {
553
+ /** One of the two memories in the duplicate pair. */
554
+ a: Memory;
555
+ /** The other memory in the duplicate pair. */
556
+ b: Memory;
557
+ /** Cosine similarity between the two embeddings, in `[0, 1]`. */
558
+ similarity: number;
559
+ }
560
+ /**
561
+ * A single audit-log entry recording a state-changing operation.
562
+ *
563
+ * @experimental Part of Phase 6 (consolidation tooling).
564
+ */
565
+ interface AuditEvent {
566
+ /** Unique identifier (`evt_*` prefixed string). */
567
+ id: string;
568
+ /** Entity whose state was changed. */
569
+ entityId: string;
570
+ /**
571
+ * Stable, dotted slug describing the change. Examples:
572
+ * `"memory.created"`, `"memory.deleted"`, `"memory.pruned"`,
573
+ * `"entity.cleared"`.
574
+ */
575
+ description: string;
576
+ /** Free-form structured details about the change. */
577
+ metadata: Record<string, unknown>;
578
+ /** When the change was recorded. */
579
+ timestamp: Date;
580
+ }
581
+ /**
582
+ * Input for {@link MnemocyteClient.listAuditLog}.
583
+ *
584
+ * @experimental Part of Phase 6 (consolidation tooling).
585
+ */
586
+ interface ListAuditLogInput {
587
+ /** Entity whose audit log should be returned. */
588
+ entityId: string;
589
+ /**
590
+ * Maximum number of entries to return, ordered newest first.
591
+ * @defaultValue `50`
592
+ */
593
+ limit?: number;
594
+ /** Only return entries strictly before this timestamp. */
595
+ before?: Date;
596
+ /** Only return entries strictly after this timestamp. */
597
+ after?: Date;
598
+ /** Optional cancellation signal. */
599
+ signal?: AbortSignal;
600
+ }
601
+ /**
602
+ * Input for {@link ExperimentalMnemocyteClient.consolidate}.
603
+ *
604
+ * Marks each memory in {@link ConsolidateInput.supersededIds} as
605
+ * superseded by {@link ConsolidateInput.survivorId}. Optionally
606
+ * unions the losers' tags into the survivor.
607
+ *
608
+ * @experimental Part of Phase 6 (consolidation tooling).
609
+ */
610
+ interface ConsolidateInput {
611
+ /** Entity that owns every memory referenced. */
612
+ entityId: string;
613
+ /** Memory that should win the merge. Must not itself be superseded. */
614
+ survivorId: string;
615
+ /**
616
+ * Memories to mark as superseded by the survivor. Already-superseded
617
+ * entries in this list are skipped silently for idempotency. Must
618
+ * not contain {@link ConsolidateInput.survivorId}.
619
+ */
620
+ supersededIds: readonly string[];
621
+ /**
622
+ * When `true`, the survivor's `tags` becomes the union of its own
623
+ * tags and the tags of every memory that was actually superseded.
624
+ * @defaultValue `true`
625
+ */
626
+ mergeTags?: boolean;
627
+ /** Optional cancellation signal. */
628
+ signal?: AbortSignal;
629
+ }
630
+ /**
631
+ * Result returned by {@link ExperimentalMnemocyteClient.consolidate}.
632
+ *
633
+ * @experimental Part of Phase 6 (consolidation tooling).
634
+ */
635
+ interface ConsolidateResult {
636
+ /** Echoes {@link ConsolidateInput.survivorId}. */
637
+ survivorId: string;
638
+ /**
639
+ * Number of memories actually marked as superseded. Excludes entries
640
+ * that were already superseded (idempotent skip).
641
+ */
642
+ supersededCount: number;
643
+ /** The IDs that were newly superseded during this call. */
644
+ supersededIds: readonly string[];
645
+ }
479
646
  /**
480
647
  * Stats for a single entity, returned by
481
648
  * {@link MnemocyteClient.stats} when an `entityId` is provided.
@@ -572,6 +739,55 @@ interface MnemocyteClient {
572
739
  * ```
573
740
  */
574
741
  prune(input: PruneInput): Promise<PruneResult>;
742
+ /**
743
+ * Scan an entity's memories for likely duplicates by pairwise cosine
744
+ * similarity and return matching pairs, ordered by descending
745
+ * similarity. Read-only — no memories are modified.
746
+ *
747
+ * @experimental Part of Phase 6 (consolidation tooling). API may change.
748
+ *
749
+ * @example
750
+ * ```ts
751
+ * const pairs = await client.findDuplicates({
752
+ * entityId: "user_123",
753
+ * threshold: 0.95,
754
+ * limit: 50,
755
+ * });
756
+ * for (const { a, b, similarity } of pairs) {
757
+ * console.log(similarity, a.content, "<>", b.content);
758
+ * }
759
+ * ```
760
+ */
761
+ findDuplicates(input: FindDuplicatesInput): Promise<DuplicatePair[]>;
762
+ /**
763
+ * Return audit-log entries for `entityId`, newest first.
764
+ *
765
+ * Entries are recorded automatically when
766
+ * {@link MnemocyteConfig.audit}.`enabled` is `true`. Historic entries
767
+ * remain readable even after toggling `enabled` back to `false`.
768
+ *
769
+ * @experimental Part of Phase 6 (consolidation tooling). API may change.
770
+ *
771
+ * @example
772
+ * ```ts
773
+ * const log = await client.listAuditLog({
774
+ * entityId: "user_123",
775
+ * limit: 100,
776
+ * });
777
+ * for (const event of log) {
778
+ * console.log(event.timestamp, event.description, event.metadata);
779
+ * }
780
+ * ```
781
+ */
782
+ listAuditLog(input: ListAuditLogInput): Promise<AuditEvent[]>;
783
+ /**
784
+ * Unstable, opt-in extension surface. Members may change or be
785
+ * removed without a semver bump until they graduate to the main
786
+ * client interface.
787
+ *
788
+ * @experimental Part of Phase 6 (consolidation tooling).
789
+ */
790
+ experimental: ExperimentalMnemocyteClient;
575
791
  /**
576
792
  * Return statistics. With an `entityId`, returns {@link EntityStats};
577
793
  * without one, returns {@link GlobalStats}.
@@ -585,6 +801,45 @@ interface MnemocyteClient {
585
801
  */
586
802
  close(): Promise<void>;
587
803
  }
804
+ /**
805
+ * Extension surface for unstable Phase 6 operations. Reached via
806
+ * {@link MnemocyteClient.experimental}.
807
+ *
808
+ * @experimental Members may change or be removed without a semver bump.
809
+ */
810
+ interface ExperimentalMnemocyteClient {
811
+ /**
812
+ * Consolidate likely-duplicate memories into a single survivor by
813
+ * marking the others as superseded. Optionally unions their tags
814
+ * onto the survivor. Idempotent for memories that are already
815
+ * superseded.
816
+ *
817
+ * Emits one `"memory.superseded"` audit event per newly superseded
818
+ * memory when {@link MnemocyteConfig.audit}.`enabled` is `true`.
819
+ *
820
+ * @experimental Part of Phase 6 (consolidation tooling). API may change.
821
+ *
822
+ * @throws {MnemocyteError} `"VALIDATION"` for empty `supersededIds`,
823
+ * a `survivorId` that also appears in `supersededIds`, or a survivor
824
+ * that is itself already superseded.
825
+ * @throws {MnemocyteError} `"NOT_FOUND"` if the survivor or any
826
+ * non-already-superseded memory in `supersededIds` does not belong
827
+ * to `entityId`.
828
+ *
829
+ * @example
830
+ * ```ts
831
+ * const pairs = await client.findDuplicates({ entityId: "user_123" });
832
+ * for (const { a, b } of pairs) {
833
+ * await client.experimental.consolidate({
834
+ * entityId: "user_123",
835
+ * survivorId: a.id,
836
+ * supersededIds: [b.id],
837
+ * });
838
+ * }
839
+ * ```
840
+ */
841
+ consolidate(input: ConsolidateInput): Promise<ConsolidateResult>;
842
+ }
588
843
  //#endregion
589
844
  //#region src/client.d.ts
590
845
  /**
@@ -601,14 +856,16 @@ interface MnemocyteClient {
601
856
  *
602
857
  * @param config - Client configuration. {@link MnemocyteConfig.embedder} is required.
603
858
  * @returns A {@link MnemocyteClient} instance.
604
- * @throws {MnemocyteError} With code `"CONFIG"` if `embedder` is missing or invalid,
605
- * or `"VALIDATION"` if `databaseUrl` is provided but empty.
859
+ * @throws {MnemocyteError} With code `"CONFIG"` if `embedder` is missing or
860
+ * invalid (including when `databaseUrl` is set and `embedder.dimensions`
861
+ * is not 1536 — the dimensionality pinned by the bundled migration), or
862
+ * `"VALIDATION"` if `databaseUrl` is provided but empty.
606
863
  *
607
864
  * @example Postgres-backed client
608
865
  * ```ts
609
866
  * const client = createMnemocyte({
610
867
  * databaseUrl: process.env.DATABASE_URL,
611
- * embedder,
868
+ * embedder, // embedder.dimensions MUST be 1536 for the Postgres backend
612
869
  * });
613
870
  * ```
614
871
  */
@@ -670,5 +927,5 @@ declare class MnemocyteError extends Error {
670
927
  */
671
928
  declare function isMnemocyteError(error: unknown): error is MnemocyteError;
672
929
  //#endregion
673
- export { type BuildContextInput, type ContextFormat, type Embedder, type EntityStats, type GlobalStats, type ImportanceLevel, 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 RetrievalConfig, type RetrievalExplanation, type RetrievalScoreWeights, type RetrievalScores, type TokenCounter, createMnemocyte, isMnemocyteError };
930
+ 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 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 RetrievalConfig, type RetrievalExplanation, type RetrievalScoreWeights, type RetrievalScores, type TokenCounter, createMnemocyte, isMnemocyteError };
674
931
  //# sourceMappingURL=index.d.mts.map