backpack-ontology 0.7.13 → 0.8.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 +123 -0
- package/dist/bin/bp.d.ts +3 -0
- package/dist/bin/bp.d.ts.map +1 -0
- package/dist/bin/bp.js +8 -0
- package/dist/bin/bp.js.map +1 -0
- package/dist/cli/colors.d.ts +23 -0
- package/dist/cli/colors.d.ts.map +1 -0
- package/dist/cli/colors.js +40 -0
- package/dist/cli/colors.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +4 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +50 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/cat.d.ts +3 -0
- package/dist/cli/commands/cat.d.ts.map +1 -0
- package/dist/cli/commands/cat.js +31 -0
- package/dist/cli/commands/cat.js.map +1 -0
- package/dist/cli/commands/cloud-admin.d.ts +7 -0
- package/dist/cli/commands/cloud-admin.d.ts.map +1 -0
- package/dist/cli/commands/cloud-admin.js +186 -0
- package/dist/cli/commands/cloud-admin.js.map +1 -0
- package/dist/cli/commands/completion.d.ts +3 -0
- package/dist/cli/commands/completion.d.ts.map +1 -0
- package/dist/cli/commands/completion.js +159 -0
- package/dist/cli/commands/completion.js.map +1 -0
- package/dist/cli/commands/containers.d.ts +3 -0
- package/dist/cli/commands/containers.d.ts.map +1 -0
- package/dist/cli/commands/containers.js +30 -0
- package/dist/cli/commands/containers.js.map +1 -0
- package/dist/cli/commands/context.d.ts +4 -0
- package/dist/cli/commands/context.d.ts.map +1 -0
- package/dist/cli/commands/context.js +61 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +74 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/graphs.d.ts +3 -0
- package/dist/cli/commands/graphs.d.ts.map +1 -0
- package/dist/cli/commands/graphs.js +68 -0
- package/dist/cli/commands/graphs.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +56 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/kbs.d.ts +3 -0
- package/dist/cli/commands/kbs.d.ts.map +1 -0
- package/dist/cli/commands/kbs.js +258 -0
- package/dist/cli/commands/kbs.js.map +1 -0
- package/dist/cli/commands/ls.d.ts +3 -0
- package/dist/cli/commands/ls.d.ts.map +1 -0
- package/dist/cli/commands/ls.js +90 -0
- package/dist/cli/commands/ls.js.map +1 -0
- package/dist/cli/commands/mutate.d.ts +7 -0
- package/dist/cli/commands/mutate.d.ts.map +1 -0
- package/dist/cli/commands/mutate.js +268 -0
- package/dist/cli/commands/mutate.js.map +1 -0
- package/dist/cli/commands/open.d.ts +3 -0
- package/dist/cli/commands/open.d.ts.map +1 -0
- package/dist/cli/commands/open.js +59 -0
- package/dist/cli/commands/open.js.map +1 -0
- package/dist/cli/commands/search.d.ts +3 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +63 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/commands/show.d.ts +3 -0
- package/dist/cli/commands/show.d.ts.map +1 -0
- package/dist/cli/commands/show.js +82 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/version.d.ts +2 -0
- package/dist/cli/commands/version.d.ts.map +1 -0
- package/dist/cli/commands/version.js +18 -0
- package/dist/cli/commands/version.js.map +1 -0
- package/dist/cli/help.d.ts +3 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +122 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/output.d.ts +35 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +224 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/parser.d.ts +16 -0
- package/dist/cli/parser.d.ts.map +1 -0
- package/dist/cli/parser.js +131 -0
- package/dist/cli/parser.js.map +1 -0
- package/dist/cli/router.d.ts +2 -0
- package/dist/cli/router.d.ts.map +1 -0
- package/dist/cli/router.js +147 -0
- package/dist/cli/router.js.map +1 -0
- package/dist/cli/util/confirm.d.ts +3 -0
- package/dist/cli/util/confirm.d.ts.map +1 -0
- package/dist/cli/util/confirm.js +48 -0
- package/dist/cli/util/confirm.js.map +1 -0
- package/dist/core/backpack.d.ts +8 -0
- package/dist/core/backpack.d.ts.map +1 -1
- package/dist/core/backpack.js +32 -0
- package/dist/core/backpack.js.map +1 -1
- package/dist/mcp/tools/cloud-tools.d.ts +2 -2
- package/dist/mcp/tools/cloud-tools.d.ts.map +1 -1
- package/dist/mcp/tools/cloud-tools.js +244 -55
- package/dist/mcp/tools/cloud-tools.js.map +1 -1
- package/dist/ops/auth.d.ts +54 -0
- package/dist/ops/auth.d.ts.map +1 -0
- package/dist/ops/auth.js +181 -0
- package/dist/ops/auth.js.map +1 -0
- package/dist/ops/containers.d.ts +27 -0
- package/dist/ops/containers.d.ts.map +1 -0
- package/dist/ops/containers.js +150 -0
- package/dist/ops/containers.js.map +1 -0
- package/dist/ops/context.d.ts +51 -0
- package/dist/ops/context.d.ts.map +1 -0
- package/dist/ops/context.js +158 -0
- package/dist/ops/context.js.map +1 -0
- package/dist/ops/graphs.d.ts +69 -0
- package/dist/ops/graphs.d.ts.map +1 -0
- package/dist/ops/graphs.js +278 -0
- package/dist/ops/graphs.js.map +1 -0
- package/dist/ops/kb.d.ts +33 -0
- package/dist/ops/kb.d.ts.map +1 -0
- package/dist/ops/kb.js +176 -0
- package/dist/ops/kb.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
// `bp kbs <verb>` — canonical form. Read-only in Step 2 (list, get).
|
|
2
|
+
import * as fs from "node:fs/promises";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
import { flagString } from "../parser.js";
|
|
7
|
+
import { runLs } from "./ls.js";
|
|
8
|
+
import { resolveFormat, emitOne } from "../output.js";
|
|
9
|
+
import { getKB, saveKB, deleteKB } from "../../ops/kb.js";
|
|
10
|
+
import { runMoveKB } from "./cloud-admin.js";
|
|
11
|
+
import { confirm } from "../util/confirm.js";
|
|
12
|
+
import { red, green, dim, bold, yellow } from "../colors.js";
|
|
13
|
+
export async function runKbs(args) {
|
|
14
|
+
const verb = args.positional[0];
|
|
15
|
+
if (!verb) {
|
|
16
|
+
process.stderr.write(`bp kbs: verb required.\nusage: bp kbs <list|get> [args]\n`);
|
|
17
|
+
return 1;
|
|
18
|
+
}
|
|
19
|
+
const sub = { positional: args.positional.slice(1), flags: args.flags, rest: args.rest };
|
|
20
|
+
switch (verb) {
|
|
21
|
+
case "list":
|
|
22
|
+
case "ls":
|
|
23
|
+
return runLs({ ...sub, positional: ["kbs", ...sub.positional] });
|
|
24
|
+
case "get":
|
|
25
|
+
case "cat":
|
|
26
|
+
return runKbGet(sub);
|
|
27
|
+
case "create":
|
|
28
|
+
case "new":
|
|
29
|
+
return runKbCreate(sub);
|
|
30
|
+
case "delete":
|
|
31
|
+
case "rm":
|
|
32
|
+
case "remove":
|
|
33
|
+
return runKbDelete(sub);
|
|
34
|
+
case "edit":
|
|
35
|
+
return runKbEdit(sub);
|
|
36
|
+
case "move":
|
|
37
|
+
case "mv-to":
|
|
38
|
+
return runMoveKB(sub);
|
|
39
|
+
default:
|
|
40
|
+
process.stderr.write(`bp kbs: unknown verb "${verb}". try list, get, create, edit, delete, or move.\n`);
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function runKbCreate(args) {
|
|
45
|
+
const file = flagString(args, "f", "file", "from-file");
|
|
46
|
+
const titleArg = flagString(args, "title", "t");
|
|
47
|
+
const contentArg = flagString(args, "content");
|
|
48
|
+
const collection = flagString(args, "collection", "c");
|
|
49
|
+
const tagsRaw = flagString(args, "tags");
|
|
50
|
+
const tags = tagsRaw ? tagsRaw.split(",").map((t) => t.trim()).filter(Boolean) : undefined;
|
|
51
|
+
const sourceRaw = flagString(args, "from-graphs");
|
|
52
|
+
const sourceGraphs = sourceRaw ? sourceRaw.split(",").map((s) => s.trim()).filter(Boolean) : undefined;
|
|
53
|
+
if (file && contentArg !== undefined) {
|
|
54
|
+
process.stderr.write(`bp kbs create: pass either -f <file> or --content, not both.\n`);
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
let title;
|
|
58
|
+
let content;
|
|
59
|
+
if (file) {
|
|
60
|
+
const raw = await fs.readFile(file, "utf8").catch((err) => {
|
|
61
|
+
process.stderr.write(`${red("✗")} could not read ${file}: ${err.message}\n`);
|
|
62
|
+
return null;
|
|
63
|
+
});
|
|
64
|
+
if (raw === null)
|
|
65
|
+
return 1;
|
|
66
|
+
// Strip leading YAML front-matter if present. DocumentStore re-prepends
|
|
67
|
+
// its own front-matter on save; without this strip the file ends up
|
|
68
|
+
// with two `---` blocks and the user's metadata silently lost.
|
|
69
|
+
const stripped = stripLeadingFrontmatter(raw);
|
|
70
|
+
content = stripped.content;
|
|
71
|
+
// Honor the file's `title:` if the CLI didn't override.
|
|
72
|
+
title = titleArg ?? stripped.frontmatter.title ?? path.basename(file, path.extname(file));
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
if (!titleArg) {
|
|
76
|
+
process.stderr.write(`bp kbs create: pass either -f <file> or --title <title> --content <text>.\n`);
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
title = titleArg;
|
|
80
|
+
if (contentArg === undefined) {
|
|
81
|
+
process.stderr.write(`bp kbs create: --content is required when not using -f <file>.\n`);
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
content = contentArg;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const { id, created } = await saveKB({ title, content, tags, sourceGraphs, collection });
|
|
88
|
+
process.stdout.write(`${green("✓")} ${created ? "created" : "updated"} ${bold(title)} ${dim(`(${id})`)}\n`);
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Pull leading YAML front-matter off a file body. Tolerant — only
|
|
97
|
+
* recognizes the literal `---\n…\n---\n` shape; anything else is
|
|
98
|
+
* returned as-is. Does NOT parse arbitrary YAML — we only care about
|
|
99
|
+
* a few common keys (title, tags) and treat the rest as opaque. */
|
|
100
|
+
function stripLeadingFrontmatter(raw) {
|
|
101
|
+
if (!raw.startsWith("---"))
|
|
102
|
+
return { content: raw, frontmatter: {} };
|
|
103
|
+
const endMatch = raw.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
104
|
+
if (!endMatch)
|
|
105
|
+
return { content: raw, frontmatter: {} };
|
|
106
|
+
const block = endMatch[1];
|
|
107
|
+
const rest = raw.slice(endMatch[0].length);
|
|
108
|
+
const fm = {};
|
|
109
|
+
for (const line of block.split("\n")) {
|
|
110
|
+
const m = line.match(/^([a-zA-Z0-9_-]+)\s*:\s*(.*)$/);
|
|
111
|
+
if (!m)
|
|
112
|
+
continue;
|
|
113
|
+
const k = m[1];
|
|
114
|
+
const v = m[2].trim();
|
|
115
|
+
if (k === "title") {
|
|
116
|
+
fm.title = v.replace(/^["']|["']$/g, "");
|
|
117
|
+
}
|
|
118
|
+
else if (k === "tags") {
|
|
119
|
+
// Accept "tags: a, b, c" or "tags: [a, b]" — best-effort.
|
|
120
|
+
const cleaned = v.replace(/^\[|\]$/g, "");
|
|
121
|
+
fm.tags = cleaned.split(",").map((t) => t.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return { content: rest, frontmatter: fm };
|
|
125
|
+
}
|
|
126
|
+
async function runKbDelete(args) {
|
|
127
|
+
const id = args.positional[0];
|
|
128
|
+
if (!id) {
|
|
129
|
+
process.stderr.write(`bp kbs delete: doc id required.\nusage: bp kbs delete <id> [-y]\n`);
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
let existing;
|
|
133
|
+
try {
|
|
134
|
+
existing = await getKB(id);
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
138
|
+
return 1;
|
|
139
|
+
}
|
|
140
|
+
if (!existing) {
|
|
141
|
+
process.stderr.write(`${red("✗")} kb doc "${id}" not found in the current scope.\n`);
|
|
142
|
+
return 1;
|
|
143
|
+
}
|
|
144
|
+
const ok = await confirm(`delete ${bold(existing.title)} (${id})? [y/N] `, args);
|
|
145
|
+
if (!ok) {
|
|
146
|
+
process.stderr.write(dim("aborted.\n"));
|
|
147
|
+
return 0;
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
await deleteKB(id);
|
|
151
|
+
process.stdout.write(`${green("✓")} deleted ${bold(existing.title)}\n`);
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
156
|
+
return 1;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function runKbEdit(args) {
|
|
160
|
+
const id = args.positional[0];
|
|
161
|
+
if (!id) {
|
|
162
|
+
process.stderr.write(`bp kbs edit: doc id required.\n`);
|
|
163
|
+
return 1;
|
|
164
|
+
}
|
|
165
|
+
let doc;
|
|
166
|
+
try {
|
|
167
|
+
doc = await getKB(id);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
171
|
+
return 1;
|
|
172
|
+
}
|
|
173
|
+
if (!doc) {
|
|
174
|
+
process.stderr.write(`${red("✗")} kb doc "${id}" not found.\n`);
|
|
175
|
+
return 1;
|
|
176
|
+
}
|
|
177
|
+
const editorCmd = process.env.EDITOR || process.env.VISUAL || (process.platform === "win32" ? "notepad" : "vi");
|
|
178
|
+
const tokens = editorCmd.trim().split(/\s+/).filter(Boolean);
|
|
179
|
+
const editor = tokens[0];
|
|
180
|
+
const editorArgs = tokens.slice(1);
|
|
181
|
+
const userTmpDir = path.join(os.tmpdir(), `bp-${process.getuid?.() ?? "u"}`);
|
|
182
|
+
await fs.mkdir(userTmpDir, { recursive: true });
|
|
183
|
+
const tmpFile = path.join(userTmpDir, `kb-edit-${process.pid}-${Date.now()}.md`);
|
|
184
|
+
const original = doc.content;
|
|
185
|
+
await fs.writeFile(tmpFile, original, { mode: 0o600 });
|
|
186
|
+
let cleanedUp = false;
|
|
187
|
+
let interrupted = false;
|
|
188
|
+
const cleanup = async () => {
|
|
189
|
+
if (cleanedUp)
|
|
190
|
+
return;
|
|
191
|
+
cleanedUp = true;
|
|
192
|
+
await fs.unlink(tmpFile).catch(() => { });
|
|
193
|
+
};
|
|
194
|
+
const onSig = () => {
|
|
195
|
+
interrupted = true;
|
|
196
|
+
process.exitCode = 130;
|
|
197
|
+
};
|
|
198
|
+
process.once("SIGINT", onSig);
|
|
199
|
+
process.once("SIGTERM", onSig);
|
|
200
|
+
try {
|
|
201
|
+
const exitCode = await new Promise((resolve, reject) => {
|
|
202
|
+
const child = spawn(editor, [...editorArgs, tmpFile], { stdio: "inherit" });
|
|
203
|
+
child.on("error", reject);
|
|
204
|
+
child.on("exit", (code) => resolve(code ?? 0));
|
|
205
|
+
});
|
|
206
|
+
if (interrupted)
|
|
207
|
+
return 130;
|
|
208
|
+
if (exitCode !== 0) {
|
|
209
|
+
process.stderr.write(`${yellow("!")} editor exited ${exitCode} — changes discarded.\n`);
|
|
210
|
+
return 1;
|
|
211
|
+
}
|
|
212
|
+
const updated = await fs.readFile(tmpFile, "utf8");
|
|
213
|
+
if (updated === original) {
|
|
214
|
+
process.stdout.write(dim("no changes.\n"));
|
|
215
|
+
return 0;
|
|
216
|
+
}
|
|
217
|
+
await saveKB({ id, title: doc.title, content: updated, tags: doc.tags, sourceGraphs: doc.sourceGraphs, collection: doc.collection });
|
|
218
|
+
process.stdout.write(`${green("✓")} updated ${bold(doc.title)}\n`);
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
223
|
+
return 1;
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
process.removeListener("SIGINT", onSig);
|
|
227
|
+
process.removeListener("SIGTERM", onSig);
|
|
228
|
+
await cleanup();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async function runKbGet(args) {
|
|
232
|
+
const id = args.positional[0];
|
|
233
|
+
if (!id) {
|
|
234
|
+
process.stderr.write(`bp kbs get: doc id required.\n`);
|
|
235
|
+
return 1;
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
const doc = await getKB(id);
|
|
239
|
+
if (!doc) {
|
|
240
|
+
process.stderr.write(`${red("✗")} kb doc "${id}" not found in the current scope.\n`);
|
|
241
|
+
return 1;
|
|
242
|
+
}
|
|
243
|
+
const fmt = resolveFormat(args.flags);
|
|
244
|
+
if (fmt === "human") {
|
|
245
|
+
// Print just the content for piping; metadata via --json
|
|
246
|
+
process.stdout.write(doc.content + (doc.content.endsWith("\n") ? "" : "\n"));
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
emitOne(doc, { format: fmt });
|
|
250
|
+
}
|
|
251
|
+
return 0;
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
255
|
+
return 1;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=kbs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kbs.js","sourceRoot":"","sources":["../../../src/cli/commands/kbs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ls.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAe1C,wBAAsB,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAmF7D"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// `bp ls [resource]` — the daily-driver list command. Defaults to graphs.
|
|
2
|
+
// `bp ls graphs|kbs|containers` selects a different resource. Plural and
|
|
3
|
+
// singular both accepted (`graphs`/`graph`, `kbs`/`kb`, `containers`/`container`).
|
|
4
|
+
import { resolveFormat, emitList } from "../output.js";
|
|
5
|
+
import { dim, red, yellow } from "../colors.js";
|
|
6
|
+
import { listGraphs } from "../../ops/graphs.js";
|
|
7
|
+
import { listContainers } from "../../ops/containers.js";
|
|
8
|
+
import { listKB } from "../../ops/kb.js";
|
|
9
|
+
import { describeContext, getContext } from "../../ops/context.js";
|
|
10
|
+
import { resolveCloudToken } from "../../ops/auth.js";
|
|
11
|
+
const RESOURCE_ALIASES = {
|
|
12
|
+
graphs: "graphs", graph: "graphs", g: "graphs",
|
|
13
|
+
containers: "containers", container: "containers", c: "containers", buckets: "containers",
|
|
14
|
+
kbs: "kbs", kb: "kbs", docs: "kbs", doc: "kbs",
|
|
15
|
+
};
|
|
16
|
+
export async function runLs(args) {
|
|
17
|
+
const target = args.positional[0] ?? "graphs";
|
|
18
|
+
const resource = RESOURCE_ALIASES[target.toLowerCase()];
|
|
19
|
+
if (!resource) {
|
|
20
|
+
process.stderr.write(`bp ls: unknown resource "${target}". try graphs, containers, or kbs.\n`);
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
23
|
+
const fmt = { format: resolveFormat(args.flags) };
|
|
24
|
+
// For cloud listings, do an upfront auth check so the user gets a
|
|
25
|
+
// clear "not signed in" message rather than a generic fetch failure.
|
|
26
|
+
// Returns the same exit code as every other auth-failure path (1) —
|
|
27
|
+
// the entire CLI uses 0/1 like kubectl, not the kludge of a third
|
|
28
|
+
// code that scripts would have to special-case for one command.
|
|
29
|
+
const ctx = await getContext();
|
|
30
|
+
const needsCloud = ctx.source === "cloud" || resource === "containers";
|
|
31
|
+
if (needsCloud) {
|
|
32
|
+
const token = await resolveCloudToken();
|
|
33
|
+
if (!token) {
|
|
34
|
+
process.stderr.write(`${yellow("!")} not signed in. run \`bp login\` first to list ${resource}.\n`);
|
|
35
|
+
return 1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
if (resource === "graphs") {
|
|
40
|
+
const rows = await listGraphs();
|
|
41
|
+
emitList({
|
|
42
|
+
rows,
|
|
43
|
+
pluralLabel: "graphs",
|
|
44
|
+
empty: `no graphs in ${describeContext(await getContext())}.`,
|
|
45
|
+
cols: [
|
|
46
|
+
{ header: "NAME", get: (r) => r.name, max: 40 },
|
|
47
|
+
{ header: "NODES", get: (r) => String(r.nodeCount), numeric: true },
|
|
48
|
+
{ header: "EDGES", get: (r) => String(r.edgeCount), numeric: true },
|
|
49
|
+
{ header: "FLAGS", get: (r) => r.encrypted ? yellow("encrypted") : "", wide: true },
|
|
50
|
+
{ header: "DESCRIPTION", get: (r) => r.description ?? "", dim: true, max: 60, wide: true },
|
|
51
|
+
],
|
|
52
|
+
}, fmt);
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
if (resource === "containers") {
|
|
56
|
+
const rows = await listContainers();
|
|
57
|
+
emitList({
|
|
58
|
+
rows,
|
|
59
|
+
pluralLabel: "containers",
|
|
60
|
+
empty: dim("no cloud containers (sign in and try again)."),
|
|
61
|
+
cols: [
|
|
62
|
+
{ header: "NAME", get: (r) => r.name, max: 32 },
|
|
63
|
+
{ header: "ORIGIN", get: (r) => r.origin_kind === "local" ? `device${r.origin_device_name ? ` · ${r.origin_device_name}` : ""}` : "cloud" },
|
|
64
|
+
{ header: "ID", get: (r) => r.id, dim: true, wide: true },
|
|
65
|
+
{ header: "TAGS", get: (r) => (r.tags ?? []).join(",") || "", dim: true, wide: true },
|
|
66
|
+
],
|
|
67
|
+
}, fmt);
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
// kbs
|
|
71
|
+
const rows = await listKB();
|
|
72
|
+
emitList({
|
|
73
|
+
rows,
|
|
74
|
+
pluralLabel: "kbs",
|
|
75
|
+
empty: dim("no KB documents in the current scope."),
|
|
76
|
+
cols: [
|
|
77
|
+
{ header: "ID", get: (r) => r.id, max: 40 },
|
|
78
|
+
{ header: "TITLE", get: (r) => r.title, max: 50 },
|
|
79
|
+
{ header: "TAGS", get: (r) => r.tags.join(","), dim: true, wide: true },
|
|
80
|
+
{ header: "GRAPHS", get: (r) => r.sourceGraphs.join(","), dim: true, wide: true },
|
|
81
|
+
],
|
|
82
|
+
}, fmt);
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
87
|
+
return 1;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=ls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/cli/commands/ls.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ParsedArgs } from "../parser.js";
|
|
2
|
+
export declare function runCreate(args: ParsedArgs): Promise<number>;
|
|
3
|
+
export declare function runDelete(args: ParsedArgs): Promise<number>;
|
|
4
|
+
export declare function runRename(args: ParsedArgs): Promise<number>;
|
|
5
|
+
export declare function runApply(args: ParsedArgs): Promise<number>;
|
|
6
|
+
export declare function runEdit(args: ParsedArgs): Promise<number>;
|
|
7
|
+
//# sourceMappingURL=mutate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/mutate.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAc,MAAM,cAAc,CAAC;AAatD,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAqCjE;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAgCjE;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBjE;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAoChE;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CA8F/D"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// Mutating verbs: create, delete, rename, apply, edit. Shared by both
|
|
2
|
+
// the canonical (`bp graphs <verb>`) and shortcut (`bp rm`, `bp mv`)
|
|
3
|
+
// command surfaces.
|
|
4
|
+
import * as fs from "node:fs/promises";
|
|
5
|
+
import * as os from "node:os";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import { spawn } from "node:child_process";
|
|
8
|
+
import { flagString } from "../parser.js";
|
|
9
|
+
import { createGraph, deleteGraph, renameGraph, applyGraph, getGraph, getGraphSummary, } from "../../ops/graphs.js";
|
|
10
|
+
import { red, yellow, green, dim, bold } from "../colors.js";
|
|
11
|
+
import { confirm } from "../util/confirm.js";
|
|
12
|
+
export async function runCreate(args) {
|
|
13
|
+
const name = args.positional[0];
|
|
14
|
+
if (!name) {
|
|
15
|
+
process.stderr.write(`bp graphs create: name required.\nusage: bp graphs create <name> [--description=...] [--from-file=path.json]\n`);
|
|
16
|
+
return 1;
|
|
17
|
+
}
|
|
18
|
+
const fromFile = flagString(args, "from-file", "f");
|
|
19
|
+
const description = flagString(args, "description", "d") ?? "";
|
|
20
|
+
try {
|
|
21
|
+
// Reject if a graph by this name already exists. `create` is not an
|
|
22
|
+
// upsert — `bp graphs apply -f file` is the upsert verb. Without
|
|
23
|
+
// this check, --from-file could silently overwrite an existing graph.
|
|
24
|
+
const existing = await getGraphSummary(name).catch(() => null);
|
|
25
|
+
if (existing) {
|
|
26
|
+
process.stderr.write(`${red("✗")} graph "${name}" already exists. use \`bp graphs apply\` to overwrite.\n`);
|
|
27
|
+
return 1;
|
|
28
|
+
}
|
|
29
|
+
if (fromFile) {
|
|
30
|
+
const raw = await fs.readFile(fromFile, "utf8");
|
|
31
|
+
const data = JSON.parse(raw);
|
|
32
|
+
// Reject mismatch between the requested name and the file's metadata
|
|
33
|
+
// unless the file's metadata is missing (legitimate template case).
|
|
34
|
+
if (data.metadata?.name && data.metadata.name !== name) {
|
|
35
|
+
process.stderr.write(`${red("✗")} file's metadata.name is "${data.metadata.name}" but the create target is "${name}". rename in the file or call \`bp graphs apply\` instead.\n`);
|
|
36
|
+
return 1;
|
|
37
|
+
}
|
|
38
|
+
await applyGraph(name, data);
|
|
39
|
+
process.stdout.write(`${green("✓")} created ${bold(name)} from ${dim(fromFile)}\n`);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
await createGraph(name, { description });
|
|
43
|
+
process.stdout.write(`${green("✓")} created ${bold(name)}\n`);
|
|
44
|
+
}
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export async function runDelete(args) {
|
|
53
|
+
const name = args.positional[0];
|
|
54
|
+
if (!name) {
|
|
55
|
+
process.stderr.write(`bp graphs delete: name required.\nusage: bp graphs delete <name> [-y]\n`);
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
// Existence check first so we don't prompt for nothing.
|
|
59
|
+
let summary;
|
|
60
|
+
try {
|
|
61
|
+
summary = await getGraphSummary(name);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
if (!summary) {
|
|
68
|
+
process.stderr.write(`${red("✗")} graph "${name}" not found in the current scope.\n`);
|
|
69
|
+
return 1;
|
|
70
|
+
}
|
|
71
|
+
const ok = await confirm(`delete ${bold(name)} (${summary.nodeCount} nodes, ${summary.edgeCount} edges)? [y/N] `, args);
|
|
72
|
+
if (!ok) {
|
|
73
|
+
// User-cancelled — exit 0. Scripts wrapping `bp rm` with `set -e`
|
|
74
|
+
// shouldn't treat a deliberate "no" as a failure.
|
|
75
|
+
process.stdout.write(dim("aborted.\n"));
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
await deleteGraph(name);
|
|
80
|
+
process.stdout.write(`${green("✓")} deleted ${bold(name)}\n`);
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
85
|
+
return 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export async function runRename(args) {
|
|
89
|
+
const [oldName, newName] = args.positional;
|
|
90
|
+
if (!oldName || !newName) {
|
|
91
|
+
process.stderr.write(`bp graphs rename: old + new names required.\nusage: bp graphs rename <old> <new>\n`);
|
|
92
|
+
return 1;
|
|
93
|
+
}
|
|
94
|
+
if (oldName === newName) {
|
|
95
|
+
process.stderr.write(`bp graphs rename: old and new names are the same.\n`);
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
await renameGraph(oldName, newName);
|
|
100
|
+
process.stdout.write(`${green("✓")} ${bold(oldName)} → ${bold(newName)}\n`);
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export async function runApply(args) {
|
|
109
|
+
const file = flagString(args, "f", "file", "from-file");
|
|
110
|
+
if (!file) {
|
|
111
|
+
process.stderr.write(`bp graphs apply: -f <file> required.\nusage: bp graphs apply -f <file.json>\n`);
|
|
112
|
+
return 1;
|
|
113
|
+
}
|
|
114
|
+
let data;
|
|
115
|
+
try {
|
|
116
|
+
const raw = await fs.readFile(file, "utf8");
|
|
117
|
+
data = JSON.parse(raw);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
process.stderr.write(`${red("✗")} could not read ${file}: ${err.message}\n`);
|
|
121
|
+
return 1;
|
|
122
|
+
}
|
|
123
|
+
const explicit = args.positional[0];
|
|
124
|
+
const fileName = data.metadata?.name;
|
|
125
|
+
// If both are present and disagree, refuse: silently using the
|
|
126
|
+
// command-line name would rewrite the file's identity inside the graph
|
|
127
|
+
// store and confuse anyone tracking provenance.
|
|
128
|
+
if (explicit && fileName && explicit !== fileName) {
|
|
129
|
+
process.stderr.write(`${red("✗")} name mismatch: argument is "${explicit}" but file's metadata.name is "${fileName}". pick one or fix the file.\n`);
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
const name = explicit ?? fileName;
|
|
133
|
+
if (!name) {
|
|
134
|
+
process.stderr.write(`bp graphs apply: graph name not in file metadata; pass it as the first positional arg.\n`);
|
|
135
|
+
return 1;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const { created } = await applyGraph(name, data);
|
|
139
|
+
process.stdout.write(`${green("✓")} ${created ? "created" : "applied"} ${bold(name)} (${data.nodes?.length ?? 0} nodes, ${data.edges?.length ?? 0} edges)\n`);
|
|
140
|
+
return 0;
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
144
|
+
return 1;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export async function runEdit(args) {
|
|
148
|
+
const name = args.positional[0];
|
|
149
|
+
if (!name) {
|
|
150
|
+
process.stderr.write(`bp graphs edit: name required.\nusage: bp graphs edit <name>\n`);
|
|
151
|
+
return 1;
|
|
152
|
+
}
|
|
153
|
+
let result;
|
|
154
|
+
try {
|
|
155
|
+
result = await getGraph(name);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
159
|
+
return 1;
|
|
160
|
+
}
|
|
161
|
+
if (result.kind === "missing") {
|
|
162
|
+
process.stderr.write(`${red("✗")} graph "${name}" not found in the current scope.\n`);
|
|
163
|
+
return 1;
|
|
164
|
+
}
|
|
165
|
+
if (result.kind === "encrypted") {
|
|
166
|
+
process.stderr.write(`${yellow("!")} graph "${name}" is encrypted — cannot edit from the CLI.\n`);
|
|
167
|
+
return 1;
|
|
168
|
+
}
|
|
169
|
+
// Resolve $EDITOR. Common values like `code --wait` are
|
|
170
|
+
// command-and-args, not a single binary path; split on whitespace
|
|
171
|
+
// (good enough — anything more exotic the user can wrap in a script).
|
|
172
|
+
const editorCmd = process.env.EDITOR || process.env.VISUAL || (process.platform === "win32" ? "notepad" : "vi");
|
|
173
|
+
const editorTokens = editorCmd.trim().split(/\s+/).filter(Boolean);
|
|
174
|
+
const editor = editorTokens[0];
|
|
175
|
+
const editorArgs = editorTokens.slice(1);
|
|
176
|
+
// Per-user tmpdir + 0600 mode so a SIGKILL-orphaned file doesn't leak
|
|
177
|
+
// graph contents to other users on shared machines.
|
|
178
|
+
const userTmpDir = path.join(os.tmpdir(), `bp-${process.getuid?.() ?? "u"}`);
|
|
179
|
+
await fs.mkdir(userTmpDir, { recursive: true });
|
|
180
|
+
const tmpFile = path.join(userTmpDir, `edit-${process.pid}-${Date.now()}.json`);
|
|
181
|
+
const original = JSON.stringify(result.data, null, 2);
|
|
182
|
+
await fs.writeFile(tmpFile, original, { mode: 0o600 });
|
|
183
|
+
// Make a best-effort cleanup on SIGINT so a Ctrl-C mid-edit doesn't
|
|
184
|
+
// strand the tmp file. Pulled into a flag so the finally clause and
|
|
185
|
+
// the signal handler don't double-unlink.
|
|
186
|
+
let cleanedUp = false;
|
|
187
|
+
let interrupted = false;
|
|
188
|
+
const cleanup = async () => {
|
|
189
|
+
if (cleanedUp)
|
|
190
|
+
return;
|
|
191
|
+
cleanedUp = true;
|
|
192
|
+
await fs.unlink(tmpFile).catch(() => { });
|
|
193
|
+
};
|
|
194
|
+
const onSig = () => {
|
|
195
|
+
interrupted = true;
|
|
196
|
+
process.exitCode = 130;
|
|
197
|
+
};
|
|
198
|
+
process.once("SIGINT", onSig);
|
|
199
|
+
process.once("SIGTERM", onSig);
|
|
200
|
+
try {
|
|
201
|
+
const exitCode = await new Promise((resolve, reject) => {
|
|
202
|
+
const child = spawn(editor, [...editorArgs, tmpFile], { stdio: "inherit" });
|
|
203
|
+
child.on("error", reject);
|
|
204
|
+
child.on("exit", (code) => resolve(code ?? 0));
|
|
205
|
+
});
|
|
206
|
+
if (interrupted)
|
|
207
|
+
return 130;
|
|
208
|
+
if (exitCode !== 0) {
|
|
209
|
+
process.stderr.write(`${yellow("!")} editor exited ${exitCode} — changes discarded.\n`);
|
|
210
|
+
return 1;
|
|
211
|
+
}
|
|
212
|
+
const updated = await fs.readFile(tmpFile, "utf8");
|
|
213
|
+
let parsed;
|
|
214
|
+
try {
|
|
215
|
+
parsed = JSON.parse(updated);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
process.stderr.write(`${red("✗")} edited file is not valid JSON: ${err.message}\n`);
|
|
219
|
+
process.stderr.write(dim(` preserved at ${tmpFile}\n`));
|
|
220
|
+
cleanedUp = true; // skip cleanup so the user can recover
|
|
221
|
+
return 1;
|
|
222
|
+
}
|
|
223
|
+
// Structural diff so vim's trailing-newline doesn't trigger a false
|
|
224
|
+
// dirty (which would otherwise burn an event-source write for a
|
|
225
|
+
// semantic no-op).
|
|
226
|
+
const beforeKey = canonicalKey(result.data);
|
|
227
|
+
const afterKey = canonicalKey(parsed);
|
|
228
|
+
if (beforeKey === afterKey) {
|
|
229
|
+
process.stdout.write(dim("no changes.\n"));
|
|
230
|
+
return 0;
|
|
231
|
+
}
|
|
232
|
+
await applyGraph(name, parsed);
|
|
233
|
+
process.stdout.write(`${green("✓")} updated ${bold(name)}\n`);
|
|
234
|
+
return 0;
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
process.stderr.write(`${red("✗")} ${err.message}\n`);
|
|
238
|
+
return 1;
|
|
239
|
+
}
|
|
240
|
+
finally {
|
|
241
|
+
process.removeListener("SIGINT", onSig);
|
|
242
|
+
process.removeListener("SIGTERM", onSig);
|
|
243
|
+
await cleanup();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/** Canonical-form key used to detect semantic changes between two
|
|
247
|
+
* graph payloads. Stable property ordering, drop volatile metadata. */
|
|
248
|
+
function canonicalKey(data) {
|
|
249
|
+
const stripped = {
|
|
250
|
+
metadata: {
|
|
251
|
+
name: data.metadata?.name,
|
|
252
|
+
description: data.metadata?.description,
|
|
253
|
+
tags: [...(data.metadata?.tags ?? [])].sort(),
|
|
254
|
+
},
|
|
255
|
+
nodes: data.nodes,
|
|
256
|
+
edges: data.edges,
|
|
257
|
+
};
|
|
258
|
+
return stableStringify(stripped);
|
|
259
|
+
}
|
|
260
|
+
function stableStringify(v) {
|
|
261
|
+
if (v === null || typeof v !== "object")
|
|
262
|
+
return JSON.stringify(v);
|
|
263
|
+
if (Array.isArray(v))
|
|
264
|
+
return "[" + v.map(stableStringify).join(",") + "]";
|
|
265
|
+
const keys = Object.keys(v).sort();
|
|
266
|
+
return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(v[k])).join(",") + "}";
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=mutate.js.map
|