@de-otio/chaoskb-client 0.3.0 → 0.3.2

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.
Files changed (80) hide show
  1. package/dist/cli/bootstrap.d.ts.map +1 -1
  2. package/dist/cli/bootstrap.js +20 -27
  3. package/dist/cli/bootstrap.js.map +1 -1
  4. package/dist/cli/commands/devices.d.ts.map +1 -1
  5. package/dist/cli/commands/devices.js +7 -70
  6. package/dist/cli/commands/devices.js.map +1 -1
  7. package/dist/cli/commands/notifications.d.ts.map +1 -1
  8. package/dist/cli/commands/notifications.js +1 -39
  9. package/dist/cli/commands/notifications.js.map +1 -1
  10. package/dist/cli/commands/projects.d.ts.map +1 -1
  11. package/dist/cli/commands/projects.js +9 -44
  12. package/dist/cli/commands/projects.js.map +1 -1
  13. package/dist/cli/commands/rotate-key.d.ts.map +1 -1
  14. package/dist/cli/commands/rotate-key.js +14 -32
  15. package/dist/cli/commands/rotate-key.js.map +1 -1
  16. package/dist/cli/commands/setup-sync.js +7 -15
  17. package/dist/cli/commands/setup-sync.js.map +1 -1
  18. package/dist/cli/mcp-server.d.ts +3 -0
  19. package/dist/cli/mcp-server.d.ts.map +1 -1
  20. package/dist/cli/mcp-server.js +21 -2
  21. package/dist/cli/mcp-server.js.map +1 -1
  22. package/dist/cli/tools/kb-delete.d.ts.map +1 -1
  23. package/dist/cli/tools/kb-delete.js +4 -6
  24. package/dist/cli/tools/kb-delete.js.map +1 -1
  25. package/dist/cli/tools/kb-ingest.d.ts.map +1 -1
  26. package/dist/cli/tools/kb-ingest.js +8 -5
  27. package/dist/cli/tools/kb-ingest.js.map +1 -1
  28. package/dist/cli/tools/sync-client.d.ts +3 -1
  29. package/dist/cli/tools/sync-client.d.ts.map +1 -1
  30. package/dist/cli/tools/sync-client.js +10 -30
  31. package/dist/cli/tools/sync-client.js.map +1 -1
  32. package/dist/storage/kb-database.d.ts +6 -1
  33. package/dist/storage/kb-database.d.ts.map +1 -1
  34. package/dist/storage/kb-database.js +18 -0
  35. package/dist/storage/kb-database.js.map +1 -1
  36. package/dist/storage/schema.d.ts +1 -1
  37. package/dist/storage/schema.d.ts.map +1 -1
  38. package/dist/storage/schema.js +153 -1
  39. package/dist/storage/schema.js.map +1 -1
  40. package/dist/storage/sync-queue-repo.d.ts +28 -0
  41. package/dist/storage/sync-queue-repo.d.ts.map +1 -0
  42. package/dist/storage/sync-queue-repo.js +107 -0
  43. package/dist/storage/sync-queue-repo.js.map +1 -0
  44. package/dist/storage/sync-sequence-repo.d.ts +17 -0
  45. package/dist/storage/sync-sequence-repo.d.ts.map +1 -0
  46. package/dist/storage/sync-sequence-repo.js +24 -0
  47. package/dist/storage/sync-sequence-repo.js.map +1 -0
  48. package/dist/storage/sync-state-repo.d.ts +16 -0
  49. package/dist/storage/sync-state-repo.d.ts.map +1 -0
  50. package/dist/storage/sync-state-repo.js +25 -0
  51. package/dist/storage/sync-state-repo.js.map +1 -0
  52. package/dist/storage/types.d.ts +51 -0
  53. package/dist/storage/types.d.ts.map +1 -1
  54. package/dist/sync/client-factory.d.ts +21 -0
  55. package/dist/sync/client-factory.d.ts.map +1 -0
  56. package/dist/sync/client-factory.js +36 -0
  57. package/dist/sync/client-factory.js.map +1 -0
  58. package/dist/sync/http-client.d.ts +2 -2
  59. package/dist/sync/http-client.d.ts.map +1 -1
  60. package/dist/sync/http-client.js +9 -3
  61. package/dist/sync/http-client.js.map +1 -1
  62. package/dist/sync/index.d.ts +2 -0
  63. package/dist/sync/index.d.ts.map +1 -1
  64. package/dist/sync/index.js +2 -0
  65. package/dist/sync/index.js.map +1 -1
  66. package/dist/sync/queue-processor.d.ts +38 -0
  67. package/dist/sync/queue-processor.d.ts.map +1 -0
  68. package/dist/sync/queue-processor.js +96 -0
  69. package/dist/sync/queue-processor.js.map +1 -0
  70. package/dist/sync/ssh-signer.d.ts +6 -1
  71. package/dist/sync/ssh-signer.d.ts.map +1 -1
  72. package/dist/sync/ssh-signer.js +9 -2
  73. package/dist/sync/ssh-signer.js.map +1 -1
  74. package/dist/sync/sync-service.d.ts +18 -8
  75. package/dist/sync/sync-service.d.ts.map +1 -1
  76. package/dist/sync/sync-service.js +55 -43
  77. package/dist/sync/sync-service.js.map +1 -1
  78. package/dist/sync/types.d.ts +4 -0
  79. package/dist/sync/types.d.ts.map +1 -1
  80. package/package.json +3 -2
