mnemocyte 0.0.7 → 0.1.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/dist/index.d.mts CHANGED
@@ -1,179 +1,931 @@
1
1
  //#region src/types.d.ts
2
+ /**
3
+ * Discriminator describing what kind of memory a {@link Memory} represents.
4
+ *
5
+ * - `"fact"` — a stable, objective statement.
6
+ * - `"preference"` — a user/entity preference that should bias future responses.
7
+ * - `"instruction"` — a directive the agent should follow.
8
+ * - `"backstory"` — long-lived background context about the entity.
9
+ * - `"episode"` — a discrete past event.
10
+ * - `"session"` — short-lived context tied to a single session.
11
+ *
12
+ * @defaultValue `"fact"` when omitted on {@link RememberInput}.
13
+ */
2
14
  type MemoryType = "fact" | "preference" | "instruction" | "backstory" | "episode" | "session";
15
+ /**
16
+ * Relative importance assigned to a memory. Influences retrieval ranking
17
+ * via the `importance` score component.
18
+ *
19
+ * @defaultValue `"normal"` when omitted on {@link RememberInput}.
20
+ */
3
21
  type ImportanceLevel = "low" | "normal" | "high" | "critical";
22
+ /**
23
+ * Output format produced by {@link MnemocyteClient.buildContext}.
24
+ *
25
+ * - `"markdown"` — headings + bullet list (default; LLM-friendly).
26
+ * - `"plain"` — newline-separated plain text.
27
+ * - `"xml"` — structured tags, useful for models that parse XML reliably.
28
+ *
29
+ * @defaultValue `"markdown"`
30
+ */
4
31
  type ContextFormat = "markdown" | "plain" | "xml";
32
+ /**
33
+ * Identifies which backend a {@link MnemocyteClient} is using.
34
+ *
35
+ * Selected automatically by {@link createMnemocyte} based on whether
36
+ * {@link MnemocyteConfig.databaseUrl} was provided.
37
+ */
5
38
  type MnemocyteBackend = "in-memory" | "postgres";
6
- type MnemocyteOperation = "remember" | "rememberMany" | "recall" | "buildContext" | "forget" | "forgetAll" | "stats" | "close";
39
+ /**
40
+ * The set of public {@link MnemocyteClient} methods that emit
41
+ * {@link MnemocyteObservation} events through {@link ObservabilityConfig.onEvent}.
42
+ */
43
+ type MnemocyteOperation = "remember" | "rememberMany" | "recall" | "buildContext" | "forget" | "forgetAll" | "prune" | "findDuplicates" | "listAuditLog" | "consolidate" | "stats" | "close";
44
+ /**
45
+ * Lifecycle phase of a {@link MnemocyteObservation}.
46
+ *
47
+ * Every operation emits exactly one `"start"` event and exactly one of
48
+ * `"success"` or `"error"` once it settles.
49
+ */
7
50
  type MnemocyteObservationPhase = "start" | "success" | "error";
51
+ /**
52
+ * A single observability event emitted by a {@link MnemocyteClient}.
53
+ *
54
+ * Delivered to {@link ObservabilityConfig.onEvent} for tracing, metrics,
55
+ * and structured logging.
56
+ */
8
57
  interface MnemocyteObservation {
58
+ /** Operation that produced this event. */
9
59
  operation: MnemocyteOperation;
60
+ /** Lifecycle phase: `"start"`, `"success"`, or `"error"`. */
10
61
  phase: MnemocyteObservationPhase;
62
+ /** Backend handling the operation. */
11
63
  backend: MnemocyteBackend;
64
+ /** Wall-clock timestamp of this event. */
12
65
  timestamp: Date;
66
+ /** Elapsed milliseconds since the `"start"` event. Present on `"success"` / `"error"`. */
13
67
  durationMs?: number;
68
+ /** Entity ID associated with the operation, when applicable. */
14
69
  entityId?: string;
70
+ /** Memory ID associated with the operation, when applicable. */
15
71
  memoryId?: string;
72
+ /** Number of items processed (e.g. memories returned, batch size). */
16
73
  count?: number;
74
+ /** Thrown value. Present only on `"error"`. */
17
75
  error?: unknown;
18
76
  }
