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 +168 -77
- package/dist/index.d.mts +263 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +531 -75
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
# Mnemocyte
|
|
2
2
|
|
|
3
|
-
Persistent memory for TypeScript AI
|
|
3
|
+
Persistent memory for TypeScript AI applications.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
10
|
+
> Mnemocyte is early software. APIs may change before v1.0.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
## Features
|
|
12
13
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
61
|
+
When `databaseUrl` is omitted, Mnemocyte uses the in-memory backend.
|
|
56
62
|
|
|
57
|
-
|
|
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
|
-
|
|
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
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
109
|
+
Provider failures surface as `MnemocyteError` values with stable `code`s:
|
|
97
110
|
|
|
98
|
-
- `"TIMEOUT"
|
|
99
|
-
- `"ABORTED"
|
|
100
|
-
- `"EMBEDDING"
|
|
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
|
|
115
|
+
## Pruning
|
|
103
116
|
|
|
104
|
-
`prune`
|
|
105
|
-
|
|
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`.
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
605
|
-
*
|
|
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
|