backpack-ontology 0.7.7 → 0.7.8

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 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAepB,OAAO,EACL,aAAa,EACb,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { type BackpackSyncState, type SyncManifest, type SyncRunResult } from "./types.js";
2
+ import { SyncRelayClient } from "./sync-relay.js";
3
+ export interface SyncClientOptions {
4
+ /** Absolute path to the backpack on disk (where graphs/ + _documents/ live). */
5
+ backpackPath: string;
6
+ /** Relay client (constructed by caller, who handles auth). */
7
+ relay: SyncRelayClient;
8
+ /** Display name of the backpack (used at register time). */
9
+ name?: string;
10
+ /** Color (hex) of the backpack — derived from path by default. */
11
+ color?: string;
12
+ /** Tags to assign at register time. */
13
+ tags?: string[];
14
+ }
15
+ export interface RegisterOptions {
16
+ name: string;
17
+ color?: string;
18
+ tags?: string[];
19
+ /** Optional pre-existing UUID (for idempotent re-registration). */
20
+ backpackId?: string;
21
+ }
22
+ export declare class SyncClient {
23
+ private readonly backpackPath;
24
+ private readonly relay;
25
+ private graphsBackend;
26
+ private docStore;
27
+ private kbMounts;
28
+ constructor(opts: SyncClientOptions);
29
+ /** Read sync state from disk, or null if this backpack is not registered. */
30
+ getState(): Promise<BackpackSyncState | null>;
31
+ /**
32
+ * Register this backpack with the relay. Idempotent — if the backpack is
33
+ * already registered and the relay knows about it, returns existing state.
34
+ * If a backpack_id is provided (e.g. from a previous registration), reuses it.
35
+ */
36
+ register(opts: RegisterOptions): Promise<BackpackSyncState>;
37
+ /** Unregister: delete server-side and local sync state. */
38
+ unregister(): Promise<void>;
39
+ /**
40
+ * Compute a status diff without performing any writes. Useful for
41
+ * `backpack-sync status` and the viewer's pending-changes badge.
42
+ */
43
+ status(): Promise<{
44
+ registered: boolean;
45
+ state: BackpackSyncState | null;
46
+ localOnly: string[];
47
+ remoteOnly: string[];
48
+ diverged: string[];
49
+ upToDate: number;
50
+ }>;
51
+ /** Push every local artifact whose hash differs from its tracked synced hash. */
52
+ push(): Promise<SyncRunResult>;
53
+ /** Pull every remote artifact whose version is newer than the locally tracked one. */
54
+ pull(): Promise<SyncRunResult>;
55
+ /** Bidirectional: pull then push. */
56
+ sync(): Promise<SyncRunResult>;
57
+ private requireState;
58
+ private getRelayBaseUrl;
59
+ private getGraphsBackend;
60
+ private getKBStore;
61
+ private scanLocalArtifacts;
62
+ private writeLocalArtifact;
63
+ private deleteLocalArtifact;
64
+ private writeConflictFile;
65
+ private handleConflict;
66
+ }
67
+ /**
68
+ * Canonical hash: sorted-keys at every level of the JSON tree, no
69
+ * whitespace. Matches backpack-app's `repository.canonicalContentHash`
70
+ * so client-computed hashes survive a round-trip through PostgreSQL JSONB
71
+ * normalization.
72
+ */
73
+ export declare function hashContent(content: unknown): string;
74
+ export declare function parseArtifactId(id: string): {
75
+ kind: string;
76
+ key: string;
77
+ };
78
+ /** Manifest = SyncManifest, re-exported here for convenience. */
79
+ export type { SyncManifest };
80
+ //# sourceMappingURL=sync-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-client.d.ts","sourceRoot":"","sources":["../../src/sync/sync-client.ts"],"names":[],"mappings":"AA2BA,OAAO,EAKL,KAAK,iBAAiB,EAGtB,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAQpB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,KAAK,EAAE,eAAe,CAAC;IACvB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,QAAQ,CAAgC;gBAEpC,IAAI,EAAE,iBAAiB;IAOnC,6EAA6E;IACvE,QAAQ,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAInD;;;;OAIG;IACG,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA2BjE,2DAA2D;IACrD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC;QACtB,UAAU,EAAE,OAAO,CAAC;QACpB,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;QAChC,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IAuDF,iFAAiF;IAC3E,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC;IA4CpC,sFAAsF;IAChF,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC;IA2GpC,qCAAqC;IAC/B,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC;YAetB,YAAY;IAU1B,OAAO,CAAC,eAAe;YAYT,gBAAgB;YAQhB,UAAU;YAkBV,kBAAkB;YAsElB,kBAAkB;YA+BlB,mBAAmB;YAmBnB,iBAAiB;YAWjB,cAAc;CA0B7B;AAID;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAGpD;AA2BD,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAMzE;AAoBD,iEAAiE;AACjE,YAAY,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,539 @@
1
+ // SyncClient — orchestrates per-backpack bidirectional sync against a relay.
2
+ //
3
+ // Identity:
4
+ // - Each backpack has a stable UUID stored in <backpack>/.sync/state.json
5
+ // - Each artifact has id "graph:<name>" or "kb_doc:<id>"
6
+ //
7
+ // Algorithm (see backpack-ontology/docs/sync-protocol.md §5):
8
+ // pull-then-push: fetch manifest, reconcile each artifact in turn
9
+ // - local-only: push (expected_version=0)
10
+ // - remote-only (not tombstoned): pull, write locally
11
+ // - both, hashes equal: skip
12
+ // - both, local newer than synced ancestor: push
13
+ // - both, remote newer than synced ancestor: pull
14
+ // - both, diverged: write conflict file, take remote as canonical
15
+ import * as crypto from "node:crypto";
16
+ import * as fs from "node:fs/promises";
17
+ import * as path from "node:path";
18
+ import { randomUUID } from "node:crypto";
19
+ import { EventSourcedBackend } from "../storage/event-sourced-backend.js";
20
+ import { DocumentStore } from "../core/document-store.js";
21
+ import { getKBMounts } from "../core/backpacks-registry.js";
22
+ import { ARTIFACT_KIND_GRAPH, ARTIFACT_KIND_KB_DOC, SyncVersionConflictError, } from "./types.js";
23
+ import { emptyArtifactState, isStateInitialized, readSyncState, writeSyncState, deleteSyncState, } from "./sync-state.js";
24
+ export class SyncClient {
25
+ backpackPath;
26
+ relay;
27
+ graphsBackend = null;
28
+ docStore = null;
29
+ kbMounts = null;
30
+ constructor(opts) {
31
+ this.backpackPath = opts.backpackPath;
32
+ this.relay = opts.relay;
33
+ }
34
+ // --- Lifecycle ---
35
+ /** Read sync state from disk, or null if this backpack is not registered. */
36
+ async getState() {
37
+ return readSyncState(this.backpackPath);
38
+ }
39
+ /**
40
+ * Register this backpack with the relay. Idempotent — if the backpack is
41
+ * already registered and the relay knows about it, returns existing state.
42
+ * If a backpack_id is provided (e.g. from a previous registration), reuses it.
43
+ */
44
+ async register(opts) {
45
+ const existing = await this.getState();
46
+ const backpackId = opts.backpackId ?? existing?.backpack_id ?? randomUUID();
47
+ const remote = await this.relay.register({
48
+ id: backpackId,
49
+ name: opts.name,
50
+ color: opts.color,
51
+ tags: opts.tags ?? [],
52
+ });
53
+ const state = existing
54
+ ? { ...existing, backpack_id: remote.id, name: remote.name }
55
+ : {
56
+ backpack_id: remote.id,
57
+ name: remote.name,
58
+ relay_url: this.getRelayBaseUrl(),
59
+ registered_at: new Date().toISOString(),
60
+ last_sync_at: null,
61
+ last_synced_metadata_version: 0,
62
+ artifacts: {},
63
+ };
64
+ state.last_synced_metadata_version = remote.metadata_version;
65
+ await writeSyncState(this.backpackPath, state);
66
+ return state;
67
+ }
68
+ /** Unregister: delete server-side and local sync state. */
69
+ async unregister() {
70
+ const state = await this.getState();
71
+ if (!state)
72
+ return;
73
+ try {
74
+ await this.relay.deleteBackpack(state.backpack_id);
75
+ }
76
+ catch {
77
+ // Even if remote delete fails, drop local state
78
+ }
79
+ await deleteSyncState(this.backpackPath);
80
+ }
81
+ // --- Status ---
82
+ /**
83
+ * Compute a status diff without performing any writes. Useful for
84
+ * `backpack-sync status` and the viewer's pending-changes badge.
85
+ */
86
+ async status() {
87
+ const state = await this.getState();
88
+ if (!isStateInitialized(state)) {
89
+ return { registered: false, state: null, localOnly: [], remoteOnly: [], diverged: [], upToDate: 0 };
90
+ }
91
+ const local = await this.scanLocalArtifacts();
92
+ const manifest = await this.relay.manifest(state.backpack_id);
93
+ const localById = new Map(local.map((a) => [a.id, a]));
94
+ const remoteById = new Map();
95
+ for (const a of manifest.artifacts ?? []) {
96
+ remoteById.set(a.artifact_id, {
97
+ version: a.version,
98
+ hash: a.content_hash,
99
+ deleted: !!a.deleted,
100
+ });
101
+ }
102
+ const localOnly = [];
103
+ const remoteOnly = [];
104
+ const diverged = [];
105
+ let upToDate = 0;
106
+ const allIds = new Set([...localById.keys(), ...remoteById.keys()]);
107
+ for (const id of allIds) {
108
+ const l = localById.get(id);
109
+ const r = remoteById.get(id);
110
+ const trackedHash = state.artifacts[id]?.content_hash ?? "";
111
+ if (l && !r) {
112
+ localOnly.push(id);
113
+ }
114
+ else if (r && !l) {
115
+ if (!r.deleted)
116
+ remoteOnly.push(id);
117
+ }
118
+ else if (l && r) {
119
+ if (r.deleted) {
120
+ // Remote tombstoned but we still have it: pull will delete locally
121
+ remoteOnly.push(id);
122
+ }
123
+ else if (l.hash === r.hash) {
124
+ upToDate++;
125
+ }
126
+ else if (trackedHash === r.hash) {
127
+ // local advanced
128
+ localOnly.push(id);
129
+ }
130
+ else if (trackedHash === l.hash) {
131
+ // remote advanced
132
+ remoteOnly.push(id);
133
+ }
134
+ else {
135
+ diverged.push(id);
136
+ }
137
+ }
138
+ }
139
+ return { registered: true, state, localOnly, remoteOnly, diverged, upToDate };
140
+ }
141
+ // --- Operations ---
142
+ /** Push every local artifact whose hash differs from its tracked synced hash. */
143
+ async push() {
144
+ const state = await this.requireState();
145
+ const result = newResult();
146
+ const local = await this.scanLocalArtifacts();
147
+ let mutated = false;
148
+ for (const art of local) {
149
+ const tracked = state.artifacts[art.id] ?? emptyArtifactState();
150
+ if (tracked.content_hash === art.hash)
151
+ continue;
152
+ try {
153
+ const expectedVersion = tracked.last_synced_version;
154
+ const remote = await this.relay.putArtifact(state.backpack_id, art.id, art.content, expectedVersion);
155
+ state.artifacts[art.id] = {
156
+ version: remote.version,
157
+ content_hash: remote.content_hash,
158
+ last_synced_version: remote.version,
159
+ modified_at: remote.modified_at,
160
+ };
161
+ result.pushed.push(art.id);
162
+ mutated = true;
163
+ }
164
+ catch (err) {
165
+ if (err instanceof SyncVersionConflictError) {
166
+ // Pull-and-conflict path
167
+ await this.handleConflict(state, art.id, art.content, err, result);
168
+ mutated = true;
169
+ }
170
+ else {
171
+ result.errors.push({ artifact_id: art.id, message: err.message });
172
+ }
173
+ }
174
+ }
175
+ if (mutated) {
176
+ state.last_sync_at = new Date().toISOString();
177
+ await writeSyncState(this.backpackPath, state);
178
+ }
179
+ return result;
180
+ }
181
+ /** Pull every remote artifact whose version is newer than the locally tracked one. */
182
+ async pull() {
183
+ const state = await this.requireState();
184
+ const result = newResult();
185
+ const manifest = await this.relay.manifest(state.backpack_id);
186
+ let mutated = false;
187
+ const localArtifacts = await this.scanLocalArtifacts();
188
+ const localById = new Map(localArtifacts.map((a) => [a.id, a]));
189
+ for (const remote of manifest.artifacts ?? []) {
190
+ const tracked = state.artifacts[remote.artifact_id] ?? emptyArtifactState();
191
+ const local = localById.get(remote.artifact_id);
192
+ if (remote.deleted) {
193
+ if (local) {
194
+ await this.deleteLocalArtifact(remote.artifact_id);
195
+ result.deleted_local.push(remote.artifact_id);
196
+ }
197
+ delete state.artifacts[remote.artifact_id];
198
+ mutated = true;
199
+ continue;
200
+ }
201
+ if (local && local.hash === remote.content_hash) {
202
+ if (tracked.last_synced_version !== remote.version) {
203
+ state.artifacts[remote.artifact_id] = {
204
+ version: remote.version,
205
+ content_hash: remote.content_hash,
206
+ last_synced_version: remote.version,
207
+ modified_at: remote.modified_at,
208
+ };
209
+ mutated = true;
210
+ }
211
+ continue;
212
+ }
213
+ const localChanged = local && tracked.content_hash !== "" && local.hash !== tracked.content_hash;
214
+ // Remote newer than tracked AND local has not changed → pull
215
+ if (remote.version > tracked.last_synced_version && !localChanged) {
216
+ const fetched = await this.relay.getArtifact(state.backpack_id, remote.artifact_id);
217
+ await this.writeLocalArtifact(remote.artifact_id, fetched.content);
218
+ state.artifacts[remote.artifact_id] = {
219
+ version: remote.version,
220
+ content_hash: remote.content_hash,
221
+ last_synced_version: remote.version,
222
+ modified_at: remote.modified_at,
223
+ };
224
+ result.pulled.push(remote.artifact_id);
225
+ mutated = true;
226
+ continue;
227
+ }
228
+ // Local changed AND remote also changed → conflict.
229
+ // Write the LOCAL content as a conflict file FIRST so that even if the
230
+ // subsequent local overwrite fails (disk full, perms, crash), the
231
+ // user's local edits are preserved on disk.
232
+ if (localChanged && remote.version > tracked.last_synced_version) {
233
+ const conflictPath = await this.writeConflictFile(remote.artifact_id, local.content);
234
+ const fetched = await this.relay.getArtifact(state.backpack_id, remote.artifact_id);
235
+ await this.writeLocalArtifact(remote.artifact_id, fetched.content);
236
+ state.artifacts[remote.artifact_id] = {
237
+ version: remote.version,
238
+ content_hash: remote.content_hash,
239
+ last_synced_version: remote.version,
240
+ modified_at: remote.modified_at,
241
+ };
242
+ result.conflicts.push({
243
+ artifact_id: remote.artifact_id,
244
+ conflict_path: conflictPath,
245
+ remote_version: remote.version,
246
+ });
247
+ mutated = true;
248
+ }
249
+ }
250
+ // Detect locally-deleted artifacts (in tracked state but not on disk
251
+ // AND not just pulled from the relay this run). Re-scan local because
252
+ // the loop above wrote new files that the initial scan missed.
253
+ const justPulled = new Set([...result.pulled, ...result.conflicts.map((c) => c.artifact_id)]);
254
+ const localAfterPull = await this.scanLocalArtifacts();
255
+ const localByIdAfter = new Map(localAfterPull.map((a) => [a.id, a]));
256
+ for (const [id, tracked] of Object.entries(state.artifacts)) {
257
+ if (justPulled.has(id))
258
+ continue;
259
+ if (localByIdAfter.has(id))
260
+ continue;
261
+ if (tracked.last_synced_version <= 0 || tracked.content_hash === "")
262
+ continue;
263
+ const remoteEntry = (manifest.artifacts ?? []).find((a) => a.artifact_id === id);
264
+ if (remoteEntry?.deleted)
265
+ continue;
266
+ try {
267
+ await this.relay.deleteArtifact(state.backpack_id, id);
268
+ delete state.artifacts[id];
269
+ result.deleted_remote.push(id);
270
+ mutated = true;
271
+ }
272
+ catch (err) {
273
+ result.errors.push({ artifact_id: id, message: err.message });
274
+ }
275
+ }
276
+ if (mutated) {
277
+ state.last_sync_at = new Date().toISOString();
278
+ state.last_synced_metadata_version = manifest.metadata_version;
279
+ await writeSyncState(this.backpackPath, state);
280
+ }
281
+ return result;
282
+ }
283
+ /** Bidirectional: pull then push. */
284
+ async sync() {
285
+ const a = await this.pull();
286
+ const b = await this.push();
287
+ return {
288
+ pushed: [...a.pushed, ...b.pushed],
289
+ pulled: [...a.pulled, ...b.pulled],
290
+ deleted_local: [...a.deleted_local, ...b.deleted_local],
291
+ deleted_remote: [...a.deleted_remote, ...b.deleted_remote],
292
+ conflicts: [...a.conflicts, ...b.conflicts],
293
+ errors: [...a.errors, ...b.errors],
294
+ };
295
+ }
296
+ // --- Internal helpers ---
297
+ async requireState() {
298
+ const state = await this.getState();
299
+ if (!isStateInitialized(state)) {
300
+ throw new Error("backpack is not registered for sync; run `backpack-sync register <name>` first");
301
+ }
302
+ return state;
303
+ }
304
+ getRelayBaseUrl() {
305
+ // SyncRelayClient hides this — recover via `(this.relay as any).baseUrl` is
306
+ // tempting but we'd rather keep a copy at register time. Callers pass the
307
+ // intended relay url in the constructor; we store it in the state file then.
308
+ // For now, read from env or default.
309
+ return (process.env.BACKPACK_APP_URL ??
310
+ process.env.BACKPACK_RELAY_URL ??
311
+ "https://app.backpackontology.com");
312
+ }
313
+ async getGraphsBackend() {
314
+ if (!this.graphsBackend) {
315
+ this.graphsBackend = new EventSourcedBackend(this.backpackPath);
316
+ await this.graphsBackend.initialize();
317
+ }
318
+ return this.graphsBackend;
319
+ }
320
+ async getKBStore() {
321
+ if (!this.docStore || !this.kbMounts) {
322
+ try {
323
+ this.kbMounts = await getKBMounts(this.backpackPath);
324
+ }
325
+ catch {
326
+ this.kbMounts = [];
327
+ }
328
+ this.docStore = new DocumentStore(this.kbMounts.map((m) => ({
329
+ name: m.name,
330
+ path: m.path,
331
+ writable: m.writable !== false,
332
+ })));
333
+ }
334
+ return { store: this.docStore, mounts: this.kbMounts };
335
+ }
336
+ async scanLocalArtifacts() {
337
+ const out = [];
338
+ // Graphs
339
+ const backend = await this.getGraphsBackend();
340
+ const graphs = await backend.listOntologies();
341
+ for (const g of graphs) {
342
+ try {
343
+ const data = await backend.loadOntology(g.name);
344
+ const content = {
345
+ kind: ARTIFACT_KIND_GRAPH,
346
+ name: g.name,
347
+ data,
348
+ };
349
+ out.push({
350
+ id: `${ARTIFACT_KIND_GRAPH}:${g.name}`,
351
+ hash: hashContent(content),
352
+ content,
353
+ });
354
+ }
355
+ catch (err) {
356
+ // Skip unreadable graphs
357
+ process.stderr.write(`sync: skipping graph "${g.name}" — ${err.message}\n`);
358
+ }
359
+ }
360
+ // KB documents from synced mounts
361
+ try {
362
+ const { store, mounts } = await this.getKBStore();
363
+ const syncedMountNames = new Set(mounts.filter((m) => isMountSynced(m)).map((m) => m.name));
364
+ const result = await store.list();
365
+ for (const summary of result.documents) {
366
+ if (syncedMountNames.size > 0 && !syncedMountNames.has(summary.collection))
367
+ continue;
368
+ try {
369
+ const doc = await store.read(summary.id);
370
+ const content = {
371
+ kind: ARTIFACT_KIND_KB_DOC,
372
+ id: doc.id,
373
+ title: doc.title,
374
+ content: doc.content,
375
+ tags: doc.tags ?? [],
376
+ source_graphs: doc.sourceGraphs ?? [],
377
+ source_node_ids: doc.sourceNodeIds ?? [],
378
+ collection: doc.collection,
379
+ created_at: doc.createdAt,
380
+ updated_at: doc.updatedAt,
381
+ };
382
+ out.push({
383
+ id: `${ARTIFACT_KIND_KB_DOC}:${doc.id}`,
384
+ hash: hashContent(content),
385
+ content,
386
+ });
387
+ }
388
+ catch (err) {
389
+ process.stderr.write(`sync: skipping KB doc "${summary.id}" — ${err.message}\n`);
390
+ }
391
+ }
392
+ }
393
+ catch {
394
+ // KB not configured — skip
395
+ }
396
+ return out;
397
+ }
398
+ async writeLocalArtifact(artifactId, content) {
399
+ const { kind, key } = parseArtifactId(artifactId);
400
+ if (kind === ARTIFACT_KIND_GRAPH) {
401
+ const c = content;
402
+ const data = c.data;
403
+ const backend = await this.getGraphsBackend();
404
+ const existing = await backend.listOntologies();
405
+ if (!existing.find((o) => o.name === key)) {
406
+ await backend.createOntology(key, data.metadata?.description ?? "");
407
+ }
408
+ await backend.saveOntology(key, data);
409
+ }
410
+ else if (kind === ARTIFACT_KIND_KB_DOC) {
411
+ const c = content;
412
+ const { store } = await this.getKBStore();
413
+ const doc = {
414
+ id: c.id,
415
+ title: c.title,
416
+ content: c.content,
417
+ tags: c.tags ?? [],
418
+ sourceGraphs: c.source_graphs ?? [],
419
+ sourceNodeIds: c.source_node_ids ?? [],
420
+ collection: c.collection,
421
+ createdAt: c.created_at,
422
+ updatedAt: c.updated_at,
423
+ };
424
+ await store.save(doc);
425
+ }
426
+ else {
427
+ throw new Error(`unsupported artifact kind: ${kind}`);
428
+ }
429
+ }
430
+ async deleteLocalArtifact(artifactId) {
431
+ const { kind, key } = parseArtifactId(artifactId);
432
+ if (kind === ARTIFACT_KIND_GRAPH) {
433
+ const backend = await this.getGraphsBackend();
434
+ try {
435
+ await backend.deleteOntology(key);
436
+ }
437
+ catch {
438
+ // ignore
439
+ }
440
+ }
441
+ else if (kind === ARTIFACT_KIND_KB_DOC) {
442
+ const { store } = await this.getKBStore();
443
+ try {
444
+ await store.delete(key);
445
+ }
446
+ catch {
447
+ // ignore
448
+ }
449
+ }
450
+ }
451
+ async writeConflictFile(artifactId, content) {
452
+ const { kind, key } = parseArtifactId(artifactId);
453
+ const safeKey = key.replace(/[^a-zA-Z0-9._-]/g, "_");
454
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
455
+ const dir = path.join(this.backpackPath, ".sync", "conflicts");
456
+ await fs.mkdir(dir, { recursive: true });
457
+ const file = path.join(dir, `${kind}_${safeKey}.conflict-${ts}.json`);
458
+ await fs.writeFile(file, JSON.stringify(content, null, 2), "utf8");
459
+ return file;
460
+ }
461
+ async handleConflict(state, artifactId, localContent, err, result) {
462
+ // Server has a newer version. Save our local content as a conflict file
463
+ // FIRST (so it survives any failure in the subsequent overwrite), then
464
+ // pull the server version and update tracked state. Per spec §8.2:
465
+ // relay wins canonical, local preserved as a conflict file for manual reconciliation.
466
+ const conflictPath = await this.writeConflictFile(artifactId, localContent);
467
+ const fetched = await this.relay.getArtifact(state.backpack_id, artifactId);
468
+ await this.writeLocalArtifact(artifactId, fetched.content);
469
+ state.artifacts[artifactId] = {
470
+ version: fetched.version,
471
+ content_hash: fetched.content_hash,
472
+ last_synced_version: fetched.version,
473
+ modified_at: fetched.modified_at,
474
+ };
475
+ result.conflicts.push({
476
+ artifact_id: artifactId,
477
+ conflict_path: conflictPath,
478
+ remote_version: err.serverVersion,
479
+ });
480
+ }
481
+ }
482
+ // --- helpers ---
483
+ /**
484
+ * Canonical hash: sorted-keys at every level of the JSON tree, no
485
+ * whitespace. Matches backpack-app's `repository.canonicalContentHash`
486
+ * so client-computed hashes survive a round-trip through PostgreSQL JSONB
487
+ * normalization.
488
+ */
489
+ export function hashContent(content) {
490
+ const canonical = canonicalStringify(content);
491
+ return "sha256:" + crypto.createHash("sha256").update(canonical).digest("hex");
492
+ }
493
+ function canonicalStringify(v) {
494
+ // JSON has no representation for undefined; coerce to null so the hash
495
+ // stays a valid JSON string and survives a roundtrip through the wire.
496
+ if (v === undefined)
497
+ return "null";
498
+ if (v === null || typeof v !== "object")
499
+ return JSON.stringify(v);
500
+ if (Array.isArray(v)) {
501
+ return ("[" +
502
+ v.map((x) => canonicalStringify(x === undefined ? null : x)).join(",") +
503
+ "]");
504
+ }
505
+ const obj = v;
506
+ const keys = Object.keys(obj)
507
+ .filter((k) => obj[k] !== undefined)
508
+ .sort();
509
+ return ("{" +
510
+ keys
511
+ .map((k) => JSON.stringify(k) + ":" + canonicalStringify(obj[k]))
512
+ .join(",") +
513
+ "}");
514
+ }
515
+ export function parseArtifactId(id) {
516
+ const idx = id.indexOf(":");
517
+ if (idx <= 0 || idx === id.length - 1) {
518
+ throw new Error(`invalid artifact_id: ${id}`);
519
+ }
520
+ return { kind: id.slice(0, idx), key: id.slice(idx + 1) };
521
+ }
522
+ function isMountSynced(mount) {
523
+ // Default sync = true for writable mounts. External mounts can opt out by
524
+ // setting sync: false in backpacks.json.
525
+ if (mount.sync === false)
526
+ return false;
527
+ return mount.writable !== false;
528
+ }
529
+ function newResult() {
530
+ return {
531
+ pushed: [],
532
+ pulled: [],
533
+ deleted_local: [],
534
+ deleted_remote: [],
535
+ conflicts: [],
536
+ errors: [],
537
+ };
538
+ }
539
+ //# sourceMappingURL=sync-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-client.js","sourceRoot":"","sources":["../../src/sync/sync-client.ts"],"names":[],"mappings":"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"}