77
+ /**
78
+ * Hooks for observing client activity.
79
+ *
80
+ * Exceptions thrown by {@link ObservabilityConfig.onEvent} are swallowed so
81
+ * that telemetry never affects application logic.
82
+ */
19
83
  interface ObservabilityConfig {
84
+ /**
85
+ * Called for every lifecycle event of every operation. Receives a single
86
+ * {@link MnemocyteObservation}. May be sync or async; the operation will
87
+ * not be delayed waiting for slow async hooks beyond the awaited dispatch.
88
+ */
20
89
  onEvent?: (event: MnemocyteObservation) => void | Promise<void>;
21
90
  }
91
+ /**
92
+ * Production-hardening knobs applied to outbound provider calls
93
+ * (currently the {@link Embedder}). Mnemocyte applies a timeout, retries
94
+ * on transient failures, and forwards `AbortSignal` cancellation to each
95
+ * attempt. Every field is optional with conservative defaults; the
96
+ * defaults disable retries and timeouts so existing setups are
97
+ * unaffected unless they opt in.
98
+ */
99
+ interface ProviderResilienceConfig {
100
+ /**
101
+ * Maximum time, in milliseconds, that a single provider attempt may
102
+ * run before a {@link MnemocyteError} with code `"TIMEOUT"` is thrown.
103
+ * Defaults to `0` which disables the timeout.
104
+ */
105
+ timeoutMs?: number;
106
+ /**
107
+ * Maximum number of retry attempts after the initial call. `0`
108
+ * disables retries (default).
109
+ */
110
+ retries?: number;
111
+ /** Base backoff delay (ms) used before the first retry. Defaults to `100`. */
112
+ baseDelayMs?: number;
113
+ /** Maximum backoff delay (ms) used between retries. Defaults to `2000`. */
114
+ maxDelayMs?: number;
115
+ /**
116
+ * Optional predicate deciding whether `error` should trigger a retry.
117
+ * Receives the thrown value and the 1-indexed `attempt` number that
118
+ * just failed. When omitted, a conservative built-in heuristic is used
119
+ * that retries on common transient indicators (network errors, 5xx
120
+ * responses, rate-limit hints) and never retries `"VALIDATION"`,
121
+ * `"CONFIG"`, or `"ABORTED"` {@link MnemocyteError}s.
122
+ */
123
+ shouldRetry?: (error: unknown, attempt: number) => boolean;
124
+ }
125
+ /**
126
+ * Configuration passed to {@link createMnemocyte}.
127
+ */
22
128
  interface MnemocyteConfig {
129
+ /**
130
+ * Postgres connection string. When set, the client uses the Postgres
131
+ * backend (requires the `pgvector` extension and the bundled migration).
132
+ * When omitted, an in-memory backend is used.
133
+ */
23
134
  databaseUrl?: string;
135
+ /** Required embedder used to vectorise content for storage and retrieval. */
24
136
  embedder: Embedder;
137
+ /** Default values applied to {@link RecallInput} when properties are omitted. */
25
138
  defaults?: {
26
- limit?: number;
139
+ /** Default `limit` for {@link MnemocyteClient.recall}. */limit?: number; /** Default `minScore` cutoff for {@link MnemocyteClient.recall}. */
27
140
  minScore?: number;
28
141
  };
142
+ /** Retrieval-ranking tuning. See {@link RetrievalConfig}. */
29
143
  retrieval?: RetrievalConfig;
144
+ /** Observability hooks. See {@link ObservabilityConfig}. */
30
145
  observability?: ObservabilityConfig;
146
+ /**
147
+ * Production-hardening knobs for outbound provider calls
148
+ * (timeouts, retries, abort propagation). See
149
+ * {@link ProviderResilienceConfig}.
150
+ */
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;
31
176
  }
