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.
- package/dist/bin/backpack-sync.js +243 -65
- package/dist/bin/backpack-sync.js.map +1 -1
- package/dist/bin/backpack.js +7 -0
- package/dist/bin/backpack.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/sync/auto-sync.d.ts +10 -0
- package/dist/sync/auto-sync.d.ts.map +1 -0
- package/dist/sync/auto-sync.js +81 -0
- package/dist/sync/auto-sync.js.map +1 -0
- package/dist/sync/index.d.ts +10 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +7 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/sync-client.d.ts +80 -0
- package/dist/sync/sync-client.d.ts.map +1 -0
- package/dist/sync/sync-client.js +539 -0
- package/dist/sync/sync-client.js.map +1 -0
- package/dist/sync/sync-relay.d.ts +40 -0
- package/dist/sync/sync-relay.d.ts.map +1 -0
- package/dist/sync/sync-relay.js +118 -0
- package/dist/sync/sync-relay.js.map +1 -0
- package/dist/sync/sync-state.d.ts +7 -0
- package/dist/sync/sync-state.d.ts.map +1 -0
- package/dist/sync/sync-state.js +63 -0
- package/dist/sync/sync-state.js.map +1 -0
- package/dist/sync/types.d.ts +106 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +20 -0
- package/dist/sync/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -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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"}
|