@knowzai/local-store 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.
@@ -0,0 +1,416 @@
1
+ import { mkdirSync, chmodSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ import Database from 'better-sqlite3';
4
+ import * as sqliteVec from 'sqlite-vec';
5
+ import { SCHEMA_VERSION, DEFAULT_DIM, } from './types.js';
6
+ // sqlite-vec accepts a JSON array as float-vector input; this avoids a
7
+ // BLOB-binding path that misparses under better-sqlite3 (spurious rowid error).
8
+ function vecParam(v) {
9
+ return JSON.stringify(Array.from(v));
10
+ }
11
+ export class SqliteStore {
12
+ driver = 'sqlite';
13
+ db;
14
+ dim;
15
+ constructor(dbPath, dim = DEFAULT_DIM) {
16
+ this.dim = dim;
17
+ if (dbPath !== ':memory:')
18
+ mkdirSync(dirname(dbPath), { recursive: true, mode: 0o700 });
19
+ this.db = new Database(dbPath);
20
+ if (dbPath !== ':memory:')
21
+ chmodSync(dbPath, 0o600);
22
+ sqliteVec.load(this.db);
23
+ this.db.pragma('journal_mode = WAL');
24
+ }
25
+ async init() {
26
+ this.db.exec(`
27
+ CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT);
28
+ CREATE TABLE IF NOT EXISTS items (
29
+ id TEXT PRIMARY KEY, vault_id TEXT, title TEXT NOT NULL, type TEXT NOT NULL,
30
+ content_hash TEXT NOT NULL, content TEXT, tags TEXT NOT NULL DEFAULT '[]',
31
+ updated_at TEXT NOT NULL, sync_state TEXT NOT NULL, remote_version INTEGER
32
+ );
33
+ CREATE INDEX IF NOT EXISTS idx_items_vault ON items(vault_id);
34
+ CREATE INDEX IF NOT EXISTS idx_items_sync ON items(sync_state);
35
+ CREATE TABLE IF NOT EXISTS chunks (
36
+ rowid INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT UNIQUE NOT NULL, item_id TEXT NOT NULL,
37
+ ordinal INTEGER NOT NULL, text TEXT NOT NULL, start_byte INTEGER, end_byte INTEGER, lang TEXT
38
+ );
39
+ CREATE INDEX IF NOT EXISTS idx_chunks_item ON chunks(item_id);
40
+ CREATE TABLE IF NOT EXISTS file_state (
41
+ path TEXT PRIMARY KEY, hash TEXT NOT NULL, mtime_ms REAL NOT NULL, size INTEGER NOT NULL,
42
+ item_id TEXT, last_indexed_at TEXT
43
+ );
44
+ CREATE TABLE IF NOT EXISTS sync_log (
45
+ ts TEXT NOT NULL, direction TEXT NOT NULL, item_id TEXT, action TEXT, detail TEXT
46
+ );
47
+ CREATE TABLE IF NOT EXISTS observations (
48
+ id TEXT PRIMARY KEY, session_id TEXT NOT NULL, ts TEXT NOT NULL,
49
+ kind TEXT NOT NULL, tool_name TEXT, summary TEXT NOT NULL,
50
+ redacted INTEGER NOT NULL DEFAULT 0, vault_id TEXT, sealed_into_item_id TEXT
51
+ );
52
+ CREATE INDEX IF NOT EXISTS idx_obs_session ON observations(session_id);
53
+ CREATE INDEX IF NOT EXISTS idx_obs_sealed ON observations(sealed_into_item_id);
54
+ CREATE TABLE IF NOT EXISTS capture_outbox (
55
+ idempotency_key TEXT PRIMARY KEY, item_id TEXT NOT NULL, session_id TEXT NOT NULL,
56
+ created_at TEXT NOT NULL, attempts INTEGER NOT NULL DEFAULT 0, last_attempt_at TEXT,
57
+ state TEXT NOT NULL DEFAULT 'pending', last_error TEXT, lease_until TEXT
58
+ );
59
+ CREATE INDEX IF NOT EXISTS idx_outbox_state ON capture_outbox(state);
60
+ `);
61
+ this.db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS embeddings USING vec0(embedding float[${this.dim}]);`);
62
+ const existingDim = this.getMeta('dim');
63
+ if (existingDim && Number(existingDim) !== this.dim) {
64
+ throw new Error(`Local store dim mismatch: store=${existingDim}, requested=${this.dim}`);
65
+ }
66
+ this.setMeta('schemaVersion', String(SCHEMA_VERSION));
67
+ this.setMeta('dim', String(this.dim));
68
+ }
69
+ getMeta(key) {
70
+ const r = this.db.prepare('SELECT value FROM meta WHERE key = ?').get(key);
71
+ return r?.value;
72
+ }
73
+ setMeta(key, value) {
74
+ this.db
75
+ .prepare('INSERT INTO meta(key,value) VALUES(?,?) ON CONFLICT(key) DO UPDATE SET value=excluded.value')
76
+ .run(key, value);
77
+ }
78
+ rowToItem(r) {
79
+ return {
80
+ id: r.id,
81
+ vaultId: r.vault_id ?? undefined,
82
+ title: r.title,
83
+ type: r.type,
84
+ contentHash: r.content_hash,
85
+ content: r.content ?? undefined,
86
+ tags: JSON.parse(r.tags),
87
+ updatedAt: r.updated_at,
88
+ syncState: r.sync_state,
89
+ remoteVersion: r.remote_version ?? undefined,
90
+ };
91
+ }
92
+ async upsertItem(i) {
93
+ this.db
94
+ .prepare(`INSERT INTO items(id,vault_id,title,type,content_hash,content,tags,updated_at,sync_state,remote_version)
95
+ VALUES(@id,@vault_id,@title,@type,@content_hash,@content,@tags,@updated_at,@sync_state,@remote_version)
96
+ ON CONFLICT(id) DO UPDATE SET vault_id=excluded.vault_id, title=excluded.title, type=excluded.type,
97
+ content_hash=excluded.content_hash, content=excluded.content, tags=excluded.tags,
98
+ updated_at=excluded.updated_at, sync_state=excluded.sync_state, remote_version=excluded.remote_version`)
99
+ .run({
100
+ id: i.id,
101
+ vault_id: i.vaultId ?? null,
102
+ title: i.title,
103
+ type: i.type,
104
+ content_hash: i.contentHash,
105
+ content: i.content ?? null,
106
+ tags: JSON.stringify(i.tags ?? []),
107
+ updated_at: i.updatedAt,
108
+ sync_state: i.syncState,
109
+ remote_version: i.remoteVersion ?? null,
110
+ });
111
+ }
112
+ async getItem(id) {
113
+ const r = this.db.prepare('SELECT * FROM items WHERE id = ?').get(id);
114
+ return r ? this.rowToItem(r) : undefined;
115
+ }
116
+ async listItems(filter = {}) {
117
+ const where = [];
118
+ const params = [];
119
+ if (filter.vaultId) {
120
+ where.push('vault_id = ?');
121
+ params.push(filter.vaultId);
122
+ }
123
+ if (filter.syncState) {
124
+ where.push('sync_state = ?');
125
+ params.push(filter.syncState);
126
+ }
127
+ const sql = `SELECT * FROM items ${where.length ? `WHERE ${where.join(' AND ')}` : ''} ORDER BY updated_at DESC`;
128
+ return this.db.prepare(sql).all(...params).map((r) => this.rowToItem(r));
129
+ }
130
+ async reassignItemId(oldId, newId) {
131
+ const tx = this.db.transaction(() => {
132
+ this.db.prepare('UPDATE items SET id = ? WHERE id = ?').run(newId, oldId);
133
+ this.db.prepare('UPDATE chunks SET item_id = ? WHERE item_id = ?').run(newId, oldId);
134
+ this.db.prepare('UPDATE file_state SET item_id = ? WHERE item_id = ?').run(newId, oldId);
135
+ });
136
+ tx();
137
+ }
138
+ async deleteItem(id) {
139
+ const tx = this.db.transaction((itemId) => {
140
+ const rows = this.db.prepare('SELECT rowid FROM chunks WHERE item_id = ?').all(itemId);
141
+ const del = this.db.prepare('DELETE FROM embeddings WHERE rowid = ?');
142
+ for (const { rowid } of rows)
143
+ del.run(rowid);
144
+ this.db.prepare('DELETE FROM chunks WHERE item_id = ?').run(itemId);
145
+ this.db.prepare('DELETE FROM items WHERE id = ?').run(itemId);
146
+ });
147
+ tx(id);
148
+ }
149
+ async putChunks(itemId, chunks, vectors) {
150
+ const tx = this.db.transaction(() => {
151
+ const old = this.db.prepare('SELECT rowid FROM chunks WHERE item_id = ?').all(itemId);
152
+ const delEmb = this.db.prepare('DELETE FROM embeddings WHERE rowid = ?');
153
+ for (const { rowid } of old)
154
+ delEmb.run(rowid);
155
+ this.db.prepare('DELETE FROM chunks WHERE item_id = ?').run(itemId);
156
+ const insChunk = this.db.prepare(`INSERT INTO chunks(id,item_id,ordinal,text,start_byte,end_byte,lang)
157
+ VALUES(?,?,?,?,?,?,?)`);
158
+ const insEmb = this.db.prepare('INSERT INTO embeddings(rowid, embedding) VALUES(?, ?)');
159
+ chunks.forEach((c, idx) => {
160
+ const info = insChunk.run(c.id, c.itemId, c.ordinal, c.text, c.startByte ?? null, c.endByte ?? null, c.lang ?? null);
161
+ const vec = vectors?.[idx];
162
+ if (vec) {
163
+ if (vec.length !== this.dim)
164
+ throw new Error(`vector dim ${vec.length} != store dim ${this.dim}`);
165
+ // vec0 requires the rowid bound as SQLITE_INTEGER — better-sqlite3
166
+ // only does that for a BigInt, not a plain JS number.
167
+ insEmb.run(BigInt(info.lastInsertRowid), vecParam(vec));
168
+ }
169
+ });
170
+ });
171
+ tx();
172
+ }
173
+ async knnSearch(queryVec, k, filter) {
174
+ if (queryVec.length !== this.dim)
175
+ throw new Error(`query dim ${queryVec.length} != store dim ${this.dim}`);
176
+ const overfetch = filter?.vaultId ? k * 4 : k;
177
+ const rows = this.db
178
+ .prepare(`SELECT e.rowid AS rowid, e.distance AS distance,
179
+ c.id, c.item_id, c.ordinal, c.text, c.start_byte, c.end_byte, c.lang
180
+ FROM embeddings e JOIN chunks c ON c.rowid = e.rowid
181
+ WHERE e.embedding MATCH ? AND k = ?
182
+ ORDER BY e.distance`)
183
+ .all(vecParam(queryVec), overfetch);
184
+ let hits = rows.map((r) => ({
185
+ distance: r.distance,
186
+ chunk: {
187
+ id: r.id,
188
+ itemId: r.item_id,
189
+ ordinal: r.ordinal,
190
+ text: r.text,
191
+ startByte: r.start_byte ?? undefined,
192
+ endByte: r.end_byte ?? undefined,
193
+ lang: r.lang ?? undefined,
194
+ },
195
+ }));
196
+ if (filter?.vaultId) {
197
+ const inVault = new Set(this.db.prepare('SELECT id FROM items WHERE vault_id = ?').all(filter.vaultId).map((x) => x.id));
198
+ hits = hits.filter((h) => inVault.has(h.chunk.itemId)).slice(0, k);
199
+ }
200
+ return hits;
201
+ }
202
+ async setFileState(s) {
203
+ this.db
204
+ .prepare(`INSERT INTO file_state(path,hash,mtime_ms,size,item_id,last_indexed_at)
205
+ VALUES(@path,@hash,@mtime_ms,@size,@item_id,@last_indexed_at)
206
+ ON CONFLICT(path) DO UPDATE SET hash=excluded.hash, mtime_ms=excluded.mtime_ms,
207
+ size=excluded.size, item_id=excluded.item_id, last_indexed_at=excluded.last_indexed_at`)
208
+ .run({
209
+ path: s.path,
210
+ hash: s.hash,
211
+ mtime_ms: s.mtimeMs,
212
+ size: s.size,
213
+ item_id: s.itemId ?? null,
214
+ last_indexed_at: s.lastIndexedAt ?? null,
215
+ });
216
+ }
217
+ async getFileState(path) {
218
+ const r = this.db.prepare('SELECT * FROM file_state WHERE path = ?').get(path);
219
+ if (!r)
220
+ return undefined;
221
+ return {
222
+ path: r.path,
223
+ hash: r.hash,
224
+ mtimeMs: r.mtime_ms,
225
+ size: r.size,
226
+ itemId: r.item_id ?? undefined,
227
+ lastIndexedAt: r.last_indexed_at ?? undefined,
228
+ };
229
+ }
230
+ async listFileStates() {
231
+ const rows = this.db.prepare('SELECT * FROM file_state').all();
232
+ return rows.map((r) => ({
233
+ path: r.path,
234
+ hash: r.hash,
235
+ mtimeMs: r.mtime_ms,
236
+ size: r.size,
237
+ itemId: r.item_id ?? undefined,
238
+ lastIndexedAt: r.last_indexed_at ?? undefined,
239
+ }));
240
+ }
241
+ async meta() {
242
+ const itemCount = this.db.prepare('SELECT COUNT(*) AS n FROM items').get().n;
243
+ const chunkCount = this.db.prepare('SELECT COUNT(*) AS n FROM chunks').get().n;
244
+ return {
245
+ schemaVersion: Number(this.getMeta('schemaVersion') ?? SCHEMA_VERSION),
246
+ dim: Number(this.getMeta('dim') ?? this.dim),
247
+ itemCount,
248
+ chunkCount,
249
+ };
250
+ }
251
+ // ── Agent-memory capture / outbox (FEAT_AgentMemoryLocalOutbox) ─────────────
252
+ rowToObservation(r) {
253
+ return {
254
+ id: r.id,
255
+ sessionId: r.session_id,
256
+ ts: r.ts,
257
+ kind: r.kind,
258
+ toolName: r.tool_name ?? undefined,
259
+ summary: r.summary,
260
+ redacted: r.redacted === 1,
261
+ vaultId: r.vault_id ?? undefined,
262
+ sealedIntoItemId: r.sealed_into_item_id ?? undefined,
263
+ };
264
+ }
265
+ rowToOutbox(r) {
266
+ return {
267
+ idempotencyKey: r.idempotency_key,
268
+ itemId: r.item_id,
269
+ sessionId: r.session_id,
270
+ createdAt: r.created_at,
271
+ attempts: r.attempts,
272
+ lastAttemptAt: r.last_attempt_at ?? undefined,
273
+ state: r.state,
274
+ lastError: r.last_error ?? undefined,
275
+ leaseUntil: r.lease_until ?? undefined,
276
+ };
277
+ }
278
+ async recordObservation(o) {
279
+ this.db
280
+ .prepare(`INSERT INTO observations(id,session_id,ts,kind,tool_name,summary,redacted,vault_id,sealed_into_item_id)
281
+ VALUES(@id,@session_id,@ts,@kind,@tool_name,@summary,@redacted,@vault_id,@sealed_into_item_id)
282
+ ON CONFLICT(id) DO UPDATE SET session_id=excluded.session_id, ts=excluded.ts, kind=excluded.kind,
283
+ tool_name=excluded.tool_name, summary=excluded.summary, redacted=excluded.redacted,
284
+ vault_id=excluded.vault_id, sealed_into_item_id=excluded.sealed_into_item_id`)
285
+ .run({
286
+ id: o.id,
287
+ session_id: o.sessionId,
288
+ ts: o.ts,
289
+ kind: o.kind,
290
+ tool_name: o.toolName ?? null,
291
+ summary: o.summary,
292
+ redacted: o.redacted ? 1 : 0,
293
+ vault_id: o.vaultId ?? null,
294
+ sealed_into_item_id: o.sealedIntoItemId ?? null,
295
+ });
296
+ }
297
+ async listObservations(filter = {}) {
298
+ const where = [];
299
+ const params = [];
300
+ if (filter.sessionId) {
301
+ where.push('session_id = ?');
302
+ params.push(filter.sessionId);
303
+ }
304
+ if (filter.sealed === true)
305
+ where.push('sealed_into_item_id IS NOT NULL');
306
+ if (filter.sealed === false)
307
+ where.push('sealed_into_item_id IS NULL');
308
+ const sql = `SELECT * FROM observations ${where.length ? `WHERE ${where.join(' AND ')}` : ''} ORDER BY ts ASC`;
309
+ return this.db.prepare(sql).all(...params).map((r) => this.rowToObservation(r));
310
+ }
311
+ async markObservationsSealed(ids, itemId) {
312
+ if (ids.length === 0)
313
+ return;
314
+ const upd = this.db.prepare('UPDATE observations SET sealed_into_item_id = ? WHERE id = ?');
315
+ const tx = this.db.transaction((list) => {
316
+ for (const id of list)
317
+ upd.run(itemId, id);
318
+ });
319
+ tx(ids);
320
+ }
321
+ async enqueueOutbox(e) {
322
+ this.db
323
+ .prepare(`INSERT INTO capture_outbox(idempotency_key,item_id,session_id,created_at,attempts,last_attempt_at,state,last_error,lease_until)
324
+ VALUES(@idempotency_key,@item_id,@session_id,@created_at,@attempts,@last_attempt_at,@state,@last_error,@lease_until)
325
+ ON CONFLICT(idempotency_key) DO NOTHING`)
326
+ .run({
327
+ idempotency_key: e.idempotencyKey,
328
+ item_id: e.itemId,
329
+ session_id: e.sessionId,
330
+ created_at: e.createdAt,
331
+ attempts: e.attempts ?? 0,
332
+ last_attempt_at: e.lastAttemptAt ?? null,
333
+ state: e.state ?? 'pending',
334
+ last_error: e.lastError ?? null,
335
+ lease_until: e.leaseUntil ?? null,
336
+ });
337
+ }
338
+ async claimOutbox(opts) {
339
+ const claim = this.db.transaction((now, leaseUntil, limit) => {
340
+ // pending whose backoff has elapsed, OR inflight whose lease expired (crash recovery).
341
+ const candidates = this.db
342
+ .prepare(`SELECT idempotency_key FROM capture_outbox
343
+ WHERE (state = 'pending' AND (lease_until IS NULL OR lease_until <= @now))
344
+ OR (state = 'inflight' AND lease_until IS NOT NULL AND lease_until <= @now)
345
+ ORDER BY created_at ASC LIMIT @limit`)
346
+ .all({ now, limit });
347
+ const mark = this.db.prepare(`UPDATE capture_outbox SET state='inflight', lease_until=@lease, last_attempt_at=@now
348
+ WHERE idempotency_key=@key`);
349
+ for (const c of candidates)
350
+ mark.run({ lease: leaseUntil, now, key: c.idempotency_key });
351
+ return candidates.map((c) => c.idempotency_key);
352
+ });
353
+ const keys = claim(opts.now, opts.leaseUntil, opts.limit);
354
+ return keys
355
+ .map((k) => this.db.prepare('SELECT * FROM capture_outbox WHERE idempotency_key = ?').get(k))
356
+ .filter((r) => !!r)
357
+ .map((r) => this.rowToOutbox(r));
358
+ }
359
+ async updateOutbox(key, patch) {
360
+ const colMap = {
361
+ itemId: 'item_id',
362
+ sessionId: 'session_id',
363
+ createdAt: 'created_at',
364
+ attempts: 'attempts',
365
+ lastAttemptAt: 'last_attempt_at',
366
+ state: 'state',
367
+ lastError: 'last_error',
368
+ leaseUntil: 'lease_until',
369
+ };
370
+ const sets = [];
371
+ const params = { key };
372
+ for (const [k, v] of Object.entries(patch)) {
373
+ const col = colMap[k];
374
+ if (!col)
375
+ continue;
376
+ sets.push(`${col} = @${col}`);
377
+ params[col] = v ?? null;
378
+ }
379
+ if (sets.length === 0)
380
+ return;
381
+ this.db
382
+ .prepare(`UPDATE capture_outbox SET ${sets.join(', ')} WHERE idempotency_key = @key`)
383
+ .run(params);
384
+ }
385
+ async getOutbox(key) {
386
+ const r = this.db.prepare('SELECT * FROM capture_outbox WHERE idempotency_key = ?').get(key);
387
+ return r ? this.rowToOutbox(r) : undefined;
388
+ }
389
+ async listOutbox(filter = {}) {
390
+ const sql = `SELECT * FROM capture_outbox ${filter.state ? 'WHERE state = ?' : ''} ORDER BY created_at ASC`;
391
+ const rows = (filter.state
392
+ ? this.db.prepare(sql).all(filter.state)
393
+ : this.db.prepare(sql).all());
394
+ return rows.map((r) => this.rowToOutbox(r));
395
+ }
396
+ async outboxStats() {
397
+ const rows = this.db
398
+ .prepare('SELECT state, COUNT(*) AS n FROM capture_outbox GROUP BY state')
399
+ .all();
400
+ const stats = { pending: 0, inflight: 0, done: 0, dead: 0, conflict: 0 };
401
+ for (const r of rows) {
402
+ if (r.state === 'pending' ||
403
+ r.state === 'inflight' ||
404
+ r.state === 'done' ||
405
+ r.state === 'dead' ||
406
+ r.state === 'conflict') {
407
+ stats[r.state] = r.n;
408
+ }
409
+ }
410
+ return stats;
411
+ }
412
+ async close() {
413
+ this.db.close();
414
+ }
415
+ }
416
+ //# sourceMappingURL=sqlite-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-store.js","sourceRoot":"","sources":["../src/sqlite-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ import type { KnowzApiClient } from '@knowzai/api-client';
2
+ import type { LocalStore, LocalItem } from './types.js';
3
+ export interface SyncReport {
4
+ pulled: number;
5
+ pushed: number;
6
+ conflicts: string[];
7
+ skipped: number;
8
+ }
9
+ export interface SyncStatus {
10
+ total: number;
11
+ new: number;
12
+ dirty: number;
13
+ synced: number;
14
+ conflict: number;
15
+ deleted: number;
16
+ }
17
+ /** Result of one `flushOutbox()` drain pass. */
18
+ export interface FlushReport {
19
+ /** Entries claimed and attempted this pass. */
20
+ claimed: number;
21
+ /** Successfully delivered to the cloud (outbox → done). */
22
+ sent: number;
23
+ /** Transient failures deferred for retry (outbox → pending w/ backoff). */
24
+ failed: number;
25
+ /** Permanently failed / max-attempts exceeded (outbox → dead). */
26
+ dead: number;
27
+ conflicts: string[];
28
+ }
29
+ export interface FlushOptions {
30
+ /** Max entries to process this pass. Default 100. */
31
+ limit?: number;
32
+ /** Lease window (ms) a claimed entry holds before it can be reclaimed. Default 60s. */
33
+ leaseMs?: number;
34
+ /** Attempts after which a transient failure dead-letters. Default 5. */
35
+ maxAttempts?: number;
36
+ /** Base retry backoff (ms); doubles per attempt, capped at maxBackoffMs. Default 1s. */
37
+ baseBackoffMs?: number;
38
+ /** Backoff ceiling (ms). Default 5min. */
39
+ maxBackoffMs?: number;
40
+ /** Injectable clock (epoch ms) for deterministic tests. Default Date.now. */
41
+ now?: () => number;
42
+ /** Provenance stamped into each created item's metadata (e.g. the profile). */
43
+ source?: string;
44
+ }
45
+ /**
46
+ * Optional content encryptor (Model-3 CMEK). When present, push encrypts item
47
+ * content before it leaves the machine and pull decrypts after fetch, so the
48
+ * cloud only ever stores ciphertext.
49
+ */
50
+ export interface ContentEncryptor {
51
+ encrypt(plaintext: string): string;
52
+ decrypt(ciphertext: string): string;
53
+ isEncrypted(s: string): boolean;
54
+ }
55
+ export declare class SyncEngine {
56
+ private readonly store;
57
+ private readonly client;
58
+ private readonly encryptor?;
59
+ constructor(store: LocalStore, client: KnowzApiClient, opts?: {
60
+ encryptor?: ContentEncryptor;
61
+ });
62
+ /**
63
+ * Iterate EVERY page of `knowledge.list` for a vault, invoking `onSummary`
64
+ * per remote item. Stops when the cumulative count reaches `total` OR a page
65
+ * returns fewer than `pageSize` items (defensive against a 0/undefined total),
66
+ * so the full remote set is always covered without an infinite loop.
67
+ */
68
+ private forEachRemote;
69
+ /** Cloud → local. Upserts remote items; flags conflicts; skips unchanged. */
70
+ pull(opts?: {
71
+ vaultId?: string;
72
+ pageSize?: number;
73
+ }): Promise<SyncReport>;
74
+ /** Local dirty/new → cloud. Clears dirty + records remoteVersion. */
75
+ push(opts?: {
76
+ vaultId?: string;
77
+ }): Promise<SyncReport>;
78
+ run(opts?: {
79
+ vaultId?: string;
80
+ }): Promise<SyncReport>;
81
+ status(): Promise<SyncStatus>;
82
+ /** Items currently in conflict (local + remote both changed). */
83
+ listConflicts(): Promise<LocalItem[]>;
84
+ /** Resolve one conflicted item by keeping the remote copy or the local copy. */
85
+ resolveConflict(id: string, strategy: 'remote' | 'local'): Promise<'updated-from-remote' | 'kept-local' | 'not-found'>;
86
+ /**
87
+ * Recovery: re-pull authoritative cloud state to repair the local store
88
+ * (overwrites non-dirty items, preserves dirty-vs-advanced as conflicts) and
89
+ * report any local `synced` items no longer present remotely (orphans).
90
+ */
91
+ recover(opts?: {
92
+ vaultId?: string;
93
+ pageSize?: number;
94
+ }): Promise<{
95
+ repaired: number;
96
+ conflicts: string[];
97
+ orphanedLocal: string[];
98
+ }>;
99
+ /**
100
+ * Drain the capture outbox to the cloud (FEAT_AgentMemoryLocalOutbox).
101
+ *
102
+ * Each claimed entry's sealed content lives in `items`; we create it via the
103
+ * existing `knowledge.create` path (the batch endpoint is not yet shipped),
104
+ * stamping the idempotency key into item metadata for best-effort server-side
105
+ * dedup. Idempotency is enforced LOCALLY: a `done` entry is never reclaimed,
106
+ * and re-enqueue is a no-op on the idempotency-key PK. The only double-create
107
+ * window is "create succeeded but its ack was lost before we marked done" —
108
+ * acceptable until the content-hash-dedup batch endpoint lands.
109
+ *
110
+ * Resilience: claims `pending` (whose backoff elapsed) plus `inflight` whose
111
+ * lease expired (crash recovery). Transient failures back off exponentially;
112
+ * after `maxAttempts` an entry dead-letters (visible via `outboxStats`). This
113
+ * is what makes the orphaned-pending-captures leak structurally impossible —
114
+ * a capture is a committed row drained by an idempotent, retrying consumer.
115
+ */
116
+ flushOutbox(opts?: FlushOptions): Promise<FlushReport>;
117
+ }
118
+ //# sourceMappingURL=sync-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../src/sync-engine.ts"],"names":[],"mappings":"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"}