177
+ /**
178
+ * Pluggable embedding provider. Wraps an external embedding API
179
+ * (e.g. OpenAI, Cohere, a local model) in a small interface.
180
+ *
181
+ * Mnemocyte records {@link Embedder.model} and {@link Embedder.dimensions}
182
+ * on every stored memory and uses them to detect incompatible vectors
183
+ * (e.g. when the model is swapped).
184
+ */
32
185
  interface Embedder {
186
+ /** Stable identifier for the underlying model (e.g. `"text-embedding-3-small"`). */
33
187
  readonly model: string;
188
+ /** Dimensionality of vectors returned by {@link Embedder.embed}. */
34
189
  readonly dimensions: number;
35
- embed(texts: readonly string[]): Promise<number[][]>;
190
+ /**
191
+ * Embed one or more texts. Implementations MUST return one vector per
192
+ * input, in the same order, each of length {@link Embedder.dimensions}.
193
+ *
194
+ * The optional `options.signal` is forwarded by Mnemocyte when the
195
+ * caller passes a `signal` on a {@link RememberInput} / {@link RecallInput}
196
+ * / {@link BuildContextInput}, or when Mnemocyte's own provider timeout
197
+ * fires. Implementations that integrate with `fetch` should forward
198
+ * the signal to it so requests can be cancelled promptly.
199
+ */
200
+ embed(texts: readonly string[], options?: {
201
+ signal?: AbortSignal;
202
+ }): Promise<number[][]>;
36
203
  }
204
+ /**
205
+ * A persisted memory record as returned by the client.
206
+ *
207
+ * Memories are immutable from the caller's perspective; updates produce a
208
+ * new memory and link the previous one via {@link Memory.supersededBy}.
209
+ */
37
210
  interface Memory {
211
+ /** Unique identifier (`mem_*` prefixed string). */
38
212
  id: string;
213
+ /** Owning entity — typically a user, agent, or session ID. */
39
214
  entityId: string;
215
+ /** Raw textual content of the memory. */
40
216
  content: string;
217
+ /** Discriminator describing the kind of memory. */
41
218
  type: MemoryType;
219
+ /** Relative importance assigned at write time. */
42
220
  importance: ImportanceLevel;
221
+ /** Free-form tags used for filtering on {@link RecallInput.tags}. */
43
222
  tags: string[];
223
+ /** Optional human-readable source attribution (e.g. `"chat:2024-04-12"`). */
44
224
  source: string | null;
225
+ /** Arbitrary user-provided metadata persisted alongside the memory. */
45
226
  metadata: Record<string, unknown>;
227
+ /** Confidence in `[0, 1]`. Used in retrieval ranking. */
46
228
  confidence: number;
229
+ /** {@link Embedder.model} value at write time. */
47
230
  embeddingModel: string;
231
+ /** {@link Embedder.dimensions} value at write time. */
48
232
  embeddingDimensions: number;
233
+ /** ID of the memory that supersedes this one, or `null` if active. */
49
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;
242
+ /** Optional expiry; expired memories are filtered out by default. */
50
243
  expiresAt: Date | null;
244
+ /** Last time this memory was returned by {@link MnemocyteClient.recall}. */
51
245
  lastAccessedAt: Date | null;
246
+ /** Cumulative number of times this memory has been recalled. */
52
247
  accessCount: number;
248
+ /** Creation timestamp. */
53
249
  createdAt: Date;
250
+ /** Most recent update timestamp. */
54
251
  updatedAt: Date;
55
252
  }
253
+ /**
254
+ * Per-component scores produced during retrieval ranking. Each value is
255
+ * normalised to `[0, 1]` before being combined via
256
+ * {@link RetrievalScoreWeights}.
257
+ */
56
258
  interface RetrievalScores {
259
+ /** Cosine similarity between the query embedding and the memory embedding. */
57
260
  vector: number;
261
+ /** Token-overlap (lexical) score between query and memory content. */
58
262
  lexical: number;
263
+ /** Time-decay score based on {@link RetrievalConfig.recencyHalfLifeDays}. */
59
264
  recency: number;
265
+ /** Pass-through of the memory's stored `confidence`. */
60
266
  confidence: number;
267
+ /** Saturating score derived from `accessCount`. */
61
268
  access: number;
269
+ /** Score derived from {@link ImportanceLevel}. */
62
270
  importance: number;
63
271
  }