@@ -1,4 +1,7 @@
1
- export const SCHEMA_VERSION = 2;
1
+ import { existsSync, readFileSync, renameSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ export const SCHEMA_VERSION = 4;
2
5
  export const CREATE_TABLES_SQL = [
3
6
  `CREATE TABLE IF NOT EXISTS sources (
4
7
  id TEXT PRIMARY KEY,
@@ -54,6 +57,34 @@ export const CREATE_TABLES_SQL = [
54
57
  INSERT INTO chunks_fts(rowid, content, source_id, chunk_index)
55
58
  VALUES (new.rowid, new.content, new.source_id, new.chunk_index);
56
59
  END`,
60
+ // --- v3: Sync infrastructure tables ---
61
+ `CREATE TABLE IF NOT EXISTS sync_sequence (
62
+ id INTEGER PRIMARY KEY CHECK (id = 1),
63
+ value INTEGER NOT NULL DEFAULT 0
64
+ )`,
65
+ `INSERT OR IGNORE INTO sync_sequence (id, value) VALUES (1, 0)`,
66
+ `CREATE TABLE IF NOT EXISTS sync_queue (
67
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
68
+ blob_id TEXT NOT NULL,
69
+ operation TEXT NOT NULL CHECK (operation IN ('upload', 'delete')),
70
+ data BLOB,
71
+ retry_count INTEGER NOT NULL DEFAULT 0,
72
+ max_retries INTEGER NOT NULL DEFAULT 5,
73
+ last_attempt TEXT,
74
+ next_attempt TEXT,
75
+ error_message TEXT,
76
+ status TEXT NOT NULL DEFAULT 'pending'
77
+ CHECK (status IN ('pending', 'processing', 'failed', 'completed')),
78
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
79
+ )`,
80
+ `CREATE INDEX IF NOT EXISTS idx_sync_queue_status
81
+ ON sync_queue(status, next_attempt)`,
82
+ `CREATE INDEX IF NOT EXISTS idx_sync_queue_blob
83
+ ON sync_queue(blob_id)`,
84
+ `CREATE TABLE IF NOT EXISTS sync_state (
85
+ key TEXT PRIMARY KEY,
86
+ value TEXT NOT NULL
87
+ )`,
57
88
  ];
58
89
  export function initializeSchema(db) {
59
90
  const existing = db
@@ -88,6 +119,12 @@ export function migrateSchema(db) {
88
119
  if (currentVersion < 2) {
89
120
  runMigrationV2(db);
90
121
  }
122
+ if (currentVersion < 3) {
123
+ runMigrationV3(db);
124
+ }
125
+ if (currentVersion < 4) {
126
+ runMigrationV4(db);
127
+ }
91
128
  db.prepare('UPDATE schema_version SET version = ?').run(SCHEMA_VERSION);
92
129
  }
93
130
  /**
@@ -119,4 +156,119 @@ function runMigrationV2(db) {
119
156
  db.exec(`INSERT INTO chunks_fts(rowid, content, source_id, chunk_index)
120
157
  SELECT rowid, content, source_id, chunk_index FROM chunks`);
121
158
  }
159
+ /**
160
+ * Migration v3: Add sync infrastructure tables.
161
+ *
162
+ * Moves sequence counter, upload queue, and sync state from flat files
163
+ * into SQLite for safe multi-process concurrent access.
164
+ */
165
+ function runMigrationV3(db) {
166
+ db.exec(`CREATE TABLE IF NOT EXISTS sync_sequence (
167
+ id INTEGER PRIMARY KEY CHECK (id = 1),
168
+ value INTEGER NOT NULL DEFAULT 0
169
+ )`);
170
+ db.exec(`INSERT OR IGNORE INTO sync_sequence (id, value) VALUES (1, 0)`);
171
+ db.exec(`CREATE TABLE IF NOT EXISTS sync_queue (
172
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
173
+ blob_id TEXT NOT NULL,
174
+ operation TEXT NOT NULL CHECK (operation IN ('upload', 'delete')),
175
+ data BLOB,
176
+ retry_count INTEGER NOT NULL DEFAULT 0,
177
+ max_retries INTEGER NOT NULL DEFAULT 5,
178
+ last_attempt TEXT,
179
+ next_attempt TEXT,
180
+ error_message TEXT,
181
+ status TEXT NOT NULL DEFAULT 'pending'
182
+ CHECK (status IN ('pending', 'processing', 'failed', 'completed')),
183
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
184
+ )`);
185
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_sync_queue_status
186
+ ON sync_queue(status, next_attempt)`);
187
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_sync_queue_blob
188
+ ON sync_queue(blob_id)`);
189
+ db.exec(`CREATE TABLE IF NOT EXISTS sync_state (
190
+ key TEXT PRIMARY KEY,
191
+ value TEXT NOT NULL
192
+ )`);
193
+ // Import existing flat-file data if present
194
+ importFlatFileData(db);
195
+ }
196
+ /**
197
+ * Import data from legacy flat files into SQLite tables.
198
+ * Reads ~/.chaoskb/sequence, upload-queue.json, and sync-state.json.
199
+ * Files are left on disk as rollback backups.
200
+ */
201
+ function importFlatFileData(db) {
202
+ const chaoskbDir = join(homedir(), '.chaoskb');
203
+ // Import sequence counter
204
+ const seqPath = join(chaoskbDir, 'sequence');
205
+ if (existsSync(seqPath)) {
206
+ try {
207
+ const value = parseInt(readFileSync(seqPath, 'utf-8').trim(), 10);
208
+ if (!isNaN(value) && value > 0) {
209
+ db.prepare('UPDATE sync_sequence SET value = ? WHERE id = 1').run(value);
210
+ }
211
+ try {
212
+ renameSync(seqPath, seqPath + '.migrated');
213
+ }
214
+ catch { /* already renamed */ }
215
+ }
216
+ catch { /* ignore read errors */ }
217
+ }
218
+ // Import upload queue
219
+ const queuePath = join(chaoskbDir, 'upload-queue.json');
220
+ if (existsSync(queuePath)) {
221
+ try {
222
+ const items = JSON.parse(readFileSync(queuePath, 'utf-8'));
223
+ const insertStmt = db.prepare(`
224
+ INSERT OR IGNORE INTO sync_queue (blob_id, operation, data, retry_count, error_message, status)
225
+ VALUES (?, 'upload', ?, ?, ?, 'pending')
226
+ `);
227
+ for (const item of items) {
228
+ const data = item.data ? Buffer.from(item.data, 'base64') : null;
229
+ insertStmt.run(item.blobId, data, item.retryCount, item.error ?? null);
230
+ }
231
+ try {
232
+ renameSync(queuePath, queuePath + '.migrated');
233
+ }
234
+ catch { /* already renamed */ }
235
+ }
236
+ catch { /* ignore parse errors */ }
237
+ }
238
+ // Import sync state
239
+ const statePath = join(chaoskbDir, 'sync-state.json');
240
+ if (existsSync(statePath)) {
241
+ try {
242
+ const state = JSON.parse(readFileSync(statePath, 'utf-8'));
243
+ const insertStmt = db.prepare('INSERT OR IGNORE INTO sync_state (key, value) VALUES (?, ?)');
244
+ for (const [key, value] of Object.entries(state)) {
245
+ if (value !== undefined && value !== null) {
246
+ insertStmt.run(key, String(value));
247
+ }
248
+ }
249
+ try {
250
+ renameSync(statePath, statePath + '.migrated');
251
+ }
252
+ catch { /* already renamed */ }
253
+ }
254
+ catch { /* ignore parse errors */ }
255
+ }
256
+ }
257
+ /**
258
+ * Migration v4: Reset stale sync queue items.
259
+ *
260
+ * After fixing WAF body size blocking and sequence counter drift,
261
+ * previously failed/retried items need a fresh attempt.
262
+ */
263
+ function runMigrationV4(db) {
264
+ db.exec(`
265
+ UPDATE sync_queue
266
+ SET status = 'pending',
267
+ retry_count = 0,
268
+ error_message = NULL,
269
+ next_attempt = NULL
270
+ WHERE status IN ('pending', 'failed')
271
+ AND retry_count > 0
272
+ `);
273
+ }
122
274
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../storage/schema.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,MAAM,CAAC,MAAM,iBAAiB,GAAa;IACzC;;;;;;;;;;;IAWE;IACF;;;;;;;;;IASE;IACF;;;;;IAKE;IACF;;IAEE;IACF,2DAA2D;IAC3D;;;;;;IAME;IACF,2DAA2D;IAC3D;;;MAGI;IACJ;;;MAGI;IACJ;;;;;MAKI;CACL,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,EAA0B;IACzD,MAAM,QAAQ,GAAG,EAAE;SAChB,OAAO,CAAC,6EAA6E,CAAC;SACtF,GAAG,EAAkC,CAAC;IAEzC,IAAI,QAAQ,EAAE,CAAC;QACb,gDAAgD;QAChD,aAAa,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO;IACT,CAAC;IAED,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;QAClB,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACpC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QACD,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACpF,CAAC,CAAC,EAAE,CAAC;AACP,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAA0B;IACtD,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,EAEnD,CAAC;IAEd,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,2CAA2C;QAC3C,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACpC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QACD,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAClF,OAAO;IACT,CAAC;IAED,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC;IAEnC,IAAI,cAAc,IAAI,cAAc,EAAE,CAAC;QACrC,OAAO,CAAC,qBAAqB;IAC/B,CAAC;IAED,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACvB,cAAc,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,EAAE,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,EAA0B;IAChD,EAAE,CAAC,IAAI,CAAC;;;;;;IAMN,CAAC,CAAC;IAEJ,EAAE,CAAC,IAAI,CAAC;;;MAGJ,CAAC,CAAC;IAEN,EAAE,CAAC,IAAI,CAAC;;;MAGJ,CAAC,CAAC;IAEN,EAAE,CAAC,IAAI,CAAC;;;;;MAKJ,CAAC,CAAC;IAEN,wDAAwD;IACxD,EAAE,CAAC,IAAI,CAAC;8DACoD,CAAC,CAAC;AAChE,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../storage/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type BetterSqlite3 from 'better-sqlite3';
2
+ import type { ISyncQueueRepository, SyncQueueItem } from './types.js';
3
+ /**
4
+ * SQLite-backed sync queue for uploads and deletes.
5
+ *
6
+ * Multi-process safe: uses atomic UPDATE...RETURNING for claim,
7
+ * so concurrent processes never double-process an item.
8
+ */
9
+ export declare class SyncQueueRepository implements ISyncQueueRepository {
10
+ private readonly db;
11
+ private readonly enqueueStmt;
12
+ private readonly deleteExistingPendingStmt;
13
+ private readonly claimStmt;
14
+ private readonly completeStmt;
15
+ private readonly failStmt;
16
+ private readonly permanentFailStmt;
17
+ private readonly releaseStaleStmt;
18
+ private readonly pendingCountStmt;
19
+ constructor(db: BetterSqlite3.Database);
20
+ enqueue(blobId: string, operation: 'upload' | 'delete', data?: Uint8Array): void;
21
+ claimBatch(limit: number): SyncQueueItem[];
22
+ complete(id: number): void;
23
+ fail(id: number, error: string): void;
24
+ permanentFail(id: number, error: string): void;
25
+ releaseStale(olderThanSeconds: number): number;
26
+ pendingCount(): number;
27
+ }
28
+ //# sourceMappingURL=sync-queue-repo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-queue-repo.d.ts","sourceRoot":"","sources":["../../storage/sync-queue-repo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAgCtE;;;;;GAKG;AACH,qBAAa,mBAAoB,YAAW,oBAAoB;IAC9D,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAA0B;IACpE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA0B;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;IACnD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA0B;IAC5D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IAC3D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;gBAE/C,EAAE,EAAE,aAAa,CAAC,QAAQ;IAwDtC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,GAAG,QAAQ,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI;IAOhF,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE;IAK1C,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI1B,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI9C,YAAY,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM;IAK9C,YAAY,IAAI,MAAM;CAIvB"}
@@ -0,0 +1,107 @@
1
+ function rowToItem(row) {
2
+ return {
3
+ id: row.id,
4
+ blobId: row.blob_id,
5
+ operation: row.operation,
6
+ data: row.data ? new Uint8Array(row.data) : null,
7
+ retryCount: row.retry_count,
8
+ maxRetries: row.max_retries,
9
+ lastAttempt: row.last_attempt ?? undefined,
10
+ nextAttempt: row.next_attempt ?? undefined,
11
+ errorMessage: row.error_message ?? undefined,
12
+ status: row.status,
13
+ createdAt: row.created_at,
14
+ };
15
+ }
16
+ /**
17
+ * SQLite-backed sync queue for uploads and deletes.
18
+ *
19
+ * Multi-process safe: uses atomic UPDATE...RETURNING for claim,
20
+ * so concurrent processes never double-process an item.
21
+ */
22
+ export class SyncQueueRepository {
23
+ db;
24
+ enqueueStmt;
25
+ deleteExistingPendingStmt;
26
+ claimStmt;
27
+ completeStmt;
28
+ failStmt;
29
+ permanentFailStmt;
30
+ releaseStaleStmt;
31
+ pendingCountStmt;
32
+ constructor(db) {
33
+ this.db = db;
34
+ this.enqueueStmt = db.prepare(`
35
+ INSERT INTO sync_queue (blob_id, operation, data, status)
36
+ VALUES (?, ?, ?, 'pending')
37
+ `);
38
+ this.deleteExistingPendingStmt = db.prepare(`
39
+ DELETE FROM sync_queue
40
+ WHERE blob_id = ? AND operation = ? AND status = 'pending'
41
+ `);
42
+ this.claimStmt = db.prepare(`
43
+ UPDATE sync_queue
44
+ SET status = 'processing', last_attempt = datetime('now')
45
+ WHERE id IN (
46
+ SELECT id FROM sync_queue
47
+ WHERE status = 'pending'
48
+ AND (next_attempt IS NULL OR next_attempt <= datetime('now'))
49
+ ORDER BY created_at ASC
50
+ LIMIT ?
51
+ )
52
+ RETURNING *
53
+ `);
54
+ this.completeStmt = db.prepare('DELETE FROM sync_queue WHERE id = ?');
55
+ this.failStmt = db.prepare(`
56
+ UPDATE sync_queue
57
+ SET status = 'pending',
58
+ retry_count = retry_count + 1,
59
+ error_message = ?,
60
+ next_attempt = datetime('now', '+' || (1 << MIN(retry_count, 10)) || ' seconds')
61
+ WHERE id = ?
62
+ `);
63
+ this.permanentFailStmt = db.prepare(`
64
+ UPDATE sync_queue
65
+ SET status = 'failed', error_message = ?
66
+ WHERE id = ?
67
+ `);
68
+ this.releaseStaleStmt = db.prepare(`
69
+ UPDATE sync_queue
70
+ SET status = 'pending', next_attempt = NULL
71
+ WHERE status = 'processing'
72
+ AND last_attempt < datetime('now', '-' || ? || ' seconds')
73
+ `);
74
+ this.pendingCountStmt = db.prepare(`
75
+ SELECT COUNT(*) as count FROM sync_queue
76
+ WHERE status IN ('pending', 'processing')
77
+ `);
78
+ }
79
+ enqueue(blobId, operation, data) {
80
+ this.db.transaction(() => {
81
+ this.deleteExistingPendingStmt.run(blobId, operation);
82
+ this.enqueueStmt.run(blobId, operation, data ? Buffer.from(data) : null);
83
+ })();
84
+ }
85
+ claimBatch(limit) {
86
+ const rows = this.claimStmt.all(limit);
87
+ return rows.map(rowToItem);
88
+ }
89
+ complete(id) {
90
+ this.completeStmt.run(id);
91
+ }
92
+ fail(id, error) {
93
+ this.failStmt.run(error, id);
94
+ }
95
+ permanentFail(id, error) {
96
+ this.permanentFailStmt.run(error, id);
97
+ }
98
+ releaseStale(olderThanSeconds) {
99
+ const result = this.releaseStaleStmt.run(olderThanSeconds);
100
+ return result.changes;
101
+ }
102
+ pendingCount() {
103
+ const row = this.pendingCountStmt.get();
104
+ return row.count;
105
+ }
106
+ }
107
+ //# sourceMappingURL=sync-queue-repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-queue-repo.js","sourceRoot":"","sources":["../../storage/sync-queue-repo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type BetterSqlite3 from 'better-sqlite3';
2
+ import type { ISyncSequenceRepository } from './types.js';
3
+ /**
4
+ * SQLite-backed atomic sequence counter.
5
+ *
6
+ * Uses UPDATE...RETURNING for atomic increment. SQLite's write
7
+ * serialization (WAL mode + busy_timeout) ensures that concurrent
8
+ * processes never produce duplicate sequence numbers.
9
+ */
10
+ export declare class SyncSequenceRepository implements ISyncSequenceRepository {
11
+ private readonly nextStmt;
12
+ private readonly peekStmt;
13
+ constructor(db: BetterSqlite3.Database);
14
+ next(): number;
15
+ peek(): number;
16
+ }
17
+ //# sourceMappingURL=sync-sequence-repo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-sequence-repo.d.ts","sourceRoot":"","sources":["../../storage/sync-sequence-repo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;GAMG;AACH,qBAAa,sBAAuB,YAAW,uBAAuB;IACpE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;gBAEvC,EAAE,EAAE,aAAa,CAAC,QAAQ;IAOtC,IAAI,IAAI,MAAM;IAKd,IAAI,IAAI,MAAM;CAIf"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * SQLite-backed atomic sequence counter.
3
+ *
4
+ * Uses UPDATE...RETURNING for atomic increment. SQLite's write
5
+ * serialization (WAL mode + busy_timeout) ensures that concurrent
6
+ * processes never produce duplicate sequence numbers.
7
+ */
8
+ export class SyncSequenceRepository {
9
+ nextStmt;
10
+ peekStmt;
11
+ constructor(db) {
12
+ this.nextStmt = db.prepare('UPDATE sync_sequence SET value = value + 1 WHERE id = 1 RETURNING value');
13
+ this.peekStmt = db.prepare('SELECT value FROM sync_sequence WHERE id = 1');
14
+ }
15
+ next() {
16
+ const row = this.nextStmt.get();
17
+ return row.value;
18
+ }
19
+ peek() {
20
+ const row = this.peekStmt.get();
21
+ return row.value;
22
+ }
23
+ }
24
+ //# sourceMappingURL=sync-sequence-repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-sequence-repo.js","sourceRoot":"","sources":["../../storage/sync-sequence-repo.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,OAAO,sBAAsB;IAChB,QAAQ,CAA0B;IAClC,QAAQ,CAA0B;IAEnD,YAAY,EAA0B;QACpC,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC,OAAO,CACxB,yEAAyE,CAC1E,CAAC;QACF,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAuB,CAAC;QACrD,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IAED,IAAI;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAuB,CAAC;QACrD,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type BetterSqlite3 from 'better-sqlite3';
2
+ import type { ISyncStateRepository } from './types.js';
3
+ /**
4
+ * SQLite-backed key-value store for sync state.
5
+ * Replaces ~/.chaoskb/sync-state.json with multi-process safe storage.
6
+ */
7
+ export declare class SyncStateRepository implements ISyncStateRepository {
8
+ private readonly getStmt;
9
+ private readonly setStmt;
10
+ private readonly deleteStmt;
11
+ constructor(db: BetterSqlite3.Database);
12
+ get(key: string): string | undefined;
13
+ set(key: string, value: string): void;
14
+ delete(key: string): void;
15
+ }
16
+ //# sourceMappingURL=sync-state-repo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-state-repo.d.ts","sourceRoot":"","sources":["../../storage/sync-state-repo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,oBAAoB;IAC9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0B;gBAEzC,EAAE,EAAE,aAAa,CAAC,QAAQ;IAMtC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKpC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAG1B"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * SQLite-backed key-value store for sync state.
3
+ * Replaces ~/.chaoskb/sync-state.json with multi-process safe storage.
4
+ */
5
+ export class SyncStateRepository {
6
+ getStmt;
7
+ setStmt;
8
+ deleteStmt;
9
+ constructor(db) {
10
+ this.getStmt = db.prepare('SELECT value FROM sync_state WHERE key = ?');
11
+ this.setStmt = db.prepare('INSERT OR REPLACE INTO sync_state (key, value) VALUES (?, ?)');
12
+ this.deleteStmt = db.prepare('DELETE FROM sync_state WHERE key = ?');
13
+ }
14
+ get(key) {
15
+ const row = this.getStmt.get(key);
16
+ return row?.value;
17
+ }
18
+ set(key, value) {
19
+ this.setStmt.run(key, value);
20
+ }
21
+ delete(key) {
22
+ this.deleteStmt.run(key);
23
+ }
24
+ }
25
+ //# sourceMappingURL=sync-state-repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-state-repo.js","sourceRoot":"","sources":["../../storage/sync-state-repo.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IACb,OAAO,CAA0B;IACjC,OAAO,CAA0B;IACjC,UAAU,CAA0B;IAErD,YAAY,EAA0B;QACpC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,4CAA4C,CAAC,CAAC;QACxE,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,8DAA8D,CAAC,CAAC;QAC1F,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC;IACvE,CAAC;IAED,GAAG,CAAC,GAAW;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAkC,CAAC;QACnE,OAAO,GAAG,EAAE,KAAK,CAAC;IACpB,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAa;QAC5B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;CACF"}
@@ -130,12 +130,63 @@ export interface IDatabaseManager {
130
130
  /** Close all open databases */
131
131
  closeAll(): void;
132
132
  }
133
+ /** Sync queue item */
134
+ export interface SyncQueueItem {
135
+ id: number;
136
+ blobId: string;
137
+ operation: 'upload' | 'delete';
138
+ data: Uint8Array | null;
139
+ retryCount: number;
140
+ maxRetries: number;
141
+ lastAttempt?: string;
142
+ nextAttempt?: string;
143
+ errorMessage?: string;
144
+ status: 'pending' | 'processing' | 'failed' | 'completed';
145
+ createdAt: string;
146
+ }
147
+ /** Sync queue repository — SQLite-backed, multi-process safe */
148
+ export interface ISyncQueueRepository {
149
+ /** Enqueue an upload or delete. Replaces existing pending entry for same blob+operation. */
150
+ enqueue(blobId: string, operation: 'upload' | 'delete', data?: Uint8Array): void;
151
+ /** Atomically claim pending items for processing. Each item is claimed by exactly one process. */
152
+ claimBatch(limit: number): SyncQueueItem[];
153
+ /** Mark an item as completed (deletes from queue). */
154
+ complete(id: number): void;
155
+ /** Mark an item as failed with error, increment retry count, set exponential backoff. */
156
+ fail(id: number, error: string): void;
157
+ /** Mark an item as permanently failed (exceeded max retries). */
158
+ permanentFail(id: number, error: string): void;
159
+ /** Release stale 'processing' items back to 'pending' (crash recovery). */
160
+ releaseStale(olderThanSeconds: number): number;
161
+ /** Count of pending + processing items. */
162
+ pendingCount(): number;
163
+ }
164
+ /** Atomic sequence counter — SQLite-backed, multi-process safe */
165
+ export interface ISyncSequenceRepository {
166
+ /** Atomically increment and return the new value. */
167
+ next(): number;
168
+ /** Get current value without incrementing. */
169
+ peek(): number;
170
+ }
171
+ /** Key-value sync state store — SQLite-backed */
172
+ export interface ISyncStateRepository {
173
+ get(key: string): string | undefined;
174
+ set(key: string, value: string): void;
175
+ delete(key: string): void;
176
+ }
133
177
  /** Combined database interface */
134
178
  export interface IDatabase {
135
179
  readonly sources: ISourceRepository;
136
180
  readonly chunks: IChunkRepository;
137
181
  readonly syncStatus: ISyncStatusRepository;
138
182
  readonly embeddingIndex: IEmbeddingIndex;
183
+ readonly syncQueue: ISyncQueueRepository;
184
+ readonly syncSequence: ISyncSequenceRepository;
185
+ readonly syncState: ISyncStateRepository;
186
+ /** Enqueue an encrypted blob for upload. Sets sync status to local_only. */
187
+ storeAndEnqueueUpload(blobId: string, encryptedBytes: Uint8Array): void;
188
+ /** Enqueue a blob for deletion from the sync server. Sets sync status to pending_delete. */
189
+ enqueueDelete(blobId: string): void;
139
190
  close(): void;
140
191
  }
141
192
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../storage/types.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,YAAY,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,6BAA6B;AAC7B,oBAAY,UAAU;IACpB,SAAS,eAAe;IACxB,MAAM,WAAW;IACjB,aAAa,mBAAmB;IAChC,UAAU,gBAAgB;CAC3B;AAED,yBAAyB;AACzB,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,yBAAyB;AACzB,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yCAAyC;AACzC,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,kCAAkC;AAClC,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,WAAW,GAAG,gBAAgB,CAAC,GAAG,YAAY,CAAC;IAC/F,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,YAAY,EAAE,CAAC;IAC5E,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IACrC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,iCAAiC;AACjC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,GAAG,WAAW,EAAE,CAAC;IAC7D,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;IAC/C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3C,uDAAuD;IACvD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAAC;CACnE;AAED,uCAAuC;AACvC,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC7C,UAAU,IAAI,gBAAgB,EAAE,CAAC;IACjC,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAAC;CACrD;AAED,2CAA2C;AAC3C,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,IAAI,IAAI,IAAI,CAAC;IACb,kCAAkC;IAClC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,YAAY,CAAA;KAAE,EAAE,GAAG,IAAI,CAAC;IACvF,qCAAqC;IACrC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oEAAoE;IACpE,MAAM,CACJ,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,GACX;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7D,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wCAAwC;AACxC,MAAM,WAAW,gBAAgB;IAC/B,0CAA0C;IAC1C,aAAa,IAAI,SAAS,CAAC;IAC3B,uCAAuC;IACvC,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,qEAAqE;IACrE,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,iCAAiC;IACjC,YAAY,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzF,gCAAgC;IAChC,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5C,+BAA+B;IAC/B,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED,kCAAkC;AAClC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC;IACzC,KAAK,IAAI,IAAI,CAAC;CACf"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../storage/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { SyncConfig } from './types.js';
2
+ import type { ISyncSequenceRepository } from '../storage/types.js';
3
+ import { SyncHttpClient } from './http-client.js';
4
+ /**
5
+ * Create a SyncHttpClient from explicit config.
6
+ *
7
+ * Requires a DB-backed ISyncSequenceRepository to prevent
8
+ * sequence counter drift between SQLite and legacy flat files.
9
+ */
10
+ export declare function createSyncHttpClientFromConfig(config: SyncConfig, sequence: ISyncSequenceRepository): SyncHttpClient;
11
+ /**
12
+ * Create a SyncHttpClient by loading config from disk.
13
+ *
14
+ * Opens the personal database to use the SQLite-backed sequence counter,
15
+ * ensuring all code paths share the same counter and avoiding drift.
16
+ */
17
+ export declare function createSyncHttpClient(): Promise<{
18
+ client: SyncHttpClient;
19
+ config: SyncConfig;
20
+ }>;
21
+ //# sourceMappingURL=client-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-factory.d.ts","sourceRoot":"","sources":["../../sync/client-factory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,uBAAuB,GAChC,cAAc,CAGhB;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IACpD,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC,CAkBD"}
@@ -0,0 +1,36 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { SSHSigner } from './ssh-signer.js';
4
+ import { SyncHttpClient } from './http-client.js';
5
+ /**
6
+ * Create a SyncHttpClient from explicit config.
7
+ *
8
+ * Requires a DB-backed ISyncSequenceRepository to prevent
9
+ * sequence counter drift between SQLite and legacy flat files.
10
+ */
11
+ export function createSyncHttpClientFromConfig(config, sequence) {
12
+ const signer = new SSHSigner(config.sshKeyPath);
13
+ return new SyncHttpClient(config, signer, sequence);
14
+ }
15
+ /**
16
+ * Create a SyncHttpClient by loading config from disk.
17
+ *
18
+ * Opens the personal database to use the SQLite-backed sequence counter,
19
+ * ensuring all code paths share the same counter and avoiding drift.
20
+ */
21
+ export async function createSyncHttpClient() {
22
+ const { loadConfig } = await import('../cli/commands/setup.js');
23
+ const config = await loadConfig();
24
+ if (!config?.endpoint) {
25
+ throw new Error('Sync is not configured. Run `chaoskb-mcp setup-sync` first.');
26
+ }
27
+ const endpoint = config.endpoint;
28
+ const sshKeyPath = config.sshKeyPath ?? join(homedir(), '.ssh', 'id_ed25519');
29
+ const syncConfig = { endpoint, sshKeyPath };
30
+ const { DatabaseManager } = await import('../storage/database-manager.js');
31
+ const dbManager = new DatabaseManager();
32
+ const db = dbManager.getPersonalDb();
33
+ const client = createSyncHttpClientFromConfig(syncConfig, db.syncSequence);
34
+ return { client, config: syncConfig };
35
+ }
36
+ //# sourceMappingURL=client-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-factory.js","sourceRoot":"","sources":["../../sync/client-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;GAKG;AACH,MAAM,UAAU,8BAA8B,CAC5C,MAAkB,EAClB,QAAiC;IAEjC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChD,OAAO,IAAI,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IAIxC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAElC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACjC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAExD,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,IAAI,eAAe,EAAE,CAAC;IACxC,MAAM,EAAE,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC;IAErC,MAAM,MAAM,GAAG,8BAA8B,CAAC,UAAU,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC;IAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AACxC,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import type { ISyncHttpClient } from './types.js';
2
2
  import type { SyncConfig } from './types.js';
3
3
  import type { SSHSigner } from './ssh-signer.js';
4
- import { SequenceCounter } from './sequence.js';
4
+ import type { ISyncSequenceRepository } from '../storage/types.js';
5
5
  /** Error that indicates the request can be retried after a delay. */
6
6
  export declare class RetryableError extends Error {
7
7
  /** Seconds to wait before retrying */
@@ -18,7 +18,7 @@ export declare class SyncHttpClient implements ISyncHttpClient {
18
18
  private readonly baseUrl;
19
19
  private readonly signer;
20
20
  private readonly sequence;
21
- constructor(config: SyncConfig, signer: SSHSigner, sequence?: SequenceCounter);
21
+ constructor(config: SyncConfig, signer: SSHSigner, sequence: ISyncSequenceRepository);
22
22
  get(path: string): Promise<Response>;
23
23
  put(path: string, body: Uint8Array): Promise<Response>;
24
24
  delete(path: string): Promise<Response>;
@@ -1 +1 @@
1
- {"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../sync/http-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,qEAAqE;AACrE,qBAAa,cAAe,SAAQ,KAAK;IACvC,sCAAsC;IACtC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;CAKvD;AAKD;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;gBAE/B,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,eAAe;IAYvE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIpC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;IAItD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIvC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;YAIhD,OAAO;CAsDtB"}
1
+ {"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../sync/http-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE,qEAAqE;AACrE,qBAAa,cAAe,SAAQ,KAAK;IACvC,sCAAsC;IACtC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;CAKvD;AAKD;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;gBAEvC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,uBAAuB;IAY9E,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIpC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;IAItD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIvC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;YAIhD,OAAO;CAiEtB"}