backpack-ontology 0.2.25 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +153 -3
- package/dist/bin/backpack-benchmark.d.ts +3 -0
- package/dist/bin/backpack-benchmark.d.ts.map +1 -0
- package/dist/bin/backpack-benchmark.js +213 -0
- package/dist/bin/backpack-benchmark.js.map +1 -0
- package/dist/bin/backpack.js +3 -3
- package/dist/bin/backpack.js.map +1 -1
- package/dist/bin/init.js +8 -11
- package/dist/bin/init.js.map +1 -1
- package/dist/core/backpack.d.ts +69 -2
- package/dist/core/backpack.d.ts.map +1 -1
- package/dist/core/backpack.js +205 -3
- package/dist/core/backpack.js.map +1 -1
- package/dist/core/draft.d.ts +42 -0
- package/dist/core/draft.d.ts.map +1 -0
- package/dist/core/draft.js +232 -0
- package/dist/core/draft.js.map +1 -0
- package/dist/core/events.d.ts +114 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +375 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/graph.d.ts +3 -1
- package/dist/core/graph.d.ts.map +1 -1
- package/dist/core/graph.js +50 -0
- package/dist/core/graph.js.map +1 -1
- package/dist/core/hooks.d.ts +11 -3
- package/dist/core/hooks.d.ts.map +1 -1
- package/dist/core/hooks.js +53 -47
- package/dist/core/hooks.js.map +1 -1
- package/dist/core/normalize.d.ts +28 -0
- package/dist/core/normalize.d.ts.map +1 -0
- package/dist/core/normalize.js +133 -0
- package/dist/core/normalize.js.map +1 -0
- package/dist/core/remote-fetch.d.ts +50 -0
- package/dist/core/remote-fetch.d.ts.map +1 -0
- package/dist/core/remote-fetch.js +338 -0
- package/dist/core/remote-fetch.js.map +1 -0
- package/dist/core/remote-registry.d.ts +95 -0
- package/dist/core/remote-registry.d.ts.map +1 -0
- package/dist/core/remote-registry.js +296 -0
- package/dist/core/remote-registry.js.map +1 -0
- package/dist/core/remote-schema.d.ts +31 -0
- package/dist/core/remote-schema.d.ts.map +1 -0
- package/dist/core/remote-schema.js +252 -0
- package/dist/core/remote-schema.js.map +1 -0
- package/dist/core/role-audit.d.ts +20 -0
- package/dist/core/role-audit.d.ts.map +1 -0
- package/dist/core/role-audit.js +197 -0
- package/dist/core/role-audit.js.map +1 -0
- package/dist/core/telemetry.d.ts +2 -0
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js +16 -0
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/token-estimate.d.ts +16 -0
- package/dist/core/token-estimate.d.ts.map +1 -0
- package/dist/core/token-estimate.js +29 -0
- package/dist/core/token-estimate.js.map +1 -0
- package/dist/core/types.d.ts +30 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +9 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/bulk-tools.d.ts.map +1 -1
- package/dist/mcp/tools/bulk-tools.js +80 -12
- package/dist/mcp/tools/bulk-tools.js.map +1 -1
- package/dist/mcp/tools/edge-tools.d.ts.map +1 -1
- package/dist/mcp/tools/edge-tools.js +14 -18
- package/dist/mcp/tools/edge-tools.js.map +1 -1
- package/dist/mcp/tools/error-helpers.d.ts +16 -0
- package/dist/mcp/tools/error-helpers.d.ts.map +1 -0
- package/dist/mcp/tools/error-helpers.js +34 -0
- package/dist/mcp/tools/error-helpers.js.map +1 -0
- package/dist/mcp/tools/intelligence-tools.d.ts.map +1 -1
- package/dist/mcp/tools/intelligence-tools.js +28 -18
- package/dist/mcp/tools/intelligence-tools.js.map +1 -1
- package/dist/mcp/tools/node-tools.d.ts.map +1 -1
- package/dist/mcp/tools/node-tools.js +43 -40
- package/dist/mcp/tools/node-tools.js.map +1 -1
- package/dist/mcp/tools/ontology-tools.d.ts.map +1 -1
- package/dist/mcp/tools/ontology-tools.js +237 -12
- package/dist/mcp/tools/ontology-tools.js.map +1 -1
- package/dist/mcp/tools/remote-tools.d.ts +5 -0
- package/dist/mcp/tools/remote-tools.d.ts.map +1 -0
- package/dist/mcp/tools/remote-tools.js +295 -0
- package/dist/mcp/tools/remote-tools.js.map +1 -0
- package/dist/storage/backpack-app-backend.d.ts +1 -1
- package/dist/storage/backpack-app-backend.d.ts.map +1 -1
- package/dist/storage/backpack-app-backend.js +3 -1
- package/dist/storage/backpack-app-backend.js.map +1 -1
- package/dist/storage/event-sourced-backend.d.ts +174 -0
- package/dist/storage/event-sourced-backend.d.ts.map +1 -0
- package/dist/storage/event-sourced-backend.js +840 -0
- package/dist/storage/event-sourced-backend.js.map +1 -0
- package/dist/storage/json-file-backend.d.ts +1 -72
- package/dist/storage/json-file-backend.d.ts.map +1 -1
- package/dist/storage/json-file-backend.js +11 -549
- package/dist/storage/json-file-backend.js.map +1 -1
- package/package.json +3 -3
- package/hooks/auto-capture-prompt.md +0 -40
- package/hooks/hooks.json +0 -16
- package/hooks/suggest-viewer.sh +0 -4
|
@@ -1,550 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export class JsonFileBackend {
|
|
13
|
-
baseDir;
|
|
14
|
-
constructor(baseDir) {
|
|
15
|
-
this.baseDir = baseDir ?? dataDir();
|
|
16
|
-
}
|
|
17
|
-
// --- Path helpers ---
|
|
18
|
-
graphsDir() {
|
|
19
|
-
return path.join(this.baseDir, "graphs");
|
|
20
|
-
}
|
|
21
|
-
graphDir(name) {
|
|
22
|
-
return path.join(this.graphsDir(), name);
|
|
23
|
-
}
|
|
24
|
-
metaFile(name) {
|
|
25
|
-
return path.join(this.graphDir(name), "meta.json");
|
|
26
|
-
}
|
|
27
|
-
branchesDir(name) {
|
|
28
|
-
return path.join(this.graphDir(name), "branches");
|
|
29
|
-
}
|
|
30
|
-
branchFile(name, branch) {
|
|
31
|
-
return path.join(this.branchesDir(name), `${branch}.json`);
|
|
32
|
-
}
|
|
33
|
-
snapshotsDir(name, branch) {
|
|
34
|
-
return path.join(this.graphDir(name), "snapshots", branch);
|
|
35
|
-
}
|
|
36
|
-
snapshotFile(name, branch, version) {
|
|
37
|
-
const padded = String(version).padStart(3, "0");
|
|
38
|
-
return path.join(this.snapshotsDir(name, branch), `${padded}.json`);
|
|
39
|
-
}
|
|
40
|
-
termsFile(name) {
|
|
41
|
-
return path.join(this.graphDir(name), "terms.json");
|
|
42
|
-
}
|
|
43
|
-
snippetsDir(name) {
|
|
44
|
-
return path.join(this.graphDir(name), "snippets");
|
|
45
|
-
}
|
|
46
|
-
snippetFile(name, snippetId) {
|
|
47
|
-
return path.join(this.snippetsDir(name), `${snippetId}.json`);
|
|
48
|
-
}
|
|
49
|
-
// --- Meta helpers ---
|
|
50
|
-
async loadMeta(name) {
|
|
51
|
-
try {
|
|
52
|
-
const raw = await fs.readFile(this.metaFile(name), "utf-8");
|
|
53
|
-
return JSON.parse(raw);
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
return { ...DEFAULT_META };
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
async saveMeta(name, meta) {
|
|
60
|
-
const filePath = this.metaFile(name);
|
|
61
|
-
const tmpPath = filePath + ".tmp";
|
|
62
|
-
await fs.writeFile(tmpPath, JSON.stringify(meta, null, 2), "utf-8");
|
|
63
|
-
await fs.rename(tmpPath, filePath);
|
|
64
|
-
}
|
|
65
|
-
// --- Migration ---
|
|
66
|
-
async migrate() {
|
|
67
|
-
const oldDir = path.join(this.baseDir, "ontologies");
|
|
68
|
-
const newDir = this.graphsDir();
|
|
69
|
-
let oldExists = false;
|
|
70
|
-
try {
|
|
71
|
-
await fs.access(oldDir);
|
|
72
|
-
oldExists = true;
|
|
73
|
-
}
|
|
74
|
-
catch { }
|
|
75
|
-
let newExists = false;
|
|
76
|
-
try {
|
|
77
|
-
await fs.access(newDir);
|
|
78
|
-
newExists = true;
|
|
79
|
-
}
|
|
80
|
-
catch { }
|
|
81
|
-
if (!oldExists || newExists)
|
|
82
|
-
return;
|
|
83
|
-
console.error("[backpack] migrating ontologies/ → graphs/");
|
|
84
|
-
let entries;
|
|
85
|
-
try {
|
|
86
|
-
entries = await fs.readdir(oldDir);
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
for (const entry of entries) {
|
|
92
|
-
const oldOntologyFile = path.join(oldDir, entry, "ontology.json");
|
|
93
|
-
try {
|
|
94
|
-
await fs.access(oldOntologyFile);
|
|
95
|
-
}
|
|
96
|
-
catch {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
const graphDir = path.join(newDir, entry);
|
|
100
|
-
const branchesDir = path.join(graphDir, "branches");
|
|
101
|
-
await fs.mkdir(branchesDir, { recursive: true });
|
|
102
|
-
// Copy ontology.json → branches/main.json
|
|
103
|
-
const raw = await fs.readFile(oldOntologyFile, "utf-8");
|
|
104
|
-
const branchFile = path.join(branchesDir, "main.json");
|
|
105
|
-
const tmpBranch = branchFile + ".tmp";
|
|
106
|
-
await fs.writeFile(tmpBranch, raw, "utf-8");
|
|
107
|
-
await fs.rename(tmpBranch, branchFile);
|
|
108
|
-
// Create meta.json
|
|
109
|
-
const metaFile = path.join(graphDir, "meta.json");
|
|
110
|
-
const tmpMeta = metaFile + ".tmp";
|
|
111
|
-
await fs.writeFile(tmpMeta, JSON.stringify(DEFAULT_META, null, 2), "utf-8");
|
|
112
|
-
await fs.rename(tmpMeta, metaFile);
|
|
113
|
-
// Copy terms.json if exists
|
|
114
|
-
const oldTermsFile = path.join(oldDir, entry, "terms.json");
|
|
115
|
-
try {
|
|
116
|
-
const termsRaw = await fs.readFile(oldTermsFile, "utf-8");
|
|
117
|
-
const newTermsFile = path.join(graphDir, "terms.json");
|
|
118
|
-
const tmpTerms = newTermsFile + ".tmp";
|
|
119
|
-
await fs.writeFile(tmpTerms, termsRaw, "utf-8");
|
|
120
|
-
await fs.rename(tmpTerms, newTermsFile);
|
|
121
|
-
}
|
|
122
|
-
catch { }
|
|
123
|
-
console.error(`[backpack] migrated: ${entry}`);
|
|
124
|
-
}
|
|
125
|
-
await fs.rm(oldDir, { recursive: true });
|
|
126
|
-
console.error("[backpack] migration complete");
|
|
127
|
-
}
|
|
128
|
-
// --- StorageBackend methods ---
|
|
129
|
-
async initialize() {
|
|
130
|
-
await this.migrate();
|
|
131
|
-
await fs.mkdir(this.graphsDir(), { recursive: true });
|
|
132
|
-
}
|
|
133
|
-
async listOntologies() {
|
|
134
|
-
const dir = this.graphsDir();
|
|
135
|
-
let entries;
|
|
136
|
-
try {
|
|
137
|
-
entries = await fs.readdir(dir);
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
return [];
|
|
141
|
-
}
|
|
142
|
-
const summaries = [];
|
|
143
|
-
for (const entry of entries) {
|
|
144
|
-
try {
|
|
145
|
-
const meta = await this.loadMeta(entry);
|
|
146
|
-
const filePath = this.branchFile(entry, meta.activeBranch);
|
|
147
|
-
const raw = await fs.readFile(filePath, "utf-8");
|
|
148
|
-
const data = JSON.parse(raw);
|
|
149
|
-
const typeCounts = new Map();
|
|
150
|
-
for (const node of data.nodes) {
|
|
151
|
-
typeCounts.set(node.type, (typeCounts.get(node.type) ?? 0) + 1);
|
|
152
|
-
}
|
|
153
|
-
summaries.push({
|
|
154
|
-
name: data.metadata.name,
|
|
155
|
-
description: data.metadata.description,
|
|
156
|
-
nodeCount: data.nodes.length,
|
|
157
|
-
edgeCount: data.edges.length,
|
|
158
|
-
nodeTypes: Array.from(typeCounts.entries()).map(([type, count]) => ({
|
|
159
|
-
type,
|
|
160
|
-
count,
|
|
161
|
-
})),
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
// Skip directories that don't have valid data
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return summaries;
|
|
169
|
-
}
|
|
170
|
-
async loadOntology(name) {
|
|
171
|
-
const meta = await this.loadMeta(name);
|
|
172
|
-
const filePath = this.branchFile(name, meta.activeBranch);
|
|
173
|
-
try {
|
|
174
|
-
const raw = await fs.readFile(filePath, "utf-8");
|
|
175
|
-
return JSON.parse(raw);
|
|
176
|
-
}
|
|
177
|
-
catch {
|
|
178
|
-
throw new Error(`Ontology not found: ${name}`);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
async saveOntology(name, data) {
|
|
182
|
-
const meta = await this.loadMeta(name);
|
|
183
|
-
const filePath = this.branchFile(name, meta.activeBranch);
|
|
184
|
-
const tmpPath = filePath + ".tmp";
|
|
185
|
-
const json = JSON.stringify(data, null, 2);
|
|
186
|
-
await fs.writeFile(tmpPath, json, "utf-8");
|
|
187
|
-
await fs.rename(tmpPath, filePath);
|
|
188
|
-
this.writeTerms(name, data).catch(() => { });
|
|
189
|
-
}
|
|
190
|
-
async writeTerms(name, data) {
|
|
191
|
-
if (data.nodes.length === 0)
|
|
192
|
-
return;
|
|
193
|
-
const typeCounts = new Map();
|
|
194
|
-
const edgeTypeCounts = new Map();
|
|
195
|
-
const entities = [];
|
|
196
|
-
const seenNames = new Set();
|
|
197
|
-
for (const node of data.nodes) {
|
|
198
|
-
typeCounts.set(node.type, (typeCounts.get(node.type) ?? 0) + 1);
|
|
199
|
-
const label = firstStringValue(node.properties);
|
|
200
|
-
if (label && !seenNames.has(label)) {
|
|
201
|
-
seenNames.add(label);
|
|
202
|
-
entities.push({ name: label, type: node.type });
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
for (const edge of data.edges) {
|
|
206
|
-
edgeTypeCounts.set(edge.type, (edgeTypeCounts.get(edge.type) ?? 0) + 1);
|
|
207
|
-
}
|
|
208
|
-
const terms = {
|
|
209
|
-
types: [...typeCounts.entries()]
|
|
210
|
-
.sort((a, b) => a[0].localeCompare(b[0]))
|
|
211
|
-
.map(([name, count]) => ({ name, count })),
|
|
212
|
-
edgeTypes: [...edgeTypeCounts.entries()]
|
|
213
|
-
.sort((a, b) => a[0].localeCompare(b[0]))
|
|
214
|
-
.map(([name, count]) => ({ name, count })),
|
|
215
|
-
entities: entities
|
|
216
|
-
.sort((a, b) => a.type.localeCompare(b.type) || a.name.localeCompare(b.name))
|
|
217
|
-
.slice(0, 200),
|
|
218
|
-
};
|
|
219
|
-
const filePath = this.termsFile(name);
|
|
220
|
-
const tmpPath = filePath + ".tmp";
|
|
221
|
-
await fs.writeFile(tmpPath, JSON.stringify(terms, null, 2), "utf-8");
|
|
222
|
-
await fs.rename(tmpPath, filePath);
|
|
223
|
-
}
|
|
224
|
-
async loadTerms(name) {
|
|
225
|
-
try {
|
|
226
|
-
return await fs.readFile(this.termsFile(name), "utf-8");
|
|
227
|
-
}
|
|
228
|
-
catch {
|
|
229
|
-
return null;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
async createOntology(name, description) {
|
|
233
|
-
if (await this.ontologyExists(name)) {
|
|
234
|
-
throw new Error(`Ontology already exists: ${name}`);
|
|
235
|
-
}
|
|
236
|
-
const now = new Date().toISOString();
|
|
237
|
-
const data = {
|
|
238
|
-
metadata: {
|
|
239
|
-
name,
|
|
240
|
-
description,
|
|
241
|
-
createdAt: now,
|
|
242
|
-
updatedAt: now,
|
|
243
|
-
},
|
|
244
|
-
nodes: [],
|
|
245
|
-
edges: [],
|
|
246
|
-
};
|
|
247
|
-
await fs.mkdir(this.branchesDir(name), { recursive: true });
|
|
248
|
-
await this.saveMeta(name, { ...DEFAULT_META });
|
|
249
|
-
await this.saveOntology(name, data);
|
|
250
|
-
return data;
|
|
251
|
-
}
|
|
252
|
-
async renameOntology(oldName, newName) {
|
|
253
|
-
if (!(await this.ontologyExists(oldName))) {
|
|
254
|
-
throw new Error(`Ontology not found: ${oldName}`);
|
|
255
|
-
}
|
|
256
|
-
if (await this.ontologyExists(newName)) {
|
|
257
|
-
throw new Error(`Ontology already exists: ${newName}`);
|
|
258
|
-
}
|
|
259
|
-
// Rename the directory
|
|
260
|
-
await fs.rename(this.graphDir(oldName), this.graphDir(newName));
|
|
261
|
-
// Update metadata in the active branch
|
|
262
|
-
const data = await this.loadOntology(newName);
|
|
263
|
-
data.metadata.name = newName;
|
|
264
|
-
data.metadata.updatedAt = new Date().toISOString();
|
|
265
|
-
await this.saveOntology(newName, data);
|
|
266
|
-
}
|
|
267
|
-
async deleteOntology(name) {
|
|
268
|
-
if (!(await this.ontologyExists(name))) {
|
|
269
|
-
throw new Error(`Ontology not found: ${name}`);
|
|
270
|
-
}
|
|
271
|
-
await fs.rm(this.graphDir(name), { recursive: true });
|
|
272
|
-
}
|
|
273
|
-
async ontologyExists(name) {
|
|
274
|
-
try {
|
|
275
|
-
const meta = await this.loadMeta(name);
|
|
276
|
-
await fs.access(this.branchFile(name, meta.activeBranch));
|
|
277
|
-
return true;
|
|
278
|
-
}
|
|
279
|
-
catch {
|
|
280
|
-
return false;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
// --- Branch methods ---
|
|
284
|
-
async listBranches(name) {
|
|
285
|
-
const meta = await this.loadMeta(name);
|
|
286
|
-
const dir = this.branchesDir(name);
|
|
287
|
-
let entries;
|
|
288
|
-
try {
|
|
289
|
-
entries = await fs.readdir(dir);
|
|
290
|
-
}
|
|
291
|
-
catch {
|
|
292
|
-
return [];
|
|
293
|
-
}
|
|
294
|
-
const branches = [];
|
|
295
|
-
for (const entry of entries) {
|
|
296
|
-
if (!entry.endsWith(".json"))
|
|
297
|
-
continue;
|
|
298
|
-
const branchName = entry.replace(/\.json$/, "");
|
|
299
|
-
try {
|
|
300
|
-
const raw = await fs.readFile(path.join(dir, entry), "utf-8");
|
|
301
|
-
const data = JSON.parse(raw);
|
|
302
|
-
branches.push({
|
|
303
|
-
name: branchName,
|
|
304
|
-
nodeCount: data.nodes.length,
|
|
305
|
-
edgeCount: data.edges.length,
|
|
306
|
-
active: branchName === meta.activeBranch,
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
catch { }
|
|
310
|
-
}
|
|
311
|
-
return branches;
|
|
312
|
-
}
|
|
313
|
-
async createBranch(name, branchName, fromBranch) {
|
|
314
|
-
const branchFile = this.branchFile(name, branchName);
|
|
315
|
-
try {
|
|
316
|
-
await fs.access(branchFile);
|
|
317
|
-
throw new Error(`Branch already exists: ${branchName}`);
|
|
318
|
-
}
|
|
319
|
-
catch (err) {
|
|
320
|
-
if (err instanceof Error && err.message.startsWith("Branch already exists"))
|
|
321
|
-
throw err;
|
|
322
|
-
}
|
|
323
|
-
const meta = await this.loadMeta(name);
|
|
324
|
-
const sourceBranch = fromBranch ?? meta.activeBranch;
|
|
325
|
-
const sourceFile = this.branchFile(name, sourceBranch);
|
|
326
|
-
const raw = await fs.readFile(sourceFile, "utf-8");
|
|
327
|
-
await fs.mkdir(this.branchesDir(name), { recursive: true });
|
|
328
|
-
const tmpPath = branchFile + ".tmp";
|
|
329
|
-
await fs.writeFile(tmpPath, raw, "utf-8");
|
|
330
|
-
await fs.rename(tmpPath, branchFile);
|
|
331
|
-
}
|
|
332
|
-
async switchBranch(name, branchName) {
|
|
333
|
-
const branchFile = this.branchFile(name, branchName);
|
|
334
|
-
try {
|
|
335
|
-
await fs.access(branchFile);
|
|
336
|
-
}
|
|
337
|
-
catch {
|
|
338
|
-
throw new Error(`Branch not found: ${branchName}`);
|
|
339
|
-
}
|
|
340
|
-
const meta = await this.loadMeta(name);
|
|
341
|
-
meta.activeBranch = branchName;
|
|
342
|
-
await this.saveMeta(name, meta);
|
|
343
|
-
}
|
|
344
|
-
async deleteBranch(name, branchName) {
|
|
345
|
-
const meta = await this.loadMeta(name);
|
|
346
|
-
if (meta.activeBranch === branchName) {
|
|
347
|
-
throw new Error(`Cannot delete the active branch: ${branchName}`);
|
|
348
|
-
}
|
|
349
|
-
const branchFile = this.branchFile(name, branchName);
|
|
350
|
-
try {
|
|
351
|
-
await fs.access(branchFile);
|
|
352
|
-
}
|
|
353
|
-
catch {
|
|
354
|
-
throw new Error(`Branch not found: ${branchName}`);
|
|
355
|
-
}
|
|
356
|
-
await fs.rm(branchFile);
|
|
357
|
-
}
|
|
358
|
-
async loadBranch(name, branchName) {
|
|
359
|
-
const filePath = this.branchFile(name, branchName);
|
|
360
|
-
try {
|
|
361
|
-
const raw = await fs.readFile(filePath, "utf-8");
|
|
362
|
-
return JSON.parse(raw);
|
|
363
|
-
}
|
|
364
|
-
catch {
|
|
365
|
-
throw new Error(`Branch not found: ${branchName}`);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
// --- Snapshot methods ---
|
|
369
|
-
async createSnapshot(name, label) {
|
|
370
|
-
const meta = await this.loadMeta(name);
|
|
371
|
-
const branch = meta.activeBranch;
|
|
372
|
-
const snapDir = this.snapshotsDir(name, branch);
|
|
373
|
-
await fs.mkdir(snapDir, { recursive: true });
|
|
374
|
-
// Determine next version number
|
|
375
|
-
const existing = await this.listSnapshotFiles(name, branch);
|
|
376
|
-
const nextVersion = existing.length > 0
|
|
377
|
-
? existing[existing.length - 1].version + 1
|
|
378
|
-
: 1;
|
|
379
|
-
// Read current branch data
|
|
380
|
-
const raw = await fs.readFile(this.branchFile(name, branch), "utf-8");
|
|
381
|
-
const data = JSON.parse(raw);
|
|
382
|
-
const envelope = {
|
|
383
|
-
version: nextVersion,
|
|
384
|
-
timestamp: new Date().toISOString(),
|
|
385
|
-
branch,
|
|
386
|
-
data,
|
|
387
|
-
};
|
|
388
|
-
if (label)
|
|
389
|
-
envelope.label = label;
|
|
390
|
-
const filePath = this.snapshotFile(name, branch, nextVersion);
|
|
391
|
-
const tmpPath = filePath + ".tmp";
|
|
392
|
-
await fs.writeFile(tmpPath, JSON.stringify(envelope, null, 2), "utf-8");
|
|
393
|
-
await fs.rename(tmpPath, filePath);
|
|
394
|
-
// Prune old snapshots
|
|
395
|
-
await this.pruneSnapshots(name, branch, meta.snapshotLimit);
|
|
396
|
-
return nextVersion;
|
|
397
|
-
}
|
|
398
|
-
async listSnapshots(name) {
|
|
399
|
-
const meta = await this.loadMeta(name);
|
|
400
|
-
const branch = meta.activeBranch;
|
|
401
|
-
const snapDir = this.snapshotsDir(name, branch);
|
|
402
|
-
let entries;
|
|
403
|
-
try {
|
|
404
|
-
entries = await fs.readdir(snapDir);
|
|
405
|
-
}
|
|
406
|
-
catch {
|
|
407
|
-
return [];
|
|
408
|
-
}
|
|
409
|
-
const snapshots = [];
|
|
410
|
-
for (const entry of entries.sort()) {
|
|
411
|
-
if (!entry.endsWith(".json"))
|
|
412
|
-
continue;
|
|
413
|
-
try {
|
|
414
|
-
const raw = await fs.readFile(path.join(snapDir, entry), "utf-8");
|
|
415
|
-
const envelope = JSON.parse(raw);
|
|
416
|
-
const item = {
|
|
417
|
-
version: envelope.version,
|
|
418
|
-
timestamp: envelope.timestamp,
|
|
419
|
-
nodeCount: envelope.data.nodes.length,
|
|
420
|
-
edgeCount: envelope.data.edges.length,
|
|
421
|
-
};
|
|
422
|
-
if (envelope.label)
|
|
423
|
-
item.label = envelope.label;
|
|
424
|
-
snapshots.push(item);
|
|
425
|
-
}
|
|
426
|
-
catch { }
|
|
427
|
-
}
|
|
428
|
-
return snapshots.sort((a, b) => b.version - a.version);
|
|
429
|
-
}
|
|
430
|
-
async loadSnapshot(name, version) {
|
|
431
|
-
const meta = await this.loadMeta(name);
|
|
432
|
-
const filePath = this.snapshotFile(name, meta.activeBranch, version);
|
|
433
|
-
try {
|
|
434
|
-
const raw = await fs.readFile(filePath, "utf-8");
|
|
435
|
-
const envelope = JSON.parse(raw);
|
|
436
|
-
return envelope.data;
|
|
437
|
-
}
|
|
438
|
-
catch {
|
|
439
|
-
throw new Error(`Snapshot not found: version ${version}`);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
async rollback(name, version) {
|
|
443
|
-
const data = await this.loadSnapshot(name, version);
|
|
444
|
-
await this.saveOntology(name, data);
|
|
445
|
-
}
|
|
446
|
-
async getSnapshotLimit(name) {
|
|
447
|
-
const meta = await this.loadMeta(name);
|
|
448
|
-
return meta.snapshotLimit;
|
|
449
|
-
}
|
|
450
|
-
// --- Snapshot internals ---
|
|
451
|
-
async listSnapshotFiles(name, branch) {
|
|
452
|
-
const dir = this.snapshotsDir(name, branch);
|
|
453
|
-
let entries;
|
|
454
|
-
try {
|
|
455
|
-
entries = await fs.readdir(dir);
|
|
456
|
-
}
|
|
457
|
-
catch {
|
|
458
|
-
return [];
|
|
459
|
-
}
|
|
460
|
-
return entries
|
|
461
|
-
.filter((e) => e.endsWith(".json"))
|
|
462
|
-
.map((e) => ({ version: parseInt(e.replace(/\.json$/, ""), 10), filename: e }))
|
|
463
|
-
.filter((e) => !isNaN(e.version))
|
|
464
|
-
.sort((a, b) => a.version - b.version);
|
|
465
|
-
}
|
|
466
|
-
async pruneSnapshots(name, branch, limit) {
|
|
467
|
-
const existing = await this.listSnapshotFiles(name, branch);
|
|
468
|
-
if (existing.length <= limit)
|
|
469
|
-
return;
|
|
470
|
-
const toDelete = existing.slice(0, existing.length - limit);
|
|
471
|
-
for (const snap of toDelete) {
|
|
472
|
-
const filePath = path.join(this.snapshotsDir(name, branch), snap.filename);
|
|
473
|
-
await fs.rm(filePath).catch(() => { });
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
// --- Snippet methods ---
|
|
477
|
-
async saveSnippet(graphName, snippet) {
|
|
478
|
-
const id = snippet.label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").substring(0, 50) || "snippet";
|
|
479
|
-
const data = await this.loadOntology(graphName);
|
|
480
|
-
const meta = await this.loadMeta(graphName);
|
|
481
|
-
const nodeSet = new Set(snippet.nodeIds);
|
|
482
|
-
let resolvedEdgeIds = snippet.edgeIds;
|
|
483
|
-
if (!resolvedEdgeIds || resolvedEdgeIds.length === 0) {
|
|
484
|
-
resolvedEdgeIds = data.edges
|
|
485
|
-
.filter(e => nodeSet.has(e.sourceId) && nodeSet.has(e.targetId))
|
|
486
|
-
.map(e => e.id);
|
|
487
|
-
}
|
|
488
|
-
const edgeSet = new Set(resolvedEdgeIds);
|
|
489
|
-
const snippetData = {
|
|
490
|
-
id,
|
|
491
|
-
label: snippet.label,
|
|
492
|
-
description: snippet.description ?? "",
|
|
493
|
-
parentGraph: graphName,
|
|
494
|
-
parentBranch: meta.activeBranch,
|
|
495
|
-
nodeIds: snippet.nodeIds,
|
|
496
|
-
edgeIds: resolvedEdgeIds,
|
|
497
|
-
nodes: data.nodes.filter(n => nodeSet.has(n.id)),
|
|
498
|
-
edges: data.edges.filter(e => edgeSet.has(e.id)),
|
|
499
|
-
nodeCount: snippet.nodeIds.length,
|
|
500
|
-
edgeCount: resolvedEdgeIds.length,
|
|
501
|
-
createdAt: new Date().toISOString(),
|
|
502
|
-
};
|
|
503
|
-
const dir = this.snippetsDir(graphName);
|
|
504
|
-
await fs.mkdir(dir, { recursive: true });
|
|
505
|
-
const filePath = this.snippetFile(graphName, id);
|
|
506
|
-
const tmpPath = filePath + ".tmp";
|
|
507
|
-
await fs.writeFile(tmpPath, JSON.stringify(snippetData, null, 2), "utf-8");
|
|
508
|
-
await fs.rename(tmpPath, filePath);
|
|
509
|
-
return id;
|
|
510
|
-
}
|
|
511
|
-
async listSnippets(graphName) {
|
|
512
|
-
const dir = this.snippetsDir(graphName);
|
|
513
|
-
let entries;
|
|
514
|
-
try {
|
|
515
|
-
entries = await fs.readdir(dir);
|
|
516
|
-
}
|
|
517
|
-
catch {
|
|
518
|
-
return [];
|
|
519
|
-
}
|
|
520
|
-
const snippets = [];
|
|
521
|
-
for (const entry of entries.sort()) {
|
|
522
|
-
if (!entry.endsWith(".json"))
|
|
523
|
-
continue;
|
|
524
|
-
try {
|
|
525
|
-
const raw = await fs.readFile(path.join(dir, entry), "utf-8");
|
|
526
|
-
const data = JSON.parse(raw);
|
|
527
|
-
snippets.push({
|
|
528
|
-
id: data.id,
|
|
529
|
-
label: data.label,
|
|
530
|
-
description: data.description ?? "",
|
|
531
|
-
nodeCount: data.nodeCount ?? data.nodes?.length ?? 0,
|
|
532
|
-
edgeCount: data.edgeCount ?? data.edges?.length ?? 0,
|
|
533
|
-
createdAt: data.createdAt,
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
catch { }
|
|
537
|
-
}
|
|
538
|
-
return snippets;
|
|
539
|
-
}
|
|
540
|
-
async loadSnippet(graphName, snippetId) {
|
|
541
|
-
const filePath = this.snippetFile(graphName, snippetId);
|
|
542
|
-
const raw = await fs.readFile(filePath, "utf-8");
|
|
543
|
-
return JSON.parse(raw);
|
|
544
|
-
}
|
|
545
|
-
async deleteSnippet(graphName, snippetId) {
|
|
546
|
-
const filePath = this.snippetFile(graphName, snippetId);
|
|
547
|
-
await fs.rm(filePath);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
1
|
+
// JsonFileBackend is an alias for EventSourcedBackend.
|
|
2
|
+
//
|
|
3
|
+
// The original JsonFileBackend stored each graph as a single monolithic
|
|
4
|
+
// JSON file under branches/<branch>.json. That implementation was
|
|
5
|
+
// replaced by event-sourced storage in v0.3.0 (Phase 2 of the
|
|
6
|
+
// architectural reset). The class name is preserved for backward
|
|
7
|
+
// compatibility with downstream consumers like backpack-viewer that
|
|
8
|
+
// import { JsonFileBackend } from the package.
|
|
9
|
+
//
|
|
10
|
+
// New code should prefer EventSourcedBackend directly.
|
|
11
|
+
export { EventSourcedBackend as JsonFileBackend } from "./event-sourced-backend.js";
|
|
550
12
|
//# sourceMappingURL=json-file-backend.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-file-backend.js","sourceRoot":"","sources":["../../src/storage/json-file-backend.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"json-file-backend.js","sourceRoot":"","sources":["../../src/storage/json-file-backend.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,wEAAwE;AACxE,kEAAkE;AAClE,8DAA8D;AAC9D,iEAAiE;AACjE,oEAAoE;AACpE,+CAA+C;AAC/C,EAAE;AACF,uDAAuD;AAEvD,OAAO,EAAE,mBAAmB,IAAI,eAAe,EAAE,MAAM,4BAA4B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backpack-ontology",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A persistent learning graph engine for Claude Code via MCP — structured knowledge that carries forward across sessions",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Noah Irzinger",
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
"backpack-local": "./dist/bin/backpack.js",
|
|
11
11
|
"backpack-sync": "./dist/bin/backpack-sync.js",
|
|
12
12
|
"backpack-init": "./dist/bin/init.js",
|
|
13
|
+
"backpack-benchmark": "./dist/bin/backpack-benchmark.js",
|
|
13
14
|
"backpack": "./dist/bin/backpack.js"
|
|
14
15
|
},
|
|
15
16
|
"main": "./dist/index.js",
|
|
16
17
|
"types": "./dist/index.d.ts",
|
|
17
18
|
"files": [
|
|
18
|
-
"dist"
|
|
19
|
-
"hooks"
|
|
19
|
+
"dist"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "tsc",
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
You are a knowledge-capture agent for Backpack, a learning graph system. Your job is to review the conversation that just happened and decide whether meaningful knowledge should be preserved in a learning graph.
|
|
2
|
-
|
|
3
|
-
## Instructions
|
|
4
|
-
|
|
5
|
-
1. **Review the conversation transcript** — understand what was discussed, decided, or worked on.
|
|
6
|
-
|
|
7
|
-
2. **Decide if anything is worth capturing.** Look for:
|
|
8
|
-
- **Business knowledge**: client details, vendor info, pricing, partnerships, workflows
|
|
9
|
-
- **Technical knowledge**: architecture, APIs, data flows, integrations, design decisions
|
|
10
|
-
- **Domain knowledge**: industry concepts, terminology, regulations, best practices
|
|
11
|
-
- **Operational knowledge**: decisions made, problems solved, processes established, conventions agreed upon
|
|
12
|
-
- **Relationships**: how people, systems, concepts, or processes connect to each other
|
|
13
|
-
|
|
14
|
-
3. **Skip trivial interactions.** Do NOT capture:
|
|
15
|
-
- Simple Q&A with no lasting value
|
|
16
|
-
- Debugging sessions that led nowhere
|
|
17
|
-
- Casual conversation or greetings
|
|
18
|
-
- Knowledge that was already captured in a previous pass
|
|
19
|
-
- Temporary state or in-progress work that will change
|
|
20
|
-
|
|
21
|
-
4. **If there IS something worth capturing:**
|
|
22
|
-
a. Call `backpack_list` to see existing learning graphs
|
|
23
|
-
b. Call `backpack_describe` on relevant learning graphs to check what's already there
|
|
24
|
-
c. Decide: update an existing learning graph (if the topic fits) or create a new one (if the topic is distinct)
|
|
25
|
-
d. Use `backpack_import_nodes` for efficient bulk node creation
|
|
26
|
-
e. Use `backpack_add_edge` to create relationships between nodes
|
|
27
|
-
f. Use clear, descriptive node types and edge types that make the graph readable
|
|
28
|
-
|
|
29
|
-
5. **If there is NOTHING worth capturing**, simply stop. Do not force it.
|
|
30
|
-
|
|
31
|
-
6. **After making updates**, briefly tell the user what was added to their learning graph and suggest they can visualize it:
|
|
32
|
-
> "Your backpack was updated with [brief summary]. View it by running `npx backpack-viewer` and opening http://localhost:5173"
|
|
33
|
-
|
|
34
|
-
## Guidelines for good entries
|
|
35
|
-
|
|
36
|
-
- **Node types** should be clear nouns: `Person`, `Company`, `API`, `Decision`, `Process`, `Concept`, `Tool`, `Service`, `Regulation`, etc.
|
|
37
|
-
- **Edge types** should be clear relationships: `WORKS_WITH`, `DEPENDS_ON`, `DECIDED_TO`, `MANAGES`, `IMPLEMENTS`, `RELATES_TO`, etc.
|
|
38
|
-
- **Properties** should include enough context to be useful later: names, descriptions, dates, reasons, status.
|
|
39
|
-
- **Be selective but thorough** — capture the important things well rather than everything poorly.
|
|
40
|
-
- **Prefer updating existing nodes** over creating duplicates. Check if a concept already exists before adding it.
|