272
+ /**
273
+ * Optional overrides for the per-component retrieval weights. Missing keys
274
+ * fall back to library defaults. Weights need not sum to 1; the final
275
+ * score is computed as a weighted sum of {@link RetrievalScores}.
276
+ */
64
277
  interface RetrievalScoreWeights {
278
+ /** Weight applied to {@link RetrievalScores.vector}. */
65
279
  vector?: number;
280
+ /** Weight applied to {@link RetrievalScores.lexical}. */
66
281
  lexical?: number;
282
+ /** Weight applied to {@link RetrievalScores.recency}. */
67
283
  recency?: number;
284
+ /** Weight applied to {@link RetrievalScores.confidence}. */
68
285
  confidence?: number;
286
+ /** Weight applied to {@link RetrievalScores.access}. */
69
287
  access?: number;
288
+ /** Weight applied to {@link RetrievalScores.importance}. */
70
289
  importance?: number;
71
290
  }
291
+ /**
292
+ * Retrieval-ranking tuning. All fields are optional; sensible defaults are
293
+ * used for any field that is omitted.
294
+ */
72
295
  interface RetrievalConfig {
296
+ /** Per-component score weights. See {@link RetrievalScoreWeights}. */
73
297
  weights?: RetrievalScoreWeights;
298
+ /** Half-life (days) for the time-decay recency component. */
74
299
  recencyHalfLifeDays?: number;
300
+ /** Access count at which the access score is considered saturated. */
75
301
  accessSaturation?: number;
302
+ /**
303
+ * Multiplier applied to {@link RecallInput.limit} to determine how many
304
+ * candidates are fetched from the underlying store before re-ranking.
305
+ */
76
306
  candidateMultiplier?: number;
77
307
  }
308
+ /**
309
+ * Detailed scoring breakdown attached to each {@link MemoryWithScore} when
310
+ * {@link RecallInput.explain} is `true`. Useful for debugging ranking and
311
+ * tuning {@link RetrievalConfig}.
312
+ */
78
313
  interface RetrievalExplanation {
314
+ /** Raw vector similarity in `[0, 1]`. */
79
315
  vectorScore: number;
316
+ /** Raw lexical-overlap score in `[0, 1]`. */
80
317
  lexicalScore: number;
318
+ /** Raw recency score in `[0, 1]`. */
81
319
  recencyScore: number;
320
+ /** Raw confidence score in `[0, 1]`. */
82
321
  confidenceScore: number;
322
+ /** Raw access score in `[0, 1]`. */
83
323
  accessScore: number;
324
+ /** Raw importance score in `[0, 1]`. */
84
325
  importanceScore: number;
326
+ /** Additive multiplier applied for high-importance memories. */
85
327
  importanceBoost: number;
328
+ /** Effective weights used for this query (defaults filled in). */
86
329
  weights: Required<RetrievalScoreWeights>;
330
+ /** Final combined score — same value as {@link MemoryWithScore.score}. */
87
331
  finalScore: number;
88
332
  }
333
+ /**
334
+ * A {@link Memory} returned by {@link MnemocyteClient.recall}, annotated
335
+ * with retrieval scores.
336
+ */
89
337
  interface MemoryWithScore extends Memory {
338
+ /** Final combined relevance score. Higher is better. */
90
339
  score: number;
340
+ /** Per-component scores that produced {@link MemoryWithScore.score}. */
91
341
  scores: RetrievalScores;
342
+ /**
343
+ * Full scoring breakdown when {@link RecallInput.explain} is `true`,
344
+ * `null` otherwise.
345
+ */
92
346
  explanation: RetrievalExplanation | null;
93
347
  }
