purra-mem0 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,301 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import { randomUUID } from "node:crypto";
3
+ export class MemoryError extends Error {
4
+ code;
5
+ constructor(code) {
6
+ super(code);
7
+ this.code = code;
8
+ this.name = "MemoryError";
9
+ }
10
+ }
11
+ export function itemView(row) {
12
+ return { version: row.meta.purra_version, state: row.meta.purra_state,
13
+ metadata: row.meta.purra_metadata, reason: row.meta.purra_reason,
14
+ createdAt: row.meta.purra_created, updatedAt: row.meta.purra_updated, ...row.view };
15
+ }
16
+ /** Only control metadata is stored here. Content and vectors remain in Mem0. */
17
+ export class Journal {
18
+ scope;
19
+ db;
20
+ store;
21
+ constructor(path, scope) {
22
+ this.scope = scope;
23
+ if (typeof path !== "string" || !path.trim() || path === ":memory:") {
24
+ throw new TypeError("journalPath must be a persistent SQLite path");
25
+ }
26
+ this.db = new DatabaseSync(path);
27
+ this.db.exec(`
28
+ PRAGMA busy_timeout=5000;
29
+ CREATE TABLE IF NOT EXISTS purra_mem0_info (key TEXT PRIMARY KEY, value TEXT NOT NULL);
30
+ CREATE TABLE IF NOT EXISTS purra_mem0_epochs (scope TEXT PRIMARY KEY, epoch INTEGER NOT NULL);
31
+ CREATE TABLE IF NOT EXISTS purra_mem0_ops (
32
+ scope TEXT NOT NULL, key TEXT NOT NULL, fingerprint TEXT NOT NULL,
33
+ state TEXT NOT NULL, plan TEXT NOT NULL, ids TEXT, PRIMARY KEY(scope,key));
34
+ CREATE UNIQUE INDEX IF NOT EXISTS purra_mem0_writer ON purra_mem0_ops(scope)
35
+ WHERE state IN ('running','unknown');
36
+ CREATE TABLE IF NOT EXISTS purra_mem0_items (
37
+ scope TEXT NOT NULL, id TEXT NOT NULL, record TEXT NOT NULL, PRIMARY KEY(scope,id));
38
+ CREATE TABLE IF NOT EXISTS purra_mem0_budgets (
39
+ scope TEXT NOT NULL, key TEXT NOT NULL, limits TEXT NOT NULL, PRIMARY KEY(scope,key));
40
+ CREATE TABLE IF NOT EXISTS purra_mem0_calls (
41
+ scope TEXT NOT NULL, id TEXT NOT NULL, budget TEXT NOT NULL, operation TEXT,
42
+ kind TEXT NOT NULL, state TEXT NOT NULL, input_chars INTEGER NOT NULL,
43
+ reserved_output INTEGER NOT NULL, input_tokens INTEGER, output_tokens INTEGER,
44
+ PRIMARY KEY(scope,id));
45
+ CREATE INDEX IF NOT EXISTS purra_mem0_calls_budget ON purra_mem0_calls(scope,budget);
46
+ CREATE INDEX IF NOT EXISTS purra_mem0_calls_operation ON purra_mem0_calls(scope,operation);
47
+ CREATE TABLE IF NOT EXISTS purra_mem0_revocations (
48
+ scope TEXT NOT NULL, source TEXT NOT NULL, revision TEXT NOT NULL,
49
+ PRIMARY KEY(scope,source,revision));
50
+ `);
51
+ this.transaction(() => {
52
+ this.db.prepare("INSERT OR IGNORE INTO purra_mem0_info VALUES ('store',?)").run(randomUUID().replaceAll("-", ""));
53
+ this.db.prepare("INSERT OR IGNORE INTO purra_mem0_epochs VALUES (?,0)").run(scope);
54
+ });
55
+ this.store = this.db.prepare("SELECT value FROM purra_mem0_info WHERE key='store'").get().value;
56
+ }
57
+ transaction(work) {
58
+ this.db.exec("BEGIN IMMEDIATE");
59
+ try {
60
+ const result = work();
61
+ this.db.exec("COMMIT");
62
+ return result;
63
+ }
64
+ catch (error) {
65
+ this.db.exec("ROLLBACK");
66
+ throw error;
67
+ }
68
+ }
69
+ operation(key) {
70
+ const row = this.db.prepare("SELECT * FROM purra_mem0_ops WHERE scope=? AND key=?").get(this.scope, key);
71
+ if (!row)
72
+ return undefined;
73
+ return { key, fingerprint: row.fingerprint, state: row.state,
74
+ plan: JSON.parse(row.plan), ids: row.ids === null ? null : JSON.parse(row.ids) };
75
+ }
76
+ begin(key, fingerprint, plan) {
77
+ return this.transaction(() => {
78
+ const previous = this.operation(key);
79
+ if (previous) {
80
+ if (previous.fingerprint !== fingerprint)
81
+ throw new MemoryError("memory_idempotency_conflict");
82
+ return previous;
83
+ }
84
+ if (this.db.prepare("SELECT 1 FROM purra_mem0_ops WHERE scope=? AND state IN ('running','unknown')").get(this.scope)) {
85
+ throw new MemoryError("memory_write_busy");
86
+ }
87
+ this.db.prepare("INSERT INTO purra_mem0_ops VALUES (?,?,?,'running',?,NULL)")
88
+ .run(this.scope, key, fingerprint, JSON.stringify(plan));
89
+ return undefined;
90
+ });
91
+ }
92
+ savePlan(key, plan) {
93
+ this.db.prepare("UPDATE purra_mem0_ops SET plan=? WHERE scope=? AND key=?").run(JSON.stringify(plan), this.scope, key);
94
+ }
95
+ saveIds(key, ids) {
96
+ this.db.prepare("UPDATE purra_mem0_ops SET ids=? WHERE scope=? AND key=?").run(JSON.stringify(ids), this.scope, key);
97
+ }
98
+ budget(key, limits) {
99
+ this.transaction(() => {
100
+ const row = this.db.prepare("SELECT limits FROM purra_mem0_budgets WHERE scope=? AND key=?").get(this.scope, key);
101
+ if (row) {
102
+ const previous = JSON.parse(row.limits);
103
+ if (Object.keys(previous).length !== Object.keys(limits).length || Object.entries(limits).some(([k, v]) => previous[k] !== v)) {
104
+ throw new MemoryError("memory_budget_conflict");
105
+ }
106
+ }
107
+ this.db.prepare("INSERT OR IGNORE INTO purra_mem0_budgets VALUES (?,?,?)").run(this.scope, key, JSON.stringify(limits));
108
+ });
109
+ }
110
+ usage(column, key) {
111
+ const row = this.db.prepare(`SELECT
112
+ COALESCE(SUM(kind='llm'),0) AS llmCalls,
113
+ COALESCE(SUM(kind='embedding'),0) AS embeddingCalls,
114
+ COALESCE(SUM(input_chars),0) AS inputChars,
115
+ COALESCE(SUM(reserved_output),0) AS reservedOutputTokens,
116
+ COALESCE(SUM(input_tokens),0) AS reportedInputTokens,
117
+ COALESCE(SUM(output_tokens),0) AS reportedOutputTokens,
118
+ COALESCE(SUM(input_tokens IS NULL OR output_tokens IS NULL),0) AS unreportedCalls,
119
+ COALESCE(SUM(state='started'),0) AS unsettledCalls
120
+ FROM purra_mem0_calls WHERE scope=? AND ${column}=?`).get(this.scope, key);
121
+ return Object.freeze(row);
122
+ }
123
+ admit(budget, operation, kind, chars, reserve) {
124
+ return this.transaction(() => {
125
+ const op = operation === undefined ? undefined : this.operation(operation);
126
+ if (op?.plan.kind === "review")
127
+ this.assertSnapshot(op.plan);
128
+ if (op && op.plan.kind !== "delete" && op.plan.meta)
129
+ this.assertSource(op.plan.meta);
130
+ const limits = JSON.parse(this.db.prepare("SELECT limits FROM purra_mem0_budgets WHERE scope=? AND key=?").get(this.scope, budget).limits);
131
+ const used = this.usage("budget", budget);
132
+ if (used[kind === "llm" ? "llmCalls" : "embeddingCalls"] + 1 > limits["max_" + kind + "_calls"]
133
+ || used.inputChars + chars > limits.max_input_chars
134
+ || used.reservedOutputTokens + reserve > limits.max_output_tokens)
135
+ throw new MemoryError("memory_budget_exceeded");
136
+ const id = randomUUID().replaceAll("-", "");
137
+ this.db.prepare("INSERT INTO purra_mem0_calls VALUES (?,?,?,?,?,'started',?,?,NULL,NULL)")
138
+ .run(this.scope, id, budget, operation ?? null, kind, chars, reserve);
139
+ return id;
140
+ });
141
+ }
142
+ settle(id, state, inputTokens = null, generationTokens = null) {
143
+ this.db.prepare("UPDATE purra_mem0_calls SET state=?,input_tokens=?,output_tokens=? WHERE scope=? AND id=?")
144
+ .run(state, inputTokens, generationTokens, this.scope, id);
145
+ }
146
+ providerError(key, code) {
147
+ this.transaction(() => {
148
+ const op = this.operation(key);
149
+ if (op)
150
+ this.savePlan(key, { ...op.plan, provider_error: code });
151
+ });
152
+ }
153
+ verifyProviders(key) {
154
+ this.transaction(() => {
155
+ const op = this.operation(key);
156
+ this.savePlan(key, { ...op.plan, providers_verified: true });
157
+ });
158
+ }
159
+ fail(key, dispatched) {
160
+ this.db.prepare("UPDATE purra_mem0_ops SET state=? WHERE scope=? AND key=?").run(dispatched ? "unknown" : "failed", this.scope, key);
161
+ }
162
+ discard(key) {
163
+ this.db.prepare("UPDATE purra_mem0_ops SET state='discarded' WHERE scope=? AND key=?").run(this.scope, key);
164
+ }
165
+ revoked(source, revision) {
166
+ return !!this.db.prepare("SELECT 1 FROM purra_mem0_revocations WHERE scope=? AND source=? AND revision IN ('',?)")
167
+ .get(this.scope, source, revision);
168
+ }
169
+ assertSource(meta) {
170
+ if (this.revoked(meta.purra_source, meta.purra_revision))
171
+ throw new MemoryError("memory_source_revoked");
172
+ }
173
+ revokeSource(key, fingerprint, source, revision) {
174
+ // An uncertain SDK writer must not block withdrawal; its fence stays intact.
175
+ this.transaction(() => {
176
+ const previous = this.operation(key);
177
+ if (previous) {
178
+ if (previous.fingerprint !== fingerprint)
179
+ throw new MemoryError("memory_idempotency_conflict");
180
+ return;
181
+ }
182
+ const plan = { kind: "revoke_source", target: null, meta: null, source, revision };
183
+ this.db.prepare("INSERT INTO purra_mem0_ops VALUES (?,?,?,'complete',?,'[]')").run(this.scope, key, fingerprint, JSON.stringify(plan));
184
+ if (!this.revoked(source, revision ?? "")) {
185
+ this.db.prepare("INSERT INTO purra_mem0_revocations VALUES (?,?,?)").run(this.scope, source, revision ?? "");
186
+ this.db.prepare("UPDATE purra_mem0_epochs SET epoch=epoch+1 WHERE scope=?").run(this.scope);
187
+ }
188
+ });
189
+ }
190
+ item(id) {
191
+ const row = this.db.prepare("SELECT record FROM purra_mem0_items WHERE scope=? AND id=?").get(this.scope, id);
192
+ return row ? JSON.parse(row.record) : undefined;
193
+ }
194
+ resolve(key, fingerprint, plan, epoch) {
195
+ const resolution = plan.resolution;
196
+ this.control(key, fingerprint, plan, epoch, resolution.items, resolution.items.map(ref => ({
197
+ state: ref.id === resolution.keep ? "active" : "disabled",
198
+ reason: ref.id === resolution.keep ? null : resolution.kind, resolution: key,
199
+ })));
200
+ }
201
+ control(key, fingerprint, plan, epoch, refs, changes) {
202
+ this.transaction(() => {
203
+ const previous = this.operation(key);
204
+ if (previous) {
205
+ if (previous.fingerprint !== fingerprint)
206
+ throw new MemoryError("memory_idempotency_conflict");
207
+ return;
208
+ }
209
+ if (this.db.prepare("SELECT 1 FROM purra_mem0_ops WHERE scope=? AND state IN ('running','unknown')").get(this.scope))
210
+ throw new MemoryError("memory_write_busy");
211
+ if (this.epoch !== epoch)
212
+ throw new MemoryError("memory_context_stale");
213
+ if (plan.review_key !== undefined)
214
+ this.assertSnapshot(this.reviewPlan(plan.review_key));
215
+ const records = [], now = Date.now();
216
+ for (const [index, ref] of refs.entries()) {
217
+ const row = this.item(ref.id);
218
+ if (!row || row.deleted)
219
+ throw new MemoryError("memory_not_found");
220
+ if (itemView(row).version !== ref.version)
221
+ throw new MemoryError("memory_version_conflict");
222
+ this.assertSource(row.meta);
223
+ if ((["resolve", "link"].includes(plan.kind) || changes[index]?.state === "active")
224
+ && row.meta.purra_expires !== null && Date.parse(row.meta.purra_expires) <= now)
225
+ throw new MemoryError("memory_context_stale");
226
+ if (changes[index])
227
+ row.view = { ...itemView(row), ...changes[index], version: ref.version + 1, updatedAt: new Date(now).toISOString() };
228
+ records.push(row);
229
+ }
230
+ this.db.prepare("INSERT INTO purra_mem0_ops VALUES (?,?,?,'complete',?,?)")
231
+ .run(this.scope, key, fingerprint, JSON.stringify(plan), JSON.stringify(records.map(r => r.id)));
232
+ for (const row of records)
233
+ this.db.prepare("UPDATE purra_mem0_items SET record=? WHERE scope=? AND id=?").run(JSON.stringify(row), this.scope, row.id);
234
+ this.db.prepare("UPDATE purra_mem0_epochs SET epoch=epoch+1 WHERE scope=?").run(this.scope);
235
+ });
236
+ }
237
+ assertSnapshot(plan) {
238
+ if (plan.review_epoch !== this.epoch || !plan.review_refs?.length)
239
+ throw new MemoryError("memory_context_stale");
240
+ const now = Date.now();
241
+ for (const ref of plan.review_refs) {
242
+ const row = this.item(ref.id);
243
+ if (!row || row.deleted || itemView(row).version !== ref.version)
244
+ throw new MemoryError("memory_context_stale");
245
+ this.assertSource(row.meta);
246
+ if (row.meta.purra_expires !== null && Date.parse(row.meta.purra_expires) <= now)
247
+ throw new MemoryError("memory_context_stale");
248
+ }
249
+ }
250
+ links(id, after, limit) {
251
+ return this.db.prepare(`SELECT key,plan FROM purra_mem0_ops WHERE scope=? AND key>? AND state='complete'
252
+ AND json_extract(plan,'$.kind')='link'
253
+ AND (json_extract(plan,'$.link.from.id')=? OR json_extract(plan,'$.link.to.id')=?)
254
+ ORDER BY key LIMIT ?`).all(this.scope, after ?? "", id, id, limit)
255
+ .map(row => ({ key: row.key, data: JSON.parse(row.plan).link }));
256
+ }
257
+ reviewPlan(key) {
258
+ const op = this.operation(key);
259
+ if (!op || op.state !== "complete" || op.plan.kind !== "review" || !op.plan.review)
260
+ throw new MemoryError("memory_review_unavailable");
261
+ return op.plan;
262
+ }
263
+ finishReview(key, plan) {
264
+ this.transaction(() => {
265
+ if (this.operation(key)?.state !== "running")
266
+ throw new MemoryError("memory_operation_unresolved");
267
+ this.assertSnapshot(plan);
268
+ this.savePlan(key, plan);
269
+ this.db.prepare("UPDATE purra_mem0_ops SET state='complete',ids='[]' WHERE scope=? AND key=?").run(this.scope, key);
270
+ });
271
+ }
272
+ items(state, after, limit) {
273
+ return this.db.prepare(`SELECT record FROM purra_mem0_items AS item WHERE scope=? AND id>?
274
+ AND json_extract(record,'$.deleted')=0
275
+ AND (? IS NULL OR COALESCE(json_extract(record,'$.view.state'),json_extract(record,'$.meta.purra_state'))=?)
276
+ AND NOT EXISTS (SELECT 1 FROM purra_mem0_revocations AS r
277
+ WHERE r.scope=item.scope AND r.source=json_extract(item.record,'$.meta.purra_source')
278
+ AND r.revision IN ('',json_extract(item.record,'$.meta.purra_revision')))
279
+ AND (? IS NULL OR ? != 'active' OR json_extract(record,'$.meta.purra_expires') IS NULL
280
+ OR json_extract(record,'$.meta.purra_expires')>?) ORDER BY id LIMIT ?`)
281
+ .all(this.scope, after ?? "", state, state, state, state, new Date().toISOString(), limit)
282
+ .map(row => JSON.parse(row.record));
283
+ }
284
+ writing(id) {
285
+ return this.db.prepare("SELECT plan FROM purra_mem0_ops WHERE scope=? AND state IN ('running','unknown')").all(this.scope)
286
+ .some(row => JSON.parse(row.plan).target === id);
287
+ }
288
+ commit(key, records) {
289
+ this.transaction(() => {
290
+ for (const record of records)
291
+ this.db.prepare("INSERT OR REPLACE INTO purra_mem0_items VALUES (?,?,?)").run(this.scope, record.id, JSON.stringify(record));
292
+ this.db.prepare("UPDATE purra_mem0_ops SET state='complete' WHERE scope=? AND key=?").run(this.scope, key);
293
+ if (records.length)
294
+ this.db.prepare("UPDATE purra_mem0_epochs SET epoch=epoch+1 WHERE scope=?").run(this.scope);
295
+ });
296
+ }
297
+ get epoch() {
298
+ return this.db.prepare("SELECT epoch FROM purra_mem0_epochs WHERE scope=?").get(this.scope).epoch;
299
+ }
300
+ close() { this.db.close(); }
301
+ }
@@ -0,0 +1,213 @@
1
+ import type { ContextEvidenceReceipt, RetrievalHit, RetrievalRequest, Retriever } from "purra";
2
+ import type { MemoryProviders, MemoryUsage } from "./providers.js";
3
+ /** Structurally satisfied by `Memory` from `mem0ai/oss` 3.1.7. */
4
+ export interface Mem0Client {
5
+ add(messages: string | {
6
+ role: string;
7
+ content: string;
8
+ }[], options: {
9
+ userId: string;
10
+ runId: string;
11
+ metadata: Record<string, unknown>;
12
+ infer: boolean;
13
+ }): Promise<unknown>;
14
+ get(id: string): Promise<unknown>;
15
+ getAll(options: {
16
+ filters: Record<string, unknown>;
17
+ topK: number;
18
+ }): Promise<unknown>;
19
+ search(query: string, options: {
20
+ filters: Record<string, unknown>;
21
+ topK: number;
22
+ }): Promise<unknown>;
23
+ update(id: string, options: {
24
+ text: string;
25
+ metadata: Record<string, unknown>;
26
+ }): Promise<unknown>;
27
+ delete(id: string): Promise<unknown>;
28
+ history(id: string): Promise<unknown>;
29
+ }
30
+ export interface MemoryScope {
31
+ readonly user: string;
32
+ readonly project: string;
33
+ readonly agent?: string;
34
+ }
35
+ export interface MemorySource {
36
+ readonly id: string;
37
+ readonly revision: string;
38
+ }
39
+ export type MemoryMetadata = Readonly<Record<string, string | number | boolean | null>>;
40
+ export type MemoryFilters = Readonly<Record<string, string | number | boolean | null | readonly (string | number | boolean | null)[]>>;
41
+ export interface MemoryRecord {
42
+ readonly id: string;
43
+ readonly text: string;
44
+ readonly version: number;
45
+ readonly state: "active" | "pending" | "disabled";
46
+ readonly source: MemorySource;
47
+ readonly inferred: boolean;
48
+ readonly expiresAt: string | null;
49
+ readonly resolutionKey?: string;
50
+ readonly metadata: MemoryMetadata;
51
+ readonly reason: string | null;
52
+ readonly createdAt: string;
53
+ readonly updatedAt: string;
54
+ }
55
+ export interface MemoryPage {
56
+ readonly items: readonly MemoryRecord[];
57
+ readonly next: string | null;
58
+ readonly epoch: number;
59
+ }
60
+ export interface MemoryRef {
61
+ readonly id: string;
62
+ readonly version: number;
63
+ }
64
+ export interface MemoryLink {
65
+ readonly key: string;
66
+ readonly from: MemoryRef;
67
+ readonly to: MemoryRef;
68
+ readonly relation: string;
69
+ readonly note: string;
70
+ readonly valid: boolean;
71
+ }
72
+ export interface MemoryLinkPage {
73
+ readonly items: readonly MemoryLink[];
74
+ readonly next: string | null;
75
+ readonly epoch: number;
76
+ }
77
+ export type MemoryResolution = {
78
+ readonly items: readonly MemoryRef[];
79
+ readonly reviewKey?: string;
80
+ } & ({
81
+ readonly kind: "independent" | "duplicate" | "supersede";
82
+ readonly keep: string;
83
+ } | {
84
+ readonly kind: "conflict";
85
+ readonly keep?: never;
86
+ });
87
+ export interface MemoryMatch {
88
+ readonly item: MemoryRef;
89
+ readonly kind: "independent" | "duplicate" | "supersede" | "conflict" | "uncertain";
90
+ }
91
+ export interface MemoryReview {
92
+ readonly key: string;
93
+ readonly candidate: MemoryRef;
94
+ readonly matches: readonly MemoryMatch[];
95
+ readonly epoch: number;
96
+ readonly proposal?: MemoryResolution;
97
+ }
98
+ export interface MemoryOperation {
99
+ readonly key: string;
100
+ readonly state: "running" | "unknown" | "failed" | "complete" | "discarded";
101
+ readonly ids: readonly string[];
102
+ readonly usage: MemoryUsage | "unknown";
103
+ readonly resolution?: MemoryResolution;
104
+ readonly review?: MemoryReview;
105
+ }
106
+ interface WriteOptions {
107
+ readonly key: string;
108
+ readonly signal?: AbortSignal;
109
+ }
110
+ interface SourceOptions extends WriteOptions {
111
+ readonly source: MemorySource;
112
+ readonly expiresAt?: string | null;
113
+ readonly metadata?: MemoryMetadata;
114
+ }
115
+ interface VersionOptions extends WriteOptions {
116
+ readonly version: number;
117
+ }
118
+ export declare function requiredText(value: unknown, label: string, limit?: number): string;
119
+ export declare function positiveInteger(value: number, label: string, maximum?: number): number;
120
+ /** Host-owned SDK, immutable scope, persistent write fence. No automatic capture. */
121
+ export declare class Mem0Memory implements Retriever {
122
+ #private;
123
+ constructor(options: {
124
+ client: Mem0Client;
125
+ scope: MemoryScope;
126
+ journalPath: string;
127
+ allowInference?: boolean;
128
+ timeoutMs?: number;
129
+ maxResults?: number;
130
+ maxInputChars?: number;
131
+ providers?: MemoryProviders;
132
+ });
133
+ operation(key: string): MemoryOperation | undefined;
134
+ /** Verify content, then atomically keep one claim or quarantine a group. No SDK mutations. */
135
+ resolve(value: MemoryResolution, options: WriteOptions): Promise<MemoryOperation>;
136
+ /** Budgeted advice for a pending candidate; never activates memory. */
137
+ link(from: MemoryRef, to: MemoryRef, relation: string, options: WriteOptions & {
138
+ note?: string;
139
+ }): Promise<MemoryOperation>;
140
+ links(id: string, options?: {
141
+ limit?: number;
142
+ after?: string;
143
+ signal?: AbortSignal;
144
+ }): Promise<MemoryLinkPage>;
145
+ review(candidate: MemoryRef, options: WriteOptions & {
146
+ limit?: number;
147
+ instructions?: string;
148
+ }): Promise<MemoryOperation>;
149
+ /** Includes searches, reservations, late completions and unknown usage. */
150
+ budgetUsage(): MemoryUsage | undefined;
151
+ get epoch(): number;
152
+ assertEpoch(epoch: number): void;
153
+ /** Permanently stop using a revision, or all revisions when omitted. No physical erasure. */
154
+ revokeSource(sourceId: string, options: {
155
+ key: string;
156
+ revision?: string;
157
+ signal?: AbortSignal;
158
+ }): Promise<MemoryOperation>;
159
+ isSourceRevoked(source: MemorySource): boolean;
160
+ /** Revalidate all host-persisted memory receipts before reuse/resume; no inference or checkpoint rewriting. */
161
+ validateEvidence(receipts: readonly ContextEvidenceReceipt[], options?: {
162
+ signal?: AbortSignal;
163
+ }): Promise<void>;
164
+ get(id: string, options?: {
165
+ includeInactive?: boolean;
166
+ signal?: AbortSignal;
167
+ }): Promise<MemoryRecord | undefined>;
168
+ select(ids: readonly string[], options?: {
169
+ signal?: AbortSignal;
170
+ }): Promise<readonly RetrievalHit[]>;
171
+ list(options?: {
172
+ state?: "active" | "pending" | "disabled" | null;
173
+ limit?: number;
174
+ after?: string;
175
+ filters?: MemoryFilters;
176
+ source?: string;
177
+ query?: string;
178
+ scanLimit?: number;
179
+ signal?: AbortSignal;
180
+ }): Promise<MemoryPage>;
181
+ add(text: string, options: SourceOptions & {
182
+ state?: MemoryRecord["state"];
183
+ reason?: string | null;
184
+ }): Promise<MemoryOperation>;
185
+ extract(messages: readonly {
186
+ role: "user" | "assistant";
187
+ content: string;
188
+ }[], options: SourceOptions): Promise<MemoryOperation>;
189
+ update(id: string, text: string, options: SourceOptions & VersionOptions): Promise<MemoryOperation>;
190
+ setState(id: string, state: MemoryRecord["state"], options: VersionOptions & {
191
+ reason?: string | null;
192
+ }): Promise<MemoryOperation>;
193
+ annotate(id: string, metadata: MemoryMetadata, options: VersionOptions): Promise<MemoryOperation>;
194
+ /** Delete live content, not SDK history, source messages or checkpoints. */
195
+ delete(id: string, options: VersionOptions): Promise<MemoryOperation>;
196
+ reconcile(key: string, options?: {
197
+ writerStopped?: boolean;
198
+ signal?: AbortSignal;
199
+ }): Promise<MemoryOperation>;
200
+ discardExtraction(key: string, options?: {
201
+ writerStopped?: boolean;
202
+ signal?: AbortSignal;
203
+ }): Promise<MemoryOperation>;
204
+ history(id: string, options?: {
205
+ signal?: AbortSignal;
206
+ }): Promise<readonly unknown[]>;
207
+ retrieve(request: RetrievalRequest, signal?: AbortSignal, options?: {
208
+ filters?: MemoryFilters;
209
+ }): Promise<readonly RetrievalHit[]>;
210
+ drain(): Promise<void>;
211
+ close(): void;
212
+ }
213
+ export {};