348
+ /**
349
+ * Input for {@link MnemocyteClient.remember} and
350
+ * {@link MnemocyteClient.rememberMany}.
351
+ */
94
352
  interface RememberInput {
353
+ /** Owning entity ID (e.g. user, agent, or session). */
95
354
  entityId: string;
355
+ /** Raw textual content to store. Must be non-empty. */
96
356
  content: string;
357
+ /** Memory kind. @defaultValue `"fact"` */
97
358
  type?: MemoryType;
359
+ /** Relative importance. @defaultValue `"normal"` */
98
360
  importance?: ImportanceLevel;
361
+ /** Free-form tags used for later filtering. */
99
362
  tags?: string[];
363
+ /** Optional human-readable source attribution. */
100
364
  source?: string;
365
+ /** Arbitrary metadata persisted alongside the memory. */
101
366
  metadata?: Record<string, unknown>;
367
+ /** Confidence in `[0, 1]`. @defaultValue `1` */
102
368
  confidence?: number;
369
+ /** Optional expiry; expired memories are filtered out by default. */
103
370
  expiresAt?: Date;
371
+ /**
372
+ * Optional cancellation signal. Forwarded to the embedder; when
373
+ * aborted, the operation throws a {@link MnemocyteError} with code
374
+ * `"ABORTED"`.
375
+ */
376
+ signal?: AbortSignal;
104
377
  }
378
+ /**
379
+ * Input for {@link MnemocyteClient.recall}.
380
+ */
105
381
  interface RecallInput {
382
+ /** Owning entity ID to search within. */
106
383
  entityId: string;
384
+ /** Free-text query; embedded and matched against stored memories. */
107
385
  query: string;
386
+ /** Maximum number of results. Falls back to {@link MnemocyteConfig.defaults}. */
108
387
  limit?: number;
388
+ /** Minimum final score required for a memory to be returned. */
109
389
  minScore?: number;
390
+ /** Restrict results to these memory types. */
110
391
  types?: MemoryType[];
392
+ /** Require results to include all of these tags. */
111
393
  tags?: string[];
394
+ /** Only include memories created strictly before this date. */
112
395
  before?: Date;
396
+ /** Only include memories created strictly after this date. */
113
397
  after?: Date;
398
+ /** Include memories that have been superseded. @defaultValue `false` */
114
399
  includeSuperseded?: boolean;
400
+ /** Include memories whose `expiresAt` has passed. @defaultValue `false` */
115
401
  includeExpired?: boolean;
402
+ /** Populate {@link MemoryWithScore.explanation} on each result. @defaultValue `false` */
116
403
  explain?: boolean;
404
+ /**
405
+ * Optional cancellation signal. Forwarded to the embedder; when
406
+ * aborted, the operation throws a {@link MnemocyteError} with code
407
+ * `"ABORTED"`.
408
+ */
409
+ signal?: AbortSignal;
117
410
  }
411
+ /**
412
+ * Pluggable token counter used by {@link MnemocyteClient.buildContext} to
413
+ * enforce {@link BuildContextInput.maxTokens}. Plug in your model's real
414
+ * tokenizer (e.g. `tiktoken`) for accurate budgeting; a simple word-based
415
+ * heuristic is used when omitted.
416
+ */
118
417
  interface TokenCounter {
418
+ /** Return the number of tokens in `text`. */
119
419
  count(text: string): number;
120
420
  }
421
+ /**
422
+ * Input for {@link MnemocyteClient.buildContext}, which renders relevant
423
+ * memories into a prompt-ready string.
424
+ */
121
425
  interface BuildContextInput {
426
+ /** Owning entity ID to search within. */
122
427
  entityId: string;
428
+ /** Free-text query used to select relevant memories. */
123
429
  query: string;
430
+ /** Output format. @defaultValue `"markdown"` */
124
431
  format?: ContextFormat;
432
+ /** Optional token budget; memories are dropped from the tail until the budget fits. */
125
433
  maxTokens?: number;
434
+ /** Maximum number of memories to consider. */
126
435
  limit?: number;
436
+ /** Minimum retrieval score required. */
127
437
  minScore?: number;
438
+ /** Restrict to these memory types. */
128
439
  types?: MemoryType[];
440
+ /** Require results to include all of these tags. */
129
441
  tags?: string[];
442
+ /** Include superseded memories. @defaultValue `false` */
130
443
  includeSuperseded?: boolean;
444
+ /** Include expired memories. @defaultValue `false` */
131
445
  includeExpired?: boolean;
446
+ /** Tokenizer used to enforce {@link BuildContextInput.maxTokens}. */
132
447
  tokenCounter?: TokenCounter;
448
+ /**
449
+ * Optional cancellation signal. Forwarded to the underlying recall
450
+ * call and embedder; when aborted, the operation throws a
451
+ * {@link MnemocyteError} with code `"ABORTED"`.
452
+ */
453
+ signal?: AbortSignal;
454
+ }
455
+ /**
456
+ * Input for {@link MnemocyteClient.prune}. All fields are optional, but
457
+ * at least one selector must be set; calling `prune({})` is rejected with
458
+ * a `"VALIDATION"` {@link MnemocyteError} so memories cannot be deleted
459
+ * accidentally. Specified filters are combined with AND semantics.
460
+ */
461
+ interface PruneInput {
462
+ /** Restrict pruning to a single entity. */
463
+ entityId?: string;
464
+ /** Match memories whose `expiresAt` is in the past. */
465
+ expired?: boolean;
466
+ /** Match memories that have been superseded (`supersededBy !== null`). */
467
+ superseded?: boolean;
468
+ /** Match memories created strictly before this date. */
469
+ createdBefore?: Date;
470
+ /**
471
+ * Match memories whose `lastAccessedAt` is `null` or strictly before
472
+ * this date. Useful for evicting "cold" memories.
473
+ */
474
+ notAccessedSince?: Date;
475
+ /** Restrict pruning to these memory types. */
476
+ types?: MemoryType[];
477
+ /**
478
+ * Require memories to include all of these tags. Empty array is
479
+ * treated as no tag filter.
480
+ */
481
+ tags?: string[];
482
+ /**
483
+ * Match memories whose `importance` is at or below this level. For
484
+ * example, `"normal"` prunes `"low"` and `"normal"` but never `"high"`
485
+ * or `"critical"`. Useful for evicting low-value memories first.
486
+ */
487
+ maxImportance?: ImportanceLevel;
488
+ /**
489
+ * If `true`, count what would be pruned without deleting anything.
490
+ * @defaultValue `false`
491
+ */
492
+ dryRun?: boolean;
493
+ /** Optional cancellation signal. */
494
+ signal?: AbortSignal;
495
+ }
496
+ /**
497
+ * Result returned by {@link MnemocyteClient.prune}.
498
+ */
499
+ interface PruneResult {
500
+ /** Number of memories that matched the prune filter. */
501
+ matchedCount: number;
502
+ /**
503
+ * Number of memories actually deleted. Equals `matchedCount` for
504
+ * normal runs and `0` for `dryRun` runs.
505
+ */
506
+ deletedCount: number;
507
+ /** `true` when {@link PruneInput.dryRun} was set. */
508
+ dryRun: boolean;
133
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
+ }
646
+ /**
647
+ * Stats for a single entity, returned by
648
+ * {@link MnemocyteClient.stats} when an `entityId` is provided.
649
+ */
134
650
  interface EntityStats {
651
+ /** The entity these stats describe. */
135
652
  entityId: string;
653
+ /** Total number of memories ever stored for this entity. */
136
654
  memoryCount: number;
655
+ /** Memories that are neither expired nor superseded. */
137
656
  activeMemoryCount: number;
657
+ /** Memories whose `expiresAt` has passed. */
138
658
  expiredMemoryCount: number;
659
+ /** Memories that have been superseded by a newer one. */
139
660
  supersededMemoryCount: number;
140
661
  }
662
+ /**
663
+ * Stats aggregated across all entities, returned by
664
+ * {@link MnemocyteClient.stats} when no `entityId` is provided.
665
+ */
141
666
  interface GlobalStats {
667
+ /** Number of distinct entities with at least one memory. */
142
668
  entityCount: number;
669
+ /** Total number of memories across all entities. */
143
670
  memoryCount: number;
671
+ /** Memories that are neither expired nor superseded. */
144
672
  activeMemoryCount: number;
673
+ /** Memories whose `expiresAt` has passed. */
145
674
  expiredMemoryCount: number;
675
+ /** Memories that have been superseded by a newer one. */
146
676
  supersededMemoryCount: number;
147
677
  }
678
+ /**
679
+ * The Mnemocyte client. Returned by {@link createMnemocyte}.
680
+ *
681
+ * Every method may throw {@link MnemocyteError}; use {@link isMnemocyteError}
682
+ * to narrow caught values.
683
+ */
148
684
  interface MnemocyteClient {
685
+ /**
686
+ * Persist a single memory and return the stored record.
687
+ *
688
+ * @throws {MnemocyteError} `"VALIDATION"` for invalid input, `"EMBEDDING"`
689
+ * if the embedder fails, `"DB"` for storage failures.
690
+ */
149
691
  remember(input: RememberInput): Promise<Memory>;
692
+ /**
693
+ * Persist multiple memories in one round-trip. Returns the stored records
694
+ * in the same order as `inputs`.
695
+ */
150
696
  rememberMany(inputs: readonly RememberInput[]): Promise<Memory[]>;
697
+ /**
698
+ * Retrieve the most relevant memories for `input.query`, ranked by the
699
+ * configured {@link RetrievalConfig}.
700
+ */
151
701
  recall(input: RecallInput): Promise<MemoryWithScore[]>;
702
+ /**
703
+ * Build a prompt-ready context string from the most relevant memories.
704
+ * Respects {@link BuildContextInput.maxTokens} when supplied.
705
+ */
152
706
  buildContext(input: BuildContextInput): Promise<string>;
707
+ /**
708
+ * Delete a specific memory belonging to `entityId`.
709
+ *
710
+ * @throws {MnemocyteError} `"NOT_FOUND"` if the memory does not exist
711
+ * or does not belong to `entityId`.
712
+ */
153
713
  forget(input: {
154
714
  entityId: string;
155
715
  memoryId: string;
156
716
  }): Promise<void>;
717
+ /** Delete every memory belonging to `entityId`. */
157
718
  forgetAll(input: {
158
719
  entityId: string;
159
720
  }): Promise<void>;
721
+ /**
722
+ * Bulk-delete memories matching the filters on {@link PruneInput}.
723
+ *
724
+ * At least one filter must be specified; an empty input throws a
725
+ * `"VALIDATION"` {@link MnemocyteError} to avoid accidental full
726
+ * deletion. Pass `dryRun: true` to count without deleting.
727
+ *
728
+ * @example Evict expired or stale memories for an entity
729
+ * ```ts
730
+ * await client.prune({
731
+ * entityId: "user_123",
732
+ * expired: true,
733
+ * });
734
+ *
735
+ * await client.prune({
736
+ * notAccessedSince: new Date(Date.now() - 30 * 24 * 3600 * 1000),
737
+ * maxImportance: "normal",
738
+ * });
739
+ * ```
740
+ */
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;
791
+ /**
792
+ * Return statistics. With an `entityId`, returns {@link EntityStats};
793
+ * without one, returns {@link GlobalStats}.
794
+ */
160
795
  stats(input?: {
161
796
  entityId?: string;
162
797
  }): Promise<EntityStats | GlobalStats>;
798
+ /**
799
+ * Release any underlying resources (e.g. the Postgres connection pool).
800
+ * Safe to call multiple times. The client must not be used afterward.
801
+ */
163
802
  close(): Promise<void>;
164
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
+ }
165
843
  //#endregion
166
844
  //#region src/client.d.ts
845
+ /**
846
+ * Create a Mnemocyte client.
847
+ *
848
+ * When {@link MnemocyteConfig.databaseUrl} is provided, a Postgres-backed
849
+ * client is returned (requires the `pgvector` extension and the bundled
850
+ * migration applied). Otherwise an in-memory client is returned, intended
851
+ * for tests, demos, and short-lived processes.
852
+ *
853
+ * The returned client owns any underlying resources (e.g. the Postgres
854
+ * connection pool). Call {@link MnemocyteClient.close} when finished to
855
+ * release them.
856
+ *
857
+ * @param config - Client configuration. {@link MnemocyteConfig.embedder} is required.
858
+ * @returns A {@link MnemocyteClient} instance.
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.
863
+ *
864
+ * @example Postgres-backed client
865
+ * ```ts
866
+ * const client = createMnemocyte({
867
+ * databaseUrl: process.env.DATABASE_URL,
868
+ * embedder, // embedder.dimensions MUST be 1536 for the Postgres backend
869
+ * });
870
+ * ```
871
+ */
167
872
  declare function createMnemocyte(config: MnemocyteConfig): MnemocyteClient;
168
873
  //#endregion
169
874
  //#region src/errors.d.ts
170
- type MnemocyteErrorCode = "CONFIG" | "VALIDATION" | "DB" | "EMBEDDING" | "NOT_FOUND" | "MIGRATION";
875
+ /**
876
+ * Stable, machine-readable error code attached to every {@link MnemocyteError}.
877
+ *
878
+ * - `"CONFIG"` — invalid client configuration (e.g. missing or malformed embedder).
879
+ * - `"VALIDATION"` — invalid argument passed to a client method.
880
+ * - `"DB"` — Postgres or driver-level failure.
881
+ * - `"EMBEDDING"` — embedder threw or returned an invalid vector.
882
+ * - `"NOT_FOUND"` — referenced memory or entity does not exist.
883
+ * - `"MIGRATION"` — schema/migration check failed against the target database.
884
+ * - `"TIMEOUT"` — a provider call exceeded its configured timeout.
885
+ * - `"ABORTED"` — the operation was cancelled via an `AbortSignal`.
886
+ */
887
+ type MnemocyteErrorCode = "CONFIG" | "VALIDATION" | "DB" | "EMBEDDING" | "NOT_FOUND" | "MIGRATION" | "TIMEOUT" | "ABORTED";
888
+ /**
889
+ * Error type thrown by every public Mnemocyte API.
890
+ *
891
+ * Use the {@link MnemocyteError.code} property — not the message — to branch
892
+ * on failure modes, or call {@link isMnemocyteError} as a type guard when
893
+ * working with `unknown` errors.
894
+ *
895
+ * @example
896
+ * ```ts
897
+ * try {
898
+ * await client.recall({ entityId: "u1", query: "hi" });
899
+ * } catch (err) {
900
+ * if (isMnemocyteError(err) && err.code === "DB") {
901
+ * // handle database failure
902
+ * }
903
+ * throw err;
904
+ * }
905
+ * ```
906
+ */
171
907
  declare class MnemocyteError extends Error {
908
+ /** Stable, machine-readable failure code. See {@link MnemocyteErrorCode}. */
172
909
  readonly code: MnemocyteErrorCode;
910
+ /** Underlying cause, if any (e.g. an original driver or embedder error). */
173
911
  readonly cause?: unknown;
912
+ /**
913
+ * @param message - Human-readable error message.
914
+ * @param code - Stable failure code; see {@link MnemocyteErrorCode}.
915
+ * @param cause - Optional underlying cause (driver error, network error, etc.).
916
+ */
174
917
  constructor(message: string, code: MnemocyteErrorCode, cause?: unknown);
175
918
  }
919
+ /**
920
+ * Type guard for {@link MnemocyteError}.
921
+ *
922
+ * Prefer this over `instanceof` when working across module boundaries or
923
+ * bundlers where multiple copies of the class may exist.
924
+ *
925
+ * @param error - Value to test (typically a caught `unknown`).
926
+ * @returns `true` if `error` is a {@link MnemocyteError}.
927
+ */
176
928
  declare function isMnemocyteError(error: unknown): error is MnemocyteError;
177
929
  //#endregion
178
- 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 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 };
179
931
  //# sourceMappingURL=index.d.mts.map