@openbkn/bkn-sdk 0.1.4 → 0.1.5-rc.1
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 +7 -9
- package/README.zh.md +2 -6
- package/dist/{chunk-Z2NRTUB3.js → chunk-WIYRGBAB.js} +367 -535
- package/dist/cli.js +1835 -422
- package/dist/index.d.ts +603 -151
- package/dist/index.js +3 -3
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
BuildTaskExecuteType,
|
|
3
4
|
BuildTaskSort,
|
|
4
5
|
BuildTaskStatus,
|
|
5
6
|
DEFAULT_BUSINESS_DOMAIN,
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
DiscoverStrategy,
|
|
10
11
|
DiscoverTaskSort,
|
|
11
12
|
DiscoverTaskTriggerType,
|
|
13
|
+
DryRunSignal,
|
|
12
14
|
HttpError,
|
|
13
15
|
InputError,
|
|
14
16
|
SemanticUnderstandingApplyMode,
|
|
@@ -27,6 +29,7 @@ import {
|
|
|
27
29
|
decodeJwt,
|
|
28
30
|
deletePlatform,
|
|
29
31
|
deviceLogin,
|
|
32
|
+
enableDryRun,
|
|
30
33
|
exportCreds,
|
|
31
34
|
filesUnder,
|
|
32
35
|
formatError,
|
|
@@ -50,24 +53,25 @@ import {
|
|
|
50
53
|
stringifyBigIntJSON,
|
|
51
54
|
switchUser,
|
|
52
55
|
toExitCode,
|
|
56
|
+
trimTrailingSlashes,
|
|
53
57
|
updatePlatformConfig,
|
|
54
58
|
use,
|
|
55
59
|
validateFixturePath,
|
|
56
60
|
whoami
|
|
57
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-WIYRGBAB.js";
|
|
58
62
|
|
|
59
|
-
// src/cli.ts
|
|
63
|
+
// src/cli-program.ts
|
|
60
64
|
import { Command as Command16 } from "commander";
|
|
61
65
|
|
|
62
66
|
// package.json
|
|
63
67
|
var package_default = {
|
|
64
68
|
name: "@openbkn/bkn-sdk",
|
|
65
|
-
version: "0.1.
|
|
69
|
+
version: "0.1.5-rc.1",
|
|
66
70
|
description: "Unified TypeScript SDK + CLI for the BKN (Business Knowledge Network) platform.",
|
|
67
71
|
type: "module",
|
|
68
72
|
license: "Apache-2.0",
|
|
69
73
|
engines: {
|
|
70
|
-
node: ">=
|
|
74
|
+
node: ">=22.19.0"
|
|
71
75
|
},
|
|
72
76
|
bin: {
|
|
73
77
|
openbkn: "./dist/cli.js"
|
|
@@ -94,6 +98,7 @@ var package_default = {
|
|
|
94
98
|
dev: "tsup --watch",
|
|
95
99
|
typecheck: "tsc --noEmit",
|
|
96
100
|
"check:deps": "node scripts/check-no-self-dep.mjs",
|
|
101
|
+
"capture:returns": "node scripts/capture-returns.mjs",
|
|
97
102
|
lint: "npm run check:deps && biome check . && tsc --noEmit",
|
|
98
103
|
format: "biome format --write .",
|
|
99
104
|
test: "vitest run",
|
|
@@ -131,14 +136,72 @@ import { Command as Command2 } from "commander";
|
|
|
131
136
|
|
|
132
137
|
// src/help/grouped-help.ts
|
|
133
138
|
var GROUP = /* @__PURE__ */ Symbol("openbkn.group");
|
|
139
|
+
var GUIDE = /* @__PURE__ */ Symbol("openbkn.guide");
|
|
134
140
|
var DEFAULT_GROUP = "COMMANDS";
|
|
135
141
|
function group(cmd, name) {
|
|
136
142
|
cmd[GROUP] = name;
|
|
137
143
|
return cmd;
|
|
138
144
|
}
|
|
145
|
+
function guide(cmd, text) {
|
|
146
|
+
cmd[GUIDE] = text;
|
|
147
|
+
return cmd;
|
|
148
|
+
}
|
|
149
|
+
var SECTION_ORDER = ["GROUPS", "READ", "RUN", "WRITE"];
|
|
150
|
+
function groupChildren(parent, sections) {
|
|
151
|
+
for (const [section, names] of Object.entries(sections)) {
|
|
152
|
+
for (const name of names) {
|
|
153
|
+
const child = parent.commands.find((c) => c.name() === name);
|
|
154
|
+
if (child) group(child, section);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
var VERB_SECTIONS = [
|
|
159
|
+
[
|
|
160
|
+
/^(list|get|show|find|files|history|members|roles|tree|names|content|read-file|status|whoami|users|detail|spans|graph|health|resources|search|market|market-get|stats|export|pull|validate-fixture)$/,
|
|
161
|
+
"READ"
|
|
162
|
+
],
|
|
163
|
+
[
|
|
164
|
+
/^(query|execute|debug|run|test|chat|embeddings|rerank|diagnose|scan|discover|build|dry-run|validate|token|download|install|call|sql|receipt|fingerprint|test-connection|test-connection-config|attempt|retry|start|resume|ensure-current|create-new-generation|close|complete|fail|cancel|handoff|operations|build-status|build-list)$/,
|
|
165
|
+
"RUN"
|
|
166
|
+
],
|
|
167
|
+
[
|
|
168
|
+
/^(create|update|delete|add|edit|remove|set|register|upload|publish|unpublish|republish|import|activate|login|logout|use|switch|change-password|enable|disable|push|assign-role|revoke-role|add-member|remove-member|reset-password|grant-perm|revoke-perm|add-members|remove-members|set-status|regenerate|revoke|set-bd|list-bd|build-start|build-stop|build-delete|publish-history|update-metadata|update-package|create-from-catalog|export-config)$/,
|
|
169
|
+
"WRITE"
|
|
170
|
+
]
|
|
171
|
+
];
|
|
172
|
+
function autoGroup(parent) {
|
|
173
|
+
for (const child of parent.commands) {
|
|
174
|
+
if (child.name().startsWith("help")) continue;
|
|
175
|
+
if (child[GROUP] !== void 0) continue;
|
|
176
|
+
if (child.commands.filter((c) => !c.name().startsWith("help")).length > 0) {
|
|
177
|
+
group(child, "GROUPS");
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const verb = VERB_SECTIONS.find(([re]) => re.test(child.name()));
|
|
181
|
+
if (verb) group(child, verb[1]);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function rankOf(name) {
|
|
185
|
+
if (name === DEFAULT_GROUP) return Number.MAX_SAFE_INTEGER;
|
|
186
|
+
const i = SECTION_ORDER.indexOf(name);
|
|
187
|
+
return i === -1 ? SECTION_ORDER.length : i;
|
|
188
|
+
}
|
|
139
189
|
function groupOf(cmd) {
|
|
140
190
|
return cmd[GROUP] ?? DEFAULT_GROUP;
|
|
141
191
|
}
|
|
192
|
+
var SECTION_MEANINGS = {
|
|
193
|
+
GROUPS: "nested command groups \u2014 one level deeper",
|
|
194
|
+
READ: "changes nothing",
|
|
195
|
+
RUN: "acts without changing configuration (triggers a job, spends a model call, rotates a token)",
|
|
196
|
+
WRITE: "changes platform state \u2014 confirm with a person first",
|
|
197
|
+
[DEFAULT_GROUP]: "not sorted into a section yet"
|
|
198
|
+
};
|
|
199
|
+
function sectionOf(cmd) {
|
|
200
|
+
return groupOf(cmd);
|
|
201
|
+
}
|
|
202
|
+
function guideOf(cmd) {
|
|
203
|
+
return cmd[GUIDE];
|
|
204
|
+
}
|
|
142
205
|
function formatHelp(cmd, helper) {
|
|
143
206
|
const out = [];
|
|
144
207
|
const desc = helper.commandDescription(cmd);
|
|
@@ -154,7 +217,8 @@ function formatHelp(cmd, helper) {
|
|
|
154
217
|
if (bucket) bucket.push(c);
|
|
155
218
|
else sections.set(g, [c]);
|
|
156
219
|
}
|
|
157
|
-
|
|
220
|
+
const ordered = [...sections.entries()].map((entry, index) => ({ entry, index })).sort((a, b) => rankOf(a.entry[0]) - rankOf(b.entry[0]) || a.index - b.index).map(({ entry }) => entry);
|
|
221
|
+
for (const [name, cmds] of ordered) {
|
|
158
222
|
out.push(name);
|
|
159
223
|
for (const c of cmds) {
|
|
160
224
|
out.push(` ${helper.subcommandTerm(c).padEnd(width)} ${helper.subcommandDescription(c)}`);
|
|
@@ -162,6 +226,8 @@ function formatHelp(cmd, helper) {
|
|
|
162
226
|
out.push("");
|
|
163
227
|
}
|
|
164
228
|
}
|
|
229
|
+
const extra = guideOf(cmd);
|
|
230
|
+
if (extra) out.push(extra.trim(), "");
|
|
165
231
|
const opts = helper.visibleOptions(cmd);
|
|
166
232
|
if (opts.length > 0) {
|
|
167
233
|
const width = Math.max(...opts.map((o) => helper.optionTerm(o).length));
|
|
@@ -174,11 +240,15 @@ function formatHelp(cmd, helper) {
|
|
|
174
240
|
return out.join("\n");
|
|
175
241
|
}
|
|
176
242
|
function installGroupedHelp(root) {
|
|
177
|
-
const apply = (cmd) => {
|
|
243
|
+
const apply = (cmd, path) => {
|
|
178
244
|
cmd.configureHelp({ formatHelp });
|
|
179
|
-
|
|
245
|
+
if (cmd !== root) autoGroup(cmd);
|
|
246
|
+
cmd.showHelpAfterError(
|
|
247
|
+
path.length ? `Run \`openbkn describe ${path.join(" ")}\` to see its arguments and where their ids come from.` : "Run `openbkn describe --depth 1` for every command, or `openbkn --help` for the guide."
|
|
248
|
+
);
|
|
249
|
+
for (const child of cmd.commands) apply(child, [...path, child.name()]);
|
|
180
250
|
};
|
|
181
|
-
apply(root);
|
|
251
|
+
apply(root, []);
|
|
182
252
|
}
|
|
183
253
|
|
|
184
254
|
// src/utils/org-tree.ts
|
|
@@ -206,12 +276,12 @@ function printJson(value, opts = {}) {
|
|
|
206
276
|
process.stdout.write("(ok)\n");
|
|
207
277
|
return;
|
|
208
278
|
}
|
|
209
|
-
const
|
|
210
|
-
if (
|
|
211
|
-
const fullColumns = columnsOf(
|
|
212
|
-
const columns = opts.full ? fullColumns : selectColumns(
|
|
279
|
+
const rows2 = toRows(value);
|
|
280
|
+
if (rows2) {
|
|
281
|
+
const fullColumns = columnsOf(rows2).filter((c) => rows2.some((r) => stringifyCell(r[c]) !== ""));
|
|
282
|
+
const columns = opts.full ? fullColumns : selectColumns(rows2);
|
|
213
283
|
if (columns.length > 0) {
|
|
214
|
-
printTable(
|
|
284
|
+
printTable(rows2, columns);
|
|
215
285
|
const hidden = fullColumns.length - columns.length;
|
|
216
286
|
if (hidden > 0 && !opts.full) {
|
|
217
287
|
process.stdout.write(`\u2026 ${hidden} more column(s); use --full or --json for everything
|
|
@@ -257,9 +327,9 @@ function toRows(value) {
|
|
|
257
327
|
}
|
|
258
328
|
return null;
|
|
259
329
|
}
|
|
260
|
-
function columnsOf(
|
|
330
|
+
function columnsOf(rows2) {
|
|
261
331
|
const seen = [];
|
|
262
|
-
for (const row of
|
|
332
|
+
for (const row of rows2) {
|
|
263
333
|
for (const k of Object.keys(row)) if (!seen.includes(k)) seen.push(k);
|
|
264
334
|
}
|
|
265
335
|
return seen;
|
|
@@ -280,16 +350,16 @@ var NOISE_COLS = /* @__PURE__ */ new Set([
|
|
|
280
350
|
]);
|
|
281
351
|
var isNoiseCol = (c) => NOISE_COLS.has(c) || /_time$/.test(c);
|
|
282
352
|
var isKeyCol = (c) => /^(id|name|key|title|label)$/i.test(c) || /_(id|name|key)$/i.test(c) || /^(status|state|type|category|mode|enabled|version|branch)$/i.test(c);
|
|
283
|
-
function selectColumns(
|
|
353
|
+
function selectColumns(rows2) {
|
|
284
354
|
const isObj = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
285
|
-
const kept = columnsOf(
|
|
355
|
+
const kept = columnsOf(rows2).filter((c) => {
|
|
286
356
|
if (isNoiseCol(c)) return false;
|
|
287
|
-
const vals =
|
|
357
|
+
const vals = rows2.map((r) => r[c]);
|
|
288
358
|
if (!vals.some((v) => stringifyCell(v) !== "")) return false;
|
|
289
359
|
if (vals.every((v) => v === null || v === void 0 || isObj(v))) return false;
|
|
290
360
|
return true;
|
|
291
361
|
});
|
|
292
|
-
const isLongText = (c) =>
|
|
362
|
+
const isLongText = (c) => rows2.every((r) => {
|
|
293
363
|
const s = stringifyCell(r[c]);
|
|
294
364
|
return s === "" || s.length >= CELL_MAX - 1;
|
|
295
365
|
});
|
|
@@ -297,12 +367,12 @@ function selectColumns(rows) {
|
|
|
297
367
|
const ordered = kept.map((c, i) => ({ c, i, r: rank(c) })).sort((a, b) => a.r - b.r || a.i - b.i).map((x) => x.c);
|
|
298
368
|
return ordered.slice(0, MAX_COLS);
|
|
299
369
|
}
|
|
300
|
-
function printTable(
|
|
370
|
+
function printTable(rows2, columns, opts = {}) {
|
|
301
371
|
if (opts.json || opts.compact) {
|
|
302
|
-
printJson(
|
|
372
|
+
printJson(rows2, opts);
|
|
303
373
|
return;
|
|
304
374
|
}
|
|
305
|
-
const cells =
|
|
375
|
+
const cells = rows2.map((row) => columns.map((c) => stringifyCell(row[c])));
|
|
306
376
|
const widths = columns.map(
|
|
307
377
|
(col, i) => Math.max(displayWidth(col), ...cells.map((r) => displayWidth(r[i] ?? "")))
|
|
308
378
|
);
|
|
@@ -331,7 +401,7 @@ function stringifyCell(v) {
|
|
|
331
401
|
// src/utils/prompt.ts
|
|
332
402
|
import { createInterface } from "readline";
|
|
333
403
|
function promptLine(query, hidden = false) {
|
|
334
|
-
return new Promise((
|
|
404
|
+
return new Promise((resolve3) => {
|
|
335
405
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
336
406
|
if (hidden) {
|
|
337
407
|
const mutable = rl;
|
|
@@ -342,7 +412,7 @@ function promptLine(query, hidden = false) {
|
|
|
342
412
|
rl.question(query, (answer) => {
|
|
343
413
|
rl.close();
|
|
344
414
|
if (hidden) process.stdout.write("\n");
|
|
345
|
-
|
|
415
|
+
resolve3(answer.trim());
|
|
346
416
|
});
|
|
347
417
|
});
|
|
348
418
|
}
|
|
@@ -351,7 +421,7 @@ function promptLine(query, hidden = false) {
|
|
|
351
421
|
import { readFileSync } from "fs";
|
|
352
422
|
function platformOf(o) {
|
|
353
423
|
const baseUrl = (typeof o.baseUrl === "string" ? o.baseUrl : void 0) ?? process.env.BKN_BASE_URL ?? activePlatform();
|
|
354
|
-
return baseUrl
|
|
424
|
+
return baseUrl === void 0 ? void 0 : trimTrailingSlashes(baseUrl);
|
|
355
425
|
}
|
|
356
426
|
function transientIdentity(o) {
|
|
357
427
|
return Boolean(o.user || process.env.BKN_USER || o.token || process.env.BKN_TOKEN);
|
|
@@ -576,16 +646,16 @@ User code: ${userCode}
|
|
|
576
646
|
}
|
|
577
647
|
const expMs = typeof me.exp === "number" ? me.exp * 1e3 : void 0;
|
|
578
648
|
const expired = expMs !== void 0 && expMs < Date.now();
|
|
579
|
-
const
|
|
649
|
+
const rows2 = [
|
|
580
650
|
["User", String(me.username ?? me.sub ?? "(unknown)")],
|
|
581
651
|
...me.name && me.name !== me.username ? [["Name", String(me.name)]] : [],
|
|
582
652
|
["ID", String(me.userId ?? me.sub ?? "-")],
|
|
583
653
|
["Platform", String(me.baseUrl ?? "-")],
|
|
584
654
|
...expMs !== void 0 ? [["Expires", `${new Date(expMs).toISOString()}${expired ? " (expired)" : ""}`]] : []
|
|
585
655
|
];
|
|
586
|
-
const pad2 = Math.max(...
|
|
656
|
+
const pad2 = Math.max(...rows2.map(([k]) => k.length));
|
|
587
657
|
process.stdout.write(
|
|
588
|
-
`${
|
|
658
|
+
`${rows2.map(([k, v]) => `${k.padEnd(pad2)} ${v}`).join("\n")}
|
|
589
659
|
\u2026 use --full or --json for all claims
|
|
590
660
|
`
|
|
591
661
|
);
|
|
@@ -613,7 +683,7 @@ User code: ${userCode}
|
|
|
613
683
|
`);
|
|
614
684
|
});
|
|
615
685
|
cmd.command("users <url>").description("List saved users for a platform (* = active)").action((url, _opts, cmd2) => {
|
|
616
|
-
const norm = url
|
|
686
|
+
const norm = trimTrailingSlashes(url);
|
|
617
687
|
const items = listPlatforms().filter((i) => i.baseUrl === norm);
|
|
618
688
|
const out = outputOptions(cmd2);
|
|
619
689
|
if (out.json || out.compact) printJson(items, out);
|
|
@@ -657,9 +727,33 @@ User code: ${userCode}
|
|
|
657
727
|
});
|
|
658
728
|
}
|
|
659
729
|
function authCommand() {
|
|
660
|
-
const cmd = new Command("auth").description("
|
|
730
|
+
const cmd = new Command("auth").description("Log in; the token is saved and reused. Start here.");
|
|
661
731
|
registerAuthLeaves(cmd);
|
|
662
|
-
|
|
732
|
+
groupChildren(cmd, {
|
|
733
|
+
READ: ["status", "whoami", "list", "users"],
|
|
734
|
+
RUN: ["token", "export"],
|
|
735
|
+
WRITE: ["login", "logout", "use", "switch", "delete", "change-password"]
|
|
736
|
+
});
|
|
737
|
+
guide(
|
|
738
|
+
cmd,
|
|
739
|
+
`WAYS IN
|
|
740
|
+
login <url> -u <user> -p <pass> password, no browser
|
|
741
|
+
login <url> --token <token> a token you already hold (CI)
|
|
742
|
+
login <url> --device device code, for a host with no browser
|
|
743
|
+
login <url> opens a browser; --no-browser prints the URL instead
|
|
744
|
+
|
|
745
|
+
MANY PLATFORMS, MANY USERS
|
|
746
|
+
A session is a platform plus a user. \`use <url>\` changes which platform is
|
|
747
|
+
active; \`switch <url> <user>\` changes which saved user is active on one.
|
|
748
|
+
\`list\` shows both, marking the active pair. \`--user\` on any command borrows a
|
|
749
|
+
saved user for that call alone.
|
|
750
|
+
|
|
751
|
+
TOKENS
|
|
752
|
+
\`token\` prints the access token, refreshing it first if it has expired;
|
|
753
|
+
\`--no-refresh\` prints what is stored. \`export\` hands the whole session to a
|
|
754
|
+
headless host. Both write a secret to stdout.`
|
|
755
|
+
);
|
|
756
|
+
return group(cmd, "SIGN IN & SETTINGS");
|
|
663
757
|
}
|
|
664
758
|
|
|
665
759
|
// src/commands/admin.ts
|
|
@@ -672,10 +766,10 @@ async function importLicenseFile(cmd, file, receipt) {
|
|
|
672
766
|
if ("stored" in res && res.stored) process.exitCode = 1;
|
|
673
767
|
}
|
|
674
768
|
function adminCommand() {
|
|
675
|
-
const admin = new Command2("admin").description("
|
|
769
|
+
const admin = new Command2("admin").description("Orgs, users, roles, license, audit log");
|
|
676
770
|
registerAuthLeaves(admin.command("auth").description("Operator authentication"));
|
|
677
771
|
const org = admin.command("org").description("Departments and org structure");
|
|
678
|
-
org.command("list").description("List departments").option("--role <r>", "role qualifier", "super_admin").option("--name <s>", "filter by name").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).action(async (opts, cmd) => {
|
|
772
|
+
org.command("list").description("List departments \u2192 {departments, total}").option("--role <r>", "role qualifier", "super_admin").option("--name <s>", "filter by name").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).action(async (opts, cmd) => {
|
|
679
773
|
printJson(
|
|
680
774
|
await clientFrom(cmd).admin.orgList({
|
|
681
775
|
role: opts.role,
|
|
@@ -736,7 +830,7 @@ function adminCommand() {
|
|
|
736
830
|
else console.log(renderOrgTree(tree));
|
|
737
831
|
});
|
|
738
832
|
const user = admin.command("user").description("User management");
|
|
739
|
-
user.command("list").description("List users").option("--org <id>", "filter by department id").option("--keyword <s>", "filter by name").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).action(async (opts, cmd) => {
|
|
833
|
+
user.command("list").description("List users \u2192 {users, total}").option("--org <id>", "filter by department id").option("--keyword <s>", "filter by name").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).action(async (opts, cmd) => {
|
|
740
834
|
printJson(
|
|
741
835
|
await clientFrom(cmd).admin.userList({
|
|
742
836
|
orgId: opts.org,
|
|
@@ -822,7 +916,7 @@ function adminCommand() {
|
|
|
822
916
|
);
|
|
823
917
|
});
|
|
824
918
|
const role = admin.command("role").description("Role management");
|
|
825
|
-
role.command("list").description("List roles").option("--keyword <s>", "filter by keyword").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).option("--source <s>", "role source filter (business | user)").action(async (opts, cmd) => {
|
|
919
|
+
role.command("list").description("List roles \u2192 {roles}").option("--keyword <s>", "filter by keyword").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).option("--source <s>", "role source filter (business | user)").action(async (opts, cmd) => {
|
|
826
920
|
printJson(
|
|
827
921
|
await clientFrom(cmd).admin.roleList({ keyword: opts.keyword, limit: opts.limit }),
|
|
828
922
|
outputOptions(cmd)
|
|
@@ -924,7 +1018,10 @@ function adminCommand() {
|
|
|
924
1018
|
m.command("get <modelid>").description(`Get a ${kind} model`).action(async (id, _opts, cmd) => {
|
|
925
1019
|
printJson(await clientFrom(cmd).models[ns].get(id), outputOptions(cmd));
|
|
926
1020
|
});
|
|
927
|
-
const add = m.command("add").description(`Register a ${kind} model (granular flags or --body/--body-file)`).option("--name <s>", "model name").option("--api-model <s>", "upstream API model id").option("--api-key <s>", "upstream API key").option(
|
|
1021
|
+
const add = m.command("add").description(`Register a ${kind} model (granular flags or --body/--body-file)`).option("--name <s>", "model name").option("--api-model <s>", "upstream API model id").option("--api-key <s>", "upstream API key").option(
|
|
1022
|
+
"--body <json>",
|
|
1023
|
+
"model config JSON (overrides flags) \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (mf-model-manager)"
|
|
1024
|
+
).option("--body-file <path>", "read config JSON from a file");
|
|
928
1025
|
if (isLlm) {
|
|
929
1026
|
add.option("--series <s>", "model series").option("--api-base <url>", "upstream API base URL").option("--icon <url>", "icon URL");
|
|
930
1027
|
} else {
|
|
@@ -933,7 +1030,10 @@ function adminCommand() {
|
|
|
933
1030
|
add.action(async (opts, cmd) => {
|
|
934
1031
|
printJson(await clientFrom(cmd).models[ns].add(modelBody(opts)), outputOptions(cmd));
|
|
935
1032
|
});
|
|
936
|
-
const edit = m.command("edit <modelid>").description(`Edit a ${kind} model (granular flags or --body/--body-file)`).option("--name <s>", "model name").option(
|
|
1033
|
+
const edit = m.command("edit <modelid>").description(`Edit a ${kind} model (granular flags or --body/--body-file)`).option("--name <s>", "model name").option(
|
|
1034
|
+
"--body <json>",
|
|
1035
|
+
"model config JSON (overrides flags) \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (mf-model-manager)"
|
|
1036
|
+
).option("--body-file <path>", "read config JSON from a file");
|
|
937
1037
|
if (isLlm) {
|
|
938
1038
|
edit.option("--icon <url>", "icon URL");
|
|
939
1039
|
} else {
|
|
@@ -948,7 +1048,10 @@ function adminCommand() {
|
|
|
948
1048
|
m.command("delete <modelid...>").description(`Delete ${kind} model(s)`).action(async (ids, _opts, cmd) => {
|
|
949
1049
|
printJson(await clientFrom(cmd).models[ns].delete(ids), outputOptions(cmd));
|
|
950
1050
|
});
|
|
951
|
-
m.command("test <modelid>").description(`Test a ${kind} model`).option(
|
|
1051
|
+
m.command("test <modelid>").description(`Test a ${kind} model`).option(
|
|
1052
|
+
"--body <json>",
|
|
1053
|
+
"test request JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (mf-model-manager)"
|
|
1054
|
+
).option("--body-file <path>", "read test request JSON from a file").action(async (id, opts, cmd) => {
|
|
952
1055
|
const body = opts.body || opts.bodyFile ? readBody(opts) : {};
|
|
953
1056
|
printJson(
|
|
954
1057
|
await clientFrom(cmd).models[ns].test({ model_id: id, ...body }),
|
|
@@ -997,10 +1100,12 @@ function adminCommand() {
|
|
|
997
1100
|
if (key !== "baseUrl") {
|
|
998
1101
|
throw new Error(`Unknown config key: ${key} (only baseUrl supported)`);
|
|
999
1102
|
}
|
|
1000
|
-
setActivePlatform(value
|
|
1103
|
+
setActivePlatform(trimTrailingSlashes(value));
|
|
1001
1104
|
printJson({ ok: true, baseUrl: value }, outputOptions(cmd));
|
|
1002
1105
|
});
|
|
1003
|
-
admin.command("call <url>").description(
|
|
1106
|
+
admin.command("call <url>").description(
|
|
1107
|
+
"Operator API passthrough (curl-style; auto-injected auth) \u2014 paths at https://openbkn-ai.github.io/bkn-foundry/"
|
|
1108
|
+
).option("-X, --request <method>", "HTTP method").option(
|
|
1004
1109
|
"-H, --header <header>",
|
|
1005
1110
|
'extra header "Name: value" (repeatable)',
|
|
1006
1111
|
(v, a) => {
|
|
@@ -1030,125 +1135,16 @@ function adminCommand() {
|
|
|
1030
1135
|
}
|
|
1031
1136
|
if (res.status >= 400) process.exitCode = 1;
|
|
1032
1137
|
});
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
// src/commands/agent.ts
|
|
1037
|
-
import { Command as Command3 } from "commander";
|
|
1038
|
-
var int2 = (v) => Number.parseInt(v, 10);
|
|
1039
|
-
function agentCommand() {
|
|
1040
|
-
const cmd = new Command3("agent").description(
|
|
1041
|
-
"[DEPRECATED] Decision Agent \u2014 CRUD, chat, sessions, publish (being phased out)"
|
|
1042
|
-
);
|
|
1043
|
-
cmd.hook("preAction", () => {
|
|
1044
|
-
process.stderr.write(
|
|
1045
|
-
"\u26A0\uFE0F `openbkn agent` is deprecated and may be removed in a future release.\n"
|
|
1046
|
-
);
|
|
1047
|
-
});
|
|
1048
|
-
cmd.command("list").description("List published agents").option("--name <s>", "filter by name").option("--limit <n>", "page size", int2, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int2, 0).option("--category-id <id>", "filter by category").action(async (opts, cmd2) => {
|
|
1049
|
-
const data = await clientFrom(cmd2).agents.list({
|
|
1050
|
-
name: opts.name,
|
|
1051
|
-
limit: opts.limit,
|
|
1052
|
-
offset: opts.offset,
|
|
1053
|
-
categoryId: opts.categoryId
|
|
1054
|
-
});
|
|
1055
|
-
printJson(data, outputOptions(cmd2));
|
|
1056
|
-
});
|
|
1057
|
-
cmd.command("personal-list").description("List personal-space agents").option("--name <s>", "filter by name").option("--limit <n>", "page size", int2, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int2, 0).action(async (opts, cmd2) => {
|
|
1058
|
-
const data = await clientFrom(cmd2).agents.personalList({
|
|
1059
|
-
name: opts.name,
|
|
1060
|
-
limit: opts.limit,
|
|
1061
|
-
offset: opts.offset
|
|
1062
|
-
});
|
|
1063
|
-
printJson(data, outputOptions(cmd2));
|
|
1064
|
-
});
|
|
1065
|
-
cmd.command("category-list").description("List agent categories").action(async (_opts, cmd2) => {
|
|
1066
|
-
printJson(await clientFrom(cmd2).agents.categoryList(), outputOptions(cmd2));
|
|
1067
|
-
});
|
|
1068
|
-
cmd.command("template-list").description("List published agent templates").option("--name <s>", "filter by name").option("--limit <n>", "page size", int2, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int2, 0).action(async (opts, cmd2) => {
|
|
1069
|
-
const data = await clientFrom(cmd2).agents.templateList({
|
|
1070
|
-
name: opts.name,
|
|
1071
|
-
limit: opts.limit,
|
|
1072
|
-
offset: opts.offset
|
|
1073
|
-
});
|
|
1074
|
-
printJson(data, outputOptions(cmd2));
|
|
1075
|
-
});
|
|
1076
|
-
cmd.command("template-get <id>").description("Get a published agent template").action(async (id, _opts, cmd2) => {
|
|
1077
|
-
printJson(await clientFrom(cmd2).agents.templateGet(id), outputOptions(cmd2));
|
|
1078
|
-
});
|
|
1079
|
-
cmd.command("get <id>").description("Get agent details").action(async (id, _opts, cmd2) => {
|
|
1080
|
-
printJson(await clientFrom(cmd2).agents.get(id), outputOptions(cmd2));
|
|
1081
|
-
});
|
|
1082
|
-
cmd.command("get-by-key <key>").description("Get an agent by key").action(async (key, _opts, cmd2) => {
|
|
1083
|
-
printJson(await clientFrom(cmd2).agents.getByKey(key), outputOptions(cmd2));
|
|
1084
|
-
});
|
|
1085
|
-
cmd.command("create").description("Create an agent (--body-file <json> or --body '<json>')").option("--body <json>", "agent definition JSON").option("--body-file <path>", "read agent definition JSON from a file").action(async (opts, cmd2) => {
|
|
1086
|
-
printJson(await clientFrom(cmd2).agents.create(readBody(opts)), outputOptions(cmd2));
|
|
1087
|
-
});
|
|
1088
|
-
cmd.command("update <id>").description("Update an agent (--body-file <json> or --body '<json>')").option("--body <json>", "agent definition JSON").option("--body-file <path>", "read agent definition JSON from a file").action(async (id, opts, cmd2) => {
|
|
1089
|
-
printJson(await clientFrom(cmd2).agents.update(id, readBody(opts)), outputOptions(cmd2));
|
|
1138
|
+
groupChildren(admin, {
|
|
1139
|
+
GROUPS: ["org", "user", "role", "llm", "small-model", "license", "audit", "auth", "config"],
|
|
1140
|
+
RUN: ["call"]
|
|
1090
1141
|
});
|
|
1091
|
-
|
|
1092
|
-
printJson(await clientFrom(cmd2).agents.delete(id), outputOptions(cmd2));
|
|
1093
|
-
});
|
|
1094
|
-
cmd.command("publish <id>").description("Publish an agent").action(async (id, _opts, cmd2) => {
|
|
1095
|
-
printJson(await clientFrom(cmd2).agents.publish(id), outputOptions(cmd2));
|
|
1096
|
-
});
|
|
1097
|
-
cmd.command("unpublish <id>").description("Unpublish an agent").action(async (id, _opts, cmd2) => {
|
|
1098
|
-
printJson(await clientFrom(cmd2).agents.unpublish(id), outputOptions(cmd2));
|
|
1099
|
-
});
|
|
1100
|
-
cmd.command("sessions <agent>").description("List conversations for an agent (by agent key)").option("--limit <n>", "page size", int2, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int2, 1).action(async (agentKey, opts, cmd2) => {
|
|
1101
|
-
printJson(
|
|
1102
|
-
await clientFrom(cmd2).agents.sessions(agentKey, { size: opts.limit, page: opts.page }),
|
|
1103
|
-
outputOptions(cmd2)
|
|
1104
|
-
);
|
|
1105
|
-
});
|
|
1106
|
-
cmd.command("history <agent> <conversation-id>").description("Show message history for a conversation").action(async (agentKey, conversationId, _opts, cmd2) => {
|
|
1107
|
-
printJson(await clientFrom(cmd2).agents.history(agentKey, conversationId), outputOptions(cmd2));
|
|
1108
|
-
});
|
|
1109
|
-
cmd.command("chat <agent-id>").description("Chat with an agent (SSE streaming with --stream)").requiredOption("-m, --message <text>", "user message").option("--version <v>", "agent version", "v0").option("--conversation-id <id>", "continue an existing conversation").option("--stream", "stream the reply to stdout as it arrives").action(async (agentId, opts, cmd2) => {
|
|
1110
|
-
const client = clientFrom(cmd2);
|
|
1111
|
-
if (opts.stream) {
|
|
1112
|
-
const res = await client.agents.chat(agentId, opts.message, {
|
|
1113
|
-
version: opts.version,
|
|
1114
|
-
conversationId: opts.conversationId,
|
|
1115
|
-
stream: true,
|
|
1116
|
-
onDelta: (t) => process.stdout.write(t)
|
|
1117
|
-
});
|
|
1118
|
-
process.stdout.write("\n");
|
|
1119
|
-
if (res.conversationId) console.error(`conversation_id: ${res.conversationId}`);
|
|
1120
|
-
return;
|
|
1121
|
-
}
|
|
1122
|
-
printJson(
|
|
1123
|
-
await client.agents.chat(agentId, opts.message, {
|
|
1124
|
-
version: opts.version,
|
|
1125
|
-
conversationId: opts.conversationId
|
|
1126
|
-
}),
|
|
1127
|
-
outputOptions(cmd2)
|
|
1128
|
-
);
|
|
1129
|
-
});
|
|
1130
|
-
cmd.command("trace <conversation-id>").description("Get trace spans for a conversation (agent-scoped alias of `trace get`)").action(async (conversationId, _opts, cmd2) => {
|
|
1131
|
-
printJson(await clientFrom(cmd2).trace.spans(conversationId), outputOptions(cmd2));
|
|
1132
|
-
});
|
|
1133
|
-
const skill = cmd.command("skill").description("Manage skills attached to an agent");
|
|
1134
|
-
skill.command("list <agent-id>").description("List skill ids attached to an agent").action(async (agentId, _opts, cmd2) => {
|
|
1135
|
-
printJson(await clientFrom(cmd2).agents.skillList(agentId), outputOptions(cmd2));
|
|
1136
|
-
});
|
|
1137
|
-
skill.command("add <agent-id> <skill-ids>").description("Attach skill(s) to an agent (comma-joined ids)").action(async (agentId, ids, _opts, cmd2) => {
|
|
1138
|
-
printJson(await clientFrom(cmd2).agents.skillAdd(agentId, csv(ids) ?? []), outputOptions(cmd2));
|
|
1139
|
-
});
|
|
1140
|
-
skill.command("remove <agent-id> <skill-ids>").description("Detach skill(s) from an agent (comma-joined ids)").action(async (agentId, ids, _opts, cmd2) => {
|
|
1141
|
-
printJson(
|
|
1142
|
-
await clientFrom(cmd2).agents.skillRemove(agentId, csv(ids) ?? []),
|
|
1143
|
-
outputOptions(cmd2)
|
|
1144
|
-
);
|
|
1145
|
-
});
|
|
1146
|
-
return group(cmd, "DECISION AGENT");
|
|
1142
|
+
return group(admin, "ADMINISTRATION");
|
|
1147
1143
|
}
|
|
1148
1144
|
|
|
1149
1145
|
// src/commands/appkey.ts
|
|
1150
|
-
import { Command as
|
|
1151
|
-
var
|
|
1146
|
+
import { Command as Command3 } from "commander";
|
|
1147
|
+
var int2 = (v) => Number.parseInt(v, 10);
|
|
1152
1148
|
var DAY_MS = 864e5;
|
|
1153
1149
|
function printNewKey(created, out) {
|
|
1154
1150
|
if (out.json || out.compact) {
|
|
@@ -1170,13 +1166,13 @@ function printNewKey(created, out) {
|
|
|
1170
1166
|
`);
|
|
1171
1167
|
}
|
|
1172
1168
|
function appkeyCommand() {
|
|
1173
|
-
const appkey = new
|
|
1174
|
-
"
|
|
1169
|
+
const appkey = new Command3("appkey").description(
|
|
1170
|
+
"Issue long-lived `bak_` keys for scripts and services"
|
|
1175
1171
|
);
|
|
1176
|
-
appkey.command("list").description("List your own AppKeys
|
|
1172
|
+
appkey.command("list").description("List your own AppKeys, no secrets \u2192 {keys}").action(async (_opts, cmd) => {
|
|
1177
1173
|
printJson(await clientFrom(cmd).appKeys.list(), outputOptions(cmd));
|
|
1178
1174
|
});
|
|
1179
|
-
appkey.command("create").description("Issue an AppKey \u2014 the plaintext key is shown ONCE, on create").requiredOption("--name <s>", "display name (to tell keys apart)").option("--expires-at <rfc3339>", "expiry as RFC3339 (e.g. 2027-01-01T00:00:00Z)").option("--expire-days <n>", "expiry in N days from now (alternative to --expires-at)",
|
|
1175
|
+
appkey.command("create").description("Issue an AppKey \u2014 the plaintext key is shown ONCE, on create").requiredOption("--name <s>", "display name (to tell keys apart)").option("--expires-at <rfc3339>", "expiry as RFC3339 (e.g. 2027-01-01T00:00:00Z)").option("--expire-days <n>", "expiry in N days from now (alternative to --expires-at)", int2).option("--never-expire", "never expire (wins over --expires-at/--expire-days)").action(async (opts, cmd) => {
|
|
1180
1176
|
let expiresAt = opts.expiresAt;
|
|
1181
1177
|
if (opts.expireDays !== void 0) {
|
|
1182
1178
|
if (!Number.isFinite(opts.expireDays) || opts.expireDays <= 0) {
|
|
@@ -1210,11 +1206,18 @@ function appkeyCommand() {
|
|
|
1210
1206
|
await clientFrom(cmd).appKeys.adminRevoke(id);
|
|
1211
1207
|
printJson({ revoked: id }, outputOptions(cmd));
|
|
1212
1208
|
});
|
|
1213
|
-
|
|
1209
|
+
groupChildren(appkey, {
|
|
1210
|
+
GROUPS: ["admin"],
|
|
1211
|
+
READ: ["list"],
|
|
1212
|
+
WRITE: ["create", "regenerate", "revoke"]
|
|
1213
|
+
});
|
|
1214
|
+
const appkeyAdmin = appkey.commands.find((c) => c.name() === "admin");
|
|
1215
|
+
if (appkeyAdmin) groupChildren(appkeyAdmin, { READ: ["list"], WRITE: ["revoke"] });
|
|
1216
|
+
return group(appkey, "SIGN IN & SETTINGS");
|
|
1214
1217
|
}
|
|
1215
1218
|
|
|
1216
1219
|
// src/commands/bkn.ts
|
|
1217
|
-
import { Command as
|
|
1220
|
+
import { Command as Command4 } from "commander";
|
|
1218
1221
|
|
|
1219
1222
|
// src/utils/bkn-validate.ts
|
|
1220
1223
|
import { existsSync, readFileSync as readFileSync3, readdirSync, statSync } from "fs";
|
|
@@ -1332,10 +1335,12 @@ function validateBknDirectory(dirPath) {
|
|
|
1332
1335
|
}
|
|
1333
1336
|
|
|
1334
1337
|
// src/commands/bkn.ts
|
|
1335
|
-
var
|
|
1338
|
+
var int3 = (v) => Number.parseInt(v, 10);
|
|
1336
1339
|
function bknCommand() {
|
|
1337
|
-
const bkn = new
|
|
1338
|
-
|
|
1340
|
+
const bkn = new Command4("bkn").description(
|
|
1341
|
+
"Knowledge networks: schema, metrics, search, import/export"
|
|
1342
|
+
);
|
|
1343
|
+
bkn.command("list").description("List knowledge networks").option("--limit <n>", "page size", int3, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int3, 0).option("--name-pattern <s>", "filter by name pattern").option("--tag <s>", "filter by tag").option("--sort <field>", "sort field", "update_time").option("--direction <dir>", "asc | desc", "desc").action(async (_opts, cmd) => {
|
|
1339
1344
|
const o = cmd.optsWithGlobals();
|
|
1340
1345
|
const data = await clientFrom(cmd).kn.list({
|
|
1341
1346
|
limit: o.limit,
|
|
@@ -1354,10 +1359,17 @@ function bknCommand() {
|
|
|
1354
1359
|
});
|
|
1355
1360
|
printJson(data, outputOptions(cmd));
|
|
1356
1361
|
});
|
|
1357
|
-
bkn.command("search <kn-id> <query>").description(
|
|
1362
|
+
bkn.command("search <kn-id> <query>").description(
|
|
1363
|
+
"Recall instances from a plain sentence \u2014 no object type or field names needed \u2192 {nodes, object_types}"
|
|
1364
|
+
).option("--object-types <ids>", "pin recall to these object-type ids (comma-separated)").option("--exclude-object-types <ids>", "drop these object-type ids (comma-separated)").option("--concept-groups <names>", "limit recall to these concept groups (comma-separated)").option("--max-object-types <n>", "how many object types may take part", int3).option("--max-instances <n>", "instances per object type", int3).option("--rerank", "re-rank hits with a cross-encoder (needs a rerank model deployed)").option("--no-object-types-detail", "omit the object-type definitions that come with hits").action(async (knId, query, opts, cmd) => {
|
|
1358
1365
|
const data = await clientFrom(cmd).kn.search(knId, query, {
|
|
1359
|
-
|
|
1360
|
-
|
|
1366
|
+
objectTypes: csv(opts.objectTypes),
|
|
1367
|
+
excludeObjectTypes: csv(opts.excludeObjectTypes),
|
|
1368
|
+
conceptGroups: csv(opts.conceptGroups),
|
|
1369
|
+
maxObjectTypes: opts.maxObjectTypes,
|
|
1370
|
+
maxInstancesPerType: opts.maxInstances,
|
|
1371
|
+
rerank: opts.rerank,
|
|
1372
|
+
includeObjectTypes: opts.objectTypesDetail === false ? false : void 0
|
|
1361
1373
|
});
|
|
1362
1374
|
printJson(data, outputOptions(cmd));
|
|
1363
1375
|
});
|
|
@@ -1375,16 +1387,22 @@ function bknCommand() {
|
|
|
1375
1387
|
);
|
|
1376
1388
|
});
|
|
1377
1389
|
if (crud) {
|
|
1378
|
-
g.command("get <kn-id> <id>").description(`Get ${name}`).action(async (knId, id, _o, cmd) => {
|
|
1390
|
+
g.command("get <kn-id> <id>").description(`Get ${name} \u2192 {entries}`).action(async (knId, id, _o, cmd) => {
|
|
1379
1391
|
printJson(await clientFrom(cmd).kn[`${crud}Get`](knId, id), outputOptions(cmd));
|
|
1380
1392
|
});
|
|
1381
|
-
g.command("create <kn-id>").description(`Create ${name} (--body / --body-file)`).option(
|
|
1393
|
+
g.command("create <kn-id>").description(`Create ${name} (--body / --body-file)`).option(
|
|
1394
|
+
"--body <json>",
|
|
1395
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1396
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, opts, cmd) => {
|
|
1382
1397
|
printJson(
|
|
1383
1398
|
await clientFrom(cmd).kn[`${crud}Create`](knId, readBody(opts)),
|
|
1384
1399
|
outputOptions(cmd)
|
|
1385
1400
|
);
|
|
1386
1401
|
});
|
|
1387
|
-
g.command("update <kn-id> <id>").description(`Update ${name} (--body / --body-file)`).option(
|
|
1402
|
+
g.command("update <kn-id> <id>").description(`Update ${name} (--body / --body-file)`).option(
|
|
1403
|
+
"--body <json>",
|
|
1404
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1405
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, id, opts, cmd) => {
|
|
1388
1406
|
printJson(
|
|
1389
1407
|
await clientFrom(cmd).kn[`${crud}Update`](knId, id, readBody(opts)),
|
|
1390
1408
|
outputOptions(cmd)
|
|
@@ -1396,21 +1414,24 @@ function bknCommand() {
|
|
|
1396
1414
|
}
|
|
1397
1415
|
}
|
|
1398
1416
|
const actionType = bkn.commands.find((c) => c.name() === "action-type");
|
|
1399
|
-
actionType?.command("query <kn-id> <at-id>").description("Query an action type (--body / --body-file JSON)").option(
|
|
1417
|
+
actionType?.command("query <kn-id> <at-id>").description("Query an action type (--body / --body-file JSON)").option(
|
|
1418
|
+
"--body <json>",
|
|
1419
|
+
"query JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1420
|
+
).option("--body-file <path>", "read query JSON from a file").action(async (knId, atId, opts, cmd) => {
|
|
1400
1421
|
printJson(
|
|
1401
1422
|
await clientFrom(cmd).kn.actionTypeQuery(knId, atId, readBody(opts)),
|
|
1402
1423
|
outputOptions(cmd)
|
|
1403
1424
|
);
|
|
1404
1425
|
});
|
|
1405
|
-
actionType?.command("execute <kn-id> <at-id>").description("Execute an action type (--body / --body-file envelope JSON)").option(
|
|
1426
|
+
actionType?.command("execute <kn-id> <at-id>").description("Execute an action type (--body / --body-file envelope JSON)").option(
|
|
1427
|
+
"--body <json>",
|
|
1428
|
+
"execution envelope JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1429
|
+
).option("--body-file <path>", "read envelope JSON from a file").action(async (knId, atId, opts, cmd) => {
|
|
1406
1430
|
printJson(
|
|
1407
1431
|
await clientFrom(cmd).kn.actionTypeExecute(knId, atId, readBody(opts)),
|
|
1408
1432
|
outputOptions(cmd)
|
|
1409
1433
|
);
|
|
1410
1434
|
});
|
|
1411
|
-
actionType?.command("inputs <kn-id> <at-id>").description("Get an action type's input schema").action(async (knId, atId, _o, cmd) => {
|
|
1412
|
-
printJson(await clientFrom(cmd).kn.actionTypeInputs(knId, atId), outputOptions(cmd));
|
|
1413
|
-
});
|
|
1414
1435
|
actionType?.command("get <kn-id> <at-id>").description("Get an action type").action(async (knId, atId, _o, cmd) => {
|
|
1415
1436
|
printJson(await clientFrom(cmd).kn.actionTypeGet(knId, atId), outputOptions(cmd));
|
|
1416
1437
|
});
|
|
@@ -1421,7 +1442,10 @@ function bknCommand() {
|
|
|
1421
1442
|
printJson(await clientFrom(cmd).kn.get(knId, { exportMode: true }), outputOptions(cmd));
|
|
1422
1443
|
});
|
|
1423
1444
|
const objectType = bkn.commands.find((c) => c.name() === "object-type");
|
|
1424
|
-
objectType?.command("query <kn-id> <ot-id>").description("Query instances of an object type (--body / --body-file JSON)").option(
|
|
1445
|
+
objectType?.command("query <kn-id> <ot-id>").description("Query instances of an object type (--body / --body-file JSON)").option(
|
|
1446
|
+
"--body <json>",
|
|
1447
|
+
"query JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1448
|
+
).option("--body-file <path>", "read query JSON from a file").action(async (knId, otId, opts, cmd) => {
|
|
1425
1449
|
printJson(
|
|
1426
1450
|
await clientFrom(cmd).kn.objectTypeQuery(knId, otId, readBody(opts)),
|
|
1427
1451
|
outputOptions(cmd)
|
|
@@ -1430,17 +1454,23 @@ function bknCommand() {
|
|
|
1430
1454
|
bkn.command("create <name>").description("Create an (empty) knowledge network").option("--branch <b>", "branch", "main").action(async (name, opts, cmd) => {
|
|
1431
1455
|
printJson(await clientFrom(cmd).kn.create({ name, branch: opts.branch }), outputOptions(cmd));
|
|
1432
1456
|
});
|
|
1433
|
-
bkn.command("update <kn-id>").description("Update a knowledge network (--body / --body-file)").option(
|
|
1457
|
+
bkn.command("update <kn-id>").description("Update a knowledge network (--body / --body-file)").option(
|
|
1458
|
+
"--body <json>",
|
|
1459
|
+
"update body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1460
|
+
).option("--body-file <path>", "read update body JSON from a file").action(async (knId, opts, cmd) => {
|
|
1434
1461
|
printJson(await clientFrom(cmd).kn.update(knId, readBody(opts)), outputOptions(cmd));
|
|
1435
1462
|
});
|
|
1436
1463
|
bkn.command("delete <kn-id>").description("Delete a knowledge network").option("-y, --yes", "skip confirmation").action(async (knId, _opts, cmd) => {
|
|
1437
1464
|
printJson(await clientFrom(cmd).kn.delete(knId), outputOptions(cmd));
|
|
1438
1465
|
});
|
|
1439
|
-
bkn.command("subgraph <kn-id>").description("Query a subgraph (--body / --body-file JSON)").option(
|
|
1466
|
+
bkn.command("subgraph <kn-id>").description("Query a subgraph (--body / --body-file JSON)").option(
|
|
1467
|
+
"--body <json>",
|
|
1468
|
+
"subgraph query JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1469
|
+
).option("--body-file <path>", "read subgraph query JSON from a file").action(async (knId, opts, cmd) => {
|
|
1440
1470
|
printJson(await clientFrom(cmd).kn.subgraph(knId, readBody(opts)), outputOptions(cmd));
|
|
1441
1471
|
});
|
|
1442
|
-
const actionLog = bkn.command("action-log").description("Action logs \u2014 list/get/cancel");
|
|
1443
|
-
actionLog.command("list <kn-id>").description("List action logs").option("--status <s>", "filter by status").option("--action-type-id <id>", "filter by action type").option("--limit <n>", "page size",
|
|
1472
|
+
const actionLog = bkn.command("action-log").description("Action logs \u2014 list/get/cancel; list pages with search_after");
|
|
1473
|
+
actionLog.command("list <kn-id>").description("List action logs").option("--status <s>", "filter by status").option("--action-type-id <id>", "filter by action type").option("--limit <n>", "page size", int3, DEFAULT_LIST_LIMIT).action(async (knId, opts, cmd) => {
|
|
1444
1474
|
printJson(
|
|
1445
1475
|
await clientFrom(cmd).kn.actionLogs(knId, {
|
|
1446
1476
|
status: opts.status,
|
|
@@ -1460,25 +1490,37 @@ function bknCommand() {
|
|
|
1460
1490
|
printJson(await clientFrom(cmd).kn.actionExecution(knId, execId), outputOptions(cmd));
|
|
1461
1491
|
});
|
|
1462
1492
|
const metric = bkn.command("metric").description("Metrics \u2014 query / dry-run");
|
|
1463
|
-
metric.command("query <kn-id> <metric-id>").description("Query a metric's data (--body / --body-file JSON)").option(
|
|
1493
|
+
metric.command("query <kn-id> <metric-id>").description("Query a metric's data (--body / --body-file JSON)").option(
|
|
1494
|
+
"--body <json>",
|
|
1495
|
+
"query JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1496
|
+
).option("--body-file <path>", "read query JSON from a file").action(async (knId, metricId, opts, cmd) => {
|
|
1464
1497
|
printJson(
|
|
1465
1498
|
await clientFrom(cmd).kn.metricQuery(knId, metricId, readBody(opts)),
|
|
1466
1499
|
outputOptions(cmd)
|
|
1467
1500
|
);
|
|
1468
1501
|
});
|
|
1469
|
-
metric.command("dry-run <kn-id>").description("Dry-run a metric definition (--body / --body-file JSON)").option(
|
|
1502
|
+
metric.command("dry-run <kn-id>").description("Dry-run a metric definition (--body / --body-file JSON)").option(
|
|
1503
|
+
"--body <json>",
|
|
1504
|
+
"metric definition JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1505
|
+
).option("--body-file <path>", "read metric definition JSON from a file").action(async (knId, opts, cmd) => {
|
|
1470
1506
|
printJson(await clientFrom(cmd).kn.metricDryRun(knId, readBody(opts)), outputOptions(cmd));
|
|
1471
1507
|
});
|
|
1472
1508
|
metric.command("list <kn-id>").description("List metrics").action(async (knId, _o, cmd) => {
|
|
1473
1509
|
printJson(await clientFrom(cmd).kn.metricList(knId), outputOptions(cmd));
|
|
1474
1510
|
});
|
|
1475
|
-
metric.command("get <kn-id> <metric-id>").description("Get a metric").action(async (knId, id, _o, cmd) => {
|
|
1511
|
+
metric.command("get <kn-id> <metric-id>").description("Get a metric \u2192 {entries}, since the route takes a list of ids").action(async (knId, id, _o, cmd) => {
|
|
1476
1512
|
printJson(await clientFrom(cmd).kn.metricGet(knId, id), outputOptions(cmd));
|
|
1477
1513
|
});
|
|
1478
|
-
metric.command("create <kn-id>").description("Create a metric (--body / --body-file)").option(
|
|
1514
|
+
metric.command("create <kn-id>").description("Create a metric (--body / --body-file)").option(
|
|
1515
|
+
"--body <json>",
|
|
1516
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1517
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, opts, cmd) => {
|
|
1479
1518
|
printJson(await clientFrom(cmd).kn.metricCreate(knId, readBody(opts)), outputOptions(cmd));
|
|
1480
1519
|
});
|
|
1481
|
-
metric.command("update <kn-id> <metric-id>").description("Update a metric (--body / --body-file)").option(
|
|
1520
|
+
metric.command("update <kn-id> <metric-id>").description("Update a metric (--body / --body-file)").option(
|
|
1521
|
+
"--body <json>",
|
|
1522
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1523
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, id, opts, cmd) => {
|
|
1482
1524
|
printJson(
|
|
1483
1525
|
await clientFrom(cmd).kn.metricUpdate(knId, id, readBody(opts)),
|
|
1484
1526
|
outputOptions(cmd)
|
|
@@ -1487,10 +1529,10 @@ function bknCommand() {
|
|
|
1487
1529
|
metric.command("delete <kn-id> <metric-id>").description("Delete a metric").action(async (knId, id, _o, cmd) => {
|
|
1488
1530
|
printJson(await clientFrom(cmd).kn.metricDelete(knId, id), outputOptions(cmd));
|
|
1489
1531
|
});
|
|
1490
|
-
metric.command("
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1532
|
+
metric.command("validate <kn-id>").description("Validate a metric definition (--body / --body-file)").option(
|
|
1533
|
+
"--body <json>",
|
|
1534
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1535
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, opts, cmd) => {
|
|
1494
1536
|
printJson(await clientFrom(cmd).kn.metricValidate(knId, readBody(opts)), outputOptions(cmd));
|
|
1495
1537
|
});
|
|
1496
1538
|
const cg = bkn.command("concept-group").description("Concept groups \u2014 list/get");
|
|
@@ -1500,13 +1542,19 @@ function bknCommand() {
|
|
|
1500
1542
|
cg.command("get <kn-id> <cg-id>").description("Get a concept group").action(async (knId, cgId, _o, cmd) => {
|
|
1501
1543
|
printJson(await clientFrom(cmd).kn.conceptGroup(knId, cgId), outputOptions(cmd));
|
|
1502
1544
|
});
|
|
1503
|
-
cg.command("create <kn-id>").description("Create a concept group (--body / --body-file)").option(
|
|
1545
|
+
cg.command("create <kn-id>").description("Create a concept group (--body / --body-file)").option(
|
|
1546
|
+
"--body <json>",
|
|
1547
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1548
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, opts, cmd) => {
|
|
1504
1549
|
printJson(
|
|
1505
1550
|
await clientFrom(cmd).kn.conceptGroupCreate(knId, readBody(opts)),
|
|
1506
1551
|
outputOptions(cmd)
|
|
1507
1552
|
);
|
|
1508
1553
|
});
|
|
1509
|
-
cg.command("update <kn-id> <cg-id>").description("Update a concept group (--body / --body-file)").option(
|
|
1554
|
+
cg.command("update <kn-id> <cg-id>").description("Update a concept group (--body / --body-file)").option(
|
|
1555
|
+
"--body <json>",
|
|
1556
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1557
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, cgId, opts, cmd) => {
|
|
1510
1558
|
printJson(
|
|
1511
1559
|
await clientFrom(cmd).kn.conceptGroupUpdate(knId, cgId, readBody(opts)),
|
|
1512
1560
|
outputOptions(cmd)
|
|
@@ -1515,7 +1563,10 @@ function bknCommand() {
|
|
|
1515
1563
|
cg.command("delete <kn-id> <cg-id>").description("Delete a concept group").action(async (knId, cgId, _o, cmd) => {
|
|
1516
1564
|
printJson(await clientFrom(cmd).kn.conceptGroupDelete(knId, cgId), outputOptions(cmd));
|
|
1517
1565
|
});
|
|
1518
|
-
cg.command("add-members <kn-id> <cg-id>").description("Add object types to a concept group (--body / --body-file)").option(
|
|
1566
|
+
cg.command("add-members <kn-id> <cg-id>").description("Add object types to a concept group (--body / --body-file)").option(
|
|
1567
|
+
"--body <json>",
|
|
1568
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1569
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, cgId, opts, cmd) => {
|
|
1519
1570
|
printJson(
|
|
1520
1571
|
await clientFrom(cmd).kn.conceptGroupAddMembers(knId, cgId, readBody(opts)),
|
|
1521
1572
|
outputOptions(cmd)
|
|
@@ -1534,19 +1585,28 @@ function bknCommand() {
|
|
|
1534
1585
|
sched.command("get <kn-id> <schedule-id>").description("Get an action schedule").action(async (knId, sId, _o, cmd) => {
|
|
1535
1586
|
printJson(await clientFrom(cmd).kn.actionSchedule(knId, sId), outputOptions(cmd));
|
|
1536
1587
|
});
|
|
1537
|
-
sched.command("create <kn-id>").description("Create an action schedule (--body / --body-file)").option(
|
|
1588
|
+
sched.command("create <kn-id>").description("Create an action schedule (--body / --body-file)").option(
|
|
1589
|
+
"--body <json>",
|
|
1590
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1591
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, opts, cmd) => {
|
|
1538
1592
|
printJson(
|
|
1539
1593
|
await clientFrom(cmd).kn.actionScheduleCreate(knId, readBody(opts)),
|
|
1540
1594
|
outputOptions(cmd)
|
|
1541
1595
|
);
|
|
1542
1596
|
});
|
|
1543
|
-
sched.command("update <kn-id> <schedule-id>").description("Update an action schedule (--body / --body-file)").option(
|
|
1597
|
+
sched.command("update <kn-id> <schedule-id>").description("Update an action schedule (--body / --body-file)").option(
|
|
1598
|
+
"--body <json>",
|
|
1599
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1600
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, sId, opts, cmd) => {
|
|
1544
1601
|
printJson(
|
|
1545
1602
|
await clientFrom(cmd).kn.actionScheduleUpdate(knId, sId, readBody(opts)),
|
|
1546
1603
|
outputOptions(cmd)
|
|
1547
1604
|
);
|
|
1548
1605
|
});
|
|
1549
|
-
sched.command("set-status <kn-id> <schedule-id>").description("Set an action schedule's status (--body / --body-file)").option(
|
|
1606
|
+
sched.command("set-status <kn-id> <schedule-id>").description("Set an action schedule's status (--body / --body-file)").option(
|
|
1607
|
+
"--body <json>",
|
|
1608
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1609
|
+
).option("--body-file <path>", "read body JSON from a file").action(async (knId, sId, opts, cmd) => {
|
|
1550
1610
|
printJson(
|
|
1551
1611
|
await clientFrom(cmd).kn.actionScheduleSetStatus(knId, sId, readBody(opts)),
|
|
1552
1612
|
outputOptions(cmd)
|
|
@@ -1574,7 +1634,10 @@ function bknCommand() {
|
|
|
1574
1634
|
outputOptions(cmd)
|
|
1575
1635
|
);
|
|
1576
1636
|
});
|
|
1577
|
-
bkn.command("relation-type-paths <kn-id>").description("Query relation-type paths between object types (--body / --body-file JSON)").option(
|
|
1637
|
+
bkn.command("relation-type-paths <kn-id>").description("Query relation-type paths between object types (--body / --body-file JSON)").option(
|
|
1638
|
+
"--body <json>",
|
|
1639
|
+
"request JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1640
|
+
).option("--body-file <path>", "read request JSON from a file").action(async (knId, opts, cmd) => {
|
|
1578
1641
|
printJson(
|
|
1579
1642
|
await clientFrom(cmd).kn.relationTypePaths(knId, readBody(opts)),
|
|
1580
1643
|
outputOptions(cmd)
|
|
@@ -1610,17 +1673,73 @@ function bknCommand() {
|
|
|
1610
1673
|
printJson(result, outputOptions(cmd));
|
|
1611
1674
|
if (!result.valid) process.exitCode = 1;
|
|
1612
1675
|
});
|
|
1613
|
-
|
|
1676
|
+
groupChildren(bkn, {
|
|
1677
|
+
GROUPS: [
|
|
1678
|
+
"object-type",
|
|
1679
|
+
"relation-type",
|
|
1680
|
+
"action-type",
|
|
1681
|
+
"metric",
|
|
1682
|
+
"concept-group",
|
|
1683
|
+
"action-log",
|
|
1684
|
+
"action-schedule"
|
|
1685
|
+
],
|
|
1686
|
+
READ: [
|
|
1687
|
+
"pull",
|
|
1688
|
+
"list",
|
|
1689
|
+
"get",
|
|
1690
|
+
"stats",
|
|
1691
|
+
"export",
|
|
1692
|
+
"search",
|
|
1693
|
+
"subgraph",
|
|
1694
|
+
"relation-type-paths",
|
|
1695
|
+
"resources",
|
|
1696
|
+
"action-execution",
|
|
1697
|
+
"validate"
|
|
1698
|
+
],
|
|
1699
|
+
WRITE: ["create", "update", "delete", "push", "create-from-catalog"]
|
|
1700
|
+
});
|
|
1701
|
+
groupChildren(metric, {
|
|
1702
|
+
READ: ["list", "get"],
|
|
1703
|
+
RUN: ["query", "dry-run", "validate"],
|
|
1704
|
+
WRITE: ["create", "update", "delete"]
|
|
1705
|
+
});
|
|
1706
|
+
guide(
|
|
1707
|
+
bkn,
|
|
1708
|
+
`WHERE IDS COME FROM
|
|
1709
|
+
\`list\` gives kn ids; \`object-type list <kn-id>\` and \`search <kn-id> "<q>"\` give the rest.
|
|
1710
|
+
|
|
1711
|
+
SEARCH VS THE MCP SIDE
|
|
1712
|
+
\`search\` recalls instance rows from one sentence and ships the object-type definitions
|
|
1713
|
+
needed to read them \u2014 start here when you do not know the schema yet. It only reaches
|
|
1714
|
+
properties indexed for match/knn, so an unindexed object type yields nothing, and no hits
|
|
1715
|
+
comes back as empty nodes with a message rather than an error. For schema alone use
|
|
1716
|
+
\`openbkn context search-schema\`; for a structured filter use \`object-type query\`.
|
|
1717
|
+
|
|
1718
|
+
EDITING SCHEMA AS FILES
|
|
1719
|
+
pull <kn-id> ./dir -> edit -> validate ./dir -> push ./dir
|
|
1720
|
+
\`validate\` is offline and catches structure errors before the upload.
|
|
1721
|
+
|
|
1722
|
+
REQUEST BODIES
|
|
1723
|
+
create/update take a definition; query/execute/dry-run take a query. Both are documented
|
|
1724
|
+
at https://openbkn-ai.github.io/bkn-foundry/ \u2014 definitions under bkn-backend, reads and
|
|
1725
|
+
executions under ontology-query. Each command's --body flag names its own module.
|
|
1726
|
+
|
|
1727
|
+
CREATING FROM DATA
|
|
1728
|
+
create-from-catalog <catalog-id> --name "<n>" builds a network from a Vega catalog,
|
|
1729
|
+
then \`openbkn vega dataset build <resource-id>\` produces the index. There is no
|
|
1730
|
+
whole-network build.`
|
|
1731
|
+
);
|
|
1732
|
+
return group(bkn, "DATA & KNOWLEDGE");
|
|
1614
1733
|
}
|
|
1615
1734
|
|
|
1616
1735
|
// src/commands/call.ts
|
|
1617
|
-
import { Command as
|
|
1736
|
+
import { Command as Command5 } from "commander";
|
|
1618
1737
|
function collect(value, prev) {
|
|
1619
1738
|
prev.push(value);
|
|
1620
1739
|
return prev;
|
|
1621
1740
|
}
|
|
1622
1741
|
function callCommand() {
|
|
1623
|
-
const cmd = new
|
|
1742
|
+
const cmd = new Command5("call").alias("curl").description("Call any platform API endpoint directly (auth added)").argument("<url>", "API path (e.g. /api/...) or absolute URL").option("-X, --request <method>", "HTTP method").option("-H, --header <header>", 'extra header "Name: value" (repeatable)', collect, []).option("-d, --data <body>", "request body (sets JSON content-type if unset)").option("--data-raw <body>", "alias for --data").option(
|
|
1624
1743
|
"-F, --form <field>",
|
|
1625
1744
|
"multipart field key=value or key=@file (repeatable)",
|
|
1626
1745
|
collect,
|
|
@@ -1657,18 +1776,30 @@ function callCommand() {
|
|
|
1657
1776
|
process.exitCode = 1;
|
|
1658
1777
|
}
|
|
1659
1778
|
});
|
|
1660
|
-
|
|
1779
|
+
guide(
|
|
1780
|
+
cmd,
|
|
1781
|
+
`WHEN TO USE THIS
|
|
1782
|
+
Anything the named commands do not cover: services with no command group yet
|
|
1783
|
+
(bkn-agent, execution-factory operators and sandbox functions, MCP registration,
|
|
1784
|
+
skill index builds), and endpoints newer than this CLI.
|
|
1785
|
+
|
|
1786
|
+
FINDING THE PATH
|
|
1787
|
+
Every service's API is documented at https://openbkn-ai.github.io/bkn-foundry/ \u2014
|
|
1788
|
+
read the path and request body there rather than guessing. Auth, business domain
|
|
1789
|
+
and TLS flags are injected the same way as for any other command.`
|
|
1790
|
+
);
|
|
1791
|
+
return group(cmd, "RAW API");
|
|
1661
1792
|
}
|
|
1662
1793
|
|
|
1663
1794
|
// src/commands/config.ts
|
|
1664
|
-
import { Command as
|
|
1795
|
+
import { Command as Command6 } from "commander";
|
|
1665
1796
|
function requireActive() {
|
|
1666
1797
|
const baseUrl = activePlatform();
|
|
1667
1798
|
if (!baseUrl) throw new InputError("No active platform. Run `openbkn auth login <url>` first.");
|
|
1668
1799
|
return baseUrl;
|
|
1669
1800
|
}
|
|
1670
1801
|
function configCommand() {
|
|
1671
|
-
const config = new
|
|
1802
|
+
const config = new Command6("config").description("Remember a platform URL / business domain");
|
|
1672
1803
|
config.command("show").description("Show the active platform and business domain").action((_opts, cmd) => {
|
|
1673
1804
|
const baseUrl = activePlatform();
|
|
1674
1805
|
printJson(
|
|
@@ -1681,7 +1812,7 @@ function configCommand() {
|
|
|
1681
1812
|
});
|
|
1682
1813
|
config.command("set <key> <value>").description("Set a config value (baseUrl | businessDomain)").action((key, value, _opts, cmd) => {
|
|
1683
1814
|
if (key === "baseUrl") {
|
|
1684
|
-
setActivePlatform(value
|
|
1815
|
+
setActivePlatform(trimTrailingSlashes(value));
|
|
1685
1816
|
} else if (key === "businessDomain") {
|
|
1686
1817
|
updatePlatformConfig(requireActive(), { businessDomain: value });
|
|
1687
1818
|
} else {
|
|
@@ -1697,12 +1828,13 @@ function configCommand() {
|
|
|
1697
1828
|
config.command("list-bd").description("List business domains (requires login)").action(() => {
|
|
1698
1829
|
throw new InputError("Not yet implemented \u2014 requires backend business-domains API.");
|
|
1699
1830
|
});
|
|
1700
|
-
|
|
1831
|
+
groupChildren(config, { READ: ["show", "list-bd"], WRITE: ["set", "set-bd"] });
|
|
1832
|
+
return group(config, "SIGN IN & SETTINGS");
|
|
1701
1833
|
}
|
|
1702
1834
|
|
|
1703
1835
|
// src/commands/context.ts
|
|
1704
|
-
import { Command as
|
|
1705
|
-
var
|
|
1836
|
+
import { Command as Command7 } from "commander";
|
|
1837
|
+
var int4 = (v) => Number.parseInt(v, 10);
|
|
1706
1838
|
var collectArg = (v, prev) => {
|
|
1707
1839
|
prev.push(v);
|
|
1708
1840
|
return prev;
|
|
@@ -1740,33 +1872,44 @@ function printToolList(res, out) {
|
|
|
1740
1872
|
printJson(res, out);
|
|
1741
1873
|
return;
|
|
1742
1874
|
}
|
|
1743
|
-
const
|
|
1875
|
+
const rows2 = arr.map((t) => ({
|
|
1744
1876
|
name: t.name ?? t.tool_name ?? t.key ?? "",
|
|
1745
1877
|
description: typeof t.description === "string" ? t.description : ""
|
|
1746
1878
|
}));
|
|
1747
|
-
printJson(
|
|
1879
|
+
printJson(rows2, out);
|
|
1748
1880
|
}
|
|
1749
1881
|
function contextCommand() {
|
|
1750
|
-
const cmd = new
|
|
1751
|
-
"
|
|
1882
|
+
const cmd = new Command7("context").description(
|
|
1883
|
+
"Ask a network questions (the MCP interface agents use)"
|
|
1752
1884
|
);
|
|
1753
|
-
|
|
1885
|
+
const jsonArgs = (raw) => {
|
|
1886
|
+
if (!raw) throw new InputError("--args is required (run with --schema to see its shape)");
|
|
1887
|
+
try {
|
|
1888
|
+
return parseBigIntJSON(raw);
|
|
1889
|
+
} catch {
|
|
1890
|
+
throw new InputError("--args must be valid JSON");
|
|
1891
|
+
}
|
|
1892
|
+
};
|
|
1893
|
+
cmd.command("search-schema <kn-id> <query>").description(
|
|
1894
|
+
"Search object/relation/action/metric schemas \u2192 {object_types, relation_types, action_types, metric_types}"
|
|
1895
|
+
).option("--scope <list>", "comma-separated scopes (object,relation,action,metric)").option("--max <n>", "max concepts", int4).action(async (knId, query, opts, cmd2) => {
|
|
1754
1896
|
const data = await clientFrom(cmd2).context.searchSchema(knId, query, {
|
|
1755
1897
|
searchScope: opts.scope ? String(opts.scope).split(",") : void 0,
|
|
1756
1898
|
maxConcepts: opts.max
|
|
1757
1899
|
});
|
|
1758
1900
|
printJson(data, outputOptions(cmd2));
|
|
1759
1901
|
});
|
|
1760
|
-
cmd.command("query-object-instance <kn-id>").description(
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1902
|
+
cmd.command("query-object-instance <kn-id>").description(
|
|
1903
|
+
`Query one object type's instances \u2014 \`--args '{"ot_id":"<id>","limit":10}'\` \u2192 {datas, total_count}`
|
|
1904
|
+
).option(
|
|
1905
|
+
"--args <json>",
|
|
1906
|
+
"tool arguments as JSON; kn_id is filled from <kn-id>; --schema prints the shape"
|
|
1907
|
+
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
1908
|
+
if (opts.schema) return printToolSchema(cmd2, knId, "query_object_instance");
|
|
1909
|
+
const args = jsonArgs(opts.args);
|
|
1767
1910
|
printJson(await clientFrom(cmd2).context.queryObjectInstance(knId, args), outputOptions(cmd2));
|
|
1768
1911
|
});
|
|
1769
|
-
cmd.command("find-skills <kn-id> <object-type-id>").description("Recall skills for an object type").option("--top-k <n>", "max skills (1-20)",
|
|
1912
|
+
cmd.command("find-skills <kn-id> <object-type-id>").description("Recall skills for an object type").option("--top-k <n>", "max skills (1-20)", int4).action(async (knId, otId, opts, cmd2) => {
|
|
1770
1913
|
printJson(
|
|
1771
1914
|
await clientFrom(cmd2).context.findSkills(knId, otId, opts.topK),
|
|
1772
1915
|
outputOptions(cmd2)
|
|
@@ -1815,15 +1958,106 @@ function contextCommand() {
|
|
|
1815
1958
|
cmd.command("info").description("List the deploy's MCP tool catalog (global \u2014 no KN needed)").action(async (_opts, cmd2) => {
|
|
1816
1959
|
printToolList(await clientFrom(cmd2).context.info(), outputOptions(cmd2));
|
|
1817
1960
|
});
|
|
1818
|
-
|
|
1961
|
+
const printToolSchema = async (cmd2, knId, tool) => {
|
|
1962
|
+
const listed = await clientFrom(cmd2).context.tools(knId);
|
|
1963
|
+
const found = listed.tools?.find((t) => t.name === tool);
|
|
1964
|
+
if (!found) throw new InputError(`this deploy does not advertise the ${tool} tool`);
|
|
1965
|
+
printJson(
|
|
1966
|
+
{ tool: found.name, description: found.description, inputSchema: found.inputSchema },
|
|
1967
|
+
{ ...outputOptions(cmd2), json: true }
|
|
1968
|
+
);
|
|
1969
|
+
};
|
|
1970
|
+
cmd.command("run-sql <kn-id>").description(
|
|
1971
|
+
"Aggregate, rank or join with read-only SQL \u2014 what query-object-instance cannot do"
|
|
1972
|
+
).option("--sql <sql>", "read-only MySQL over data resources, tables named as {{<resource-id>}}").option("--timeout <sec>", "query timeout in seconds", (v) => Number.parseInt(v, 10)).option("--schema", "print this tool's argument schema from the deploy instead of calling it").addHelpText(
|
|
1973
|
+
"after",
|
|
1974
|
+
`
|
|
1975
|
+
A table is named by resource id, never by the name it carries on the source:
|
|
1976
|
+
|
|
1977
|
+
openbkn context search-schema <kn-id> "<what you are after>" --json
|
|
1978
|
+
\u2192 object_types[].data_source.id
|
|
1979
|
+
|
|
1980
|
+
openbkn context run-sql <kn-id> \\
|
|
1981
|
+
--sql "SELECT supplier_id, COUNT(*) c FROM {{d9g387peef0be1ifnurg}} GROUP BY supplier_id"
|
|
1982
|
+
|
|
1983
|
+
Joining two resources means two ids, one placeholder each. Column names are the
|
|
1984
|
+
physical ones. Answers {columns, entries, paging} plus a bkn_receipt recording
|
|
1985
|
+
the operation in BKN Trace. Row limits belong in the SQL \u2014 this tool takes no
|
|
1986
|
+
limit argument.
|
|
1987
|
+
|
|
1988
|
+
The same SQL runs without a knowledge network through \`openbkn vega sql\`, which
|
|
1989
|
+
adds paging and --need-total but records nothing in Trace.`
|
|
1990
|
+
).action(async (knId, opts, cmd2) => {
|
|
1991
|
+
if (opts.schema) return printToolSchema(cmd2, knId, "run_sql");
|
|
1992
|
+
if (!opts.sql) throw new InputError("--sql is required (or use --schema to see the shape)");
|
|
1993
|
+
const args = { sql: opts.sql };
|
|
1994
|
+
if (opts.timeout !== void 0) args.query_timeout = opts.timeout;
|
|
1995
|
+
printJson(await clientFrom(cmd2).context.toolCall(knId, "run_sql", args), outputOptions(cmd2));
|
|
1996
|
+
});
|
|
1997
|
+
cmd.command("explore-subgraph <kn-id> <object-type-id>").description("Follow relations outward from one object type without naming a path first").option("--hops <n>", "how many hops to walk, 1-3", (v) => Number.parseInt(v, 10)).option(
|
|
1998
|
+
"--direction <d>",
|
|
1999
|
+
"forward | backward | bidirectional \u2014 pick bidirectional when unsure how the relation reads",
|
|
2000
|
+
"bidirectional"
|
|
2001
|
+
).option(
|
|
2002
|
+
"--limit <n>",
|
|
2003
|
+
"instances of the STARTING type, not paths or total objects",
|
|
2004
|
+
(v) => Number.parseInt(v, 10)
|
|
2005
|
+
).option("--args <json>", "extra tool arguments merged in (condition, sort, offset \u2026)").option("--schema", "print this tool's argument schema from the deploy instead of calling it").addHelpText(
|
|
2006
|
+
"after",
|
|
2007
|
+
`
|
|
2008
|
+
Use this when the topology is the question \u2014 "what does this supplier touch?" \u2014
|
|
2009
|
+
and \`query-instance-subgraph\` when you already know which relations to walk.
|
|
2010
|
+
Paths multiply with each hop, so start at 1 or 2.`
|
|
2011
|
+
).action(async (knId, objectTypeId, opts, cmd2) => {
|
|
2012
|
+
if (opts.schema) return printToolSchema(cmd2, knId, "explore_subgraph");
|
|
2013
|
+
if (opts.hops === void 0) {
|
|
2014
|
+
throw new InputError("--hops is required (or use --schema to see the shape)");
|
|
2015
|
+
}
|
|
2016
|
+
const args = {
|
|
2017
|
+
...opts.args ? jsonArgs(opts.args) : {},
|
|
2018
|
+
source_object_type_id: objectTypeId,
|
|
2019
|
+
direction: opts.direction,
|
|
2020
|
+
path_length: opts.hops
|
|
2021
|
+
};
|
|
2022
|
+
if (opts.limit !== void 0) args.limit = opts.limit;
|
|
2023
|
+
printJson(
|
|
2024
|
+
await clientFrom(cmd2).context.toolCall(knId, "explore_subgraph", args),
|
|
2025
|
+
outputOptions(cmd2)
|
|
2026
|
+
);
|
|
2027
|
+
});
|
|
2028
|
+
cmd.command("query-metric <kn-id> <metric-id>").description("Read a modelled metric through its own definition \u2014 do not restate it in SQL").option(
|
|
2029
|
+
"--args <json>",
|
|
2030
|
+
"tool arguments: analysis_dimensions, time, condition, having, order_by"
|
|
2031
|
+
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").addHelpText(
|
|
2032
|
+
"after",
|
|
2033
|
+
`
|
|
2034
|
+
Metric ids come from an object type: \`context object-types <kn-id> <ot-id>\`
|
|
2035
|
+
lists them under related_metrics. The definition owns the arithmetic, so
|
|
2036
|
+
rewriting it with \`run-sql\` produces a number the platform will not agree with.`
|
|
2037
|
+
).action(async (knId, metricId, opts, cmd2) => {
|
|
2038
|
+
if (opts.schema) return printToolSchema(cmd2, knId, "query_metric");
|
|
2039
|
+
const args = { ...opts.args ? jsonArgs(opts.args) : {}, metric_id: metricId };
|
|
2040
|
+
printJson(
|
|
2041
|
+
await clientFrom(cmd2).context.toolCall(knId, "query_metric", args),
|
|
2042
|
+
outputOptions(cmd2)
|
|
2043
|
+
);
|
|
2044
|
+
});
|
|
2045
|
+
cmd.command("tools <kn-id>").description("List MCP tools advertised for a KN session \u2192 {tools} with each inputSchema").action(async (knId, _opts, cmd2) => {
|
|
1819
2046
|
printToolList(await clientFrom(cmd2).context.tools(knId), outputOptions(cmd2));
|
|
1820
2047
|
});
|
|
1821
|
-
cmd.command("tool-call <kn-id> <name>").description("Call any MCP tool by name \u2014 current or future (use `tools` to discover)").option(
|
|
2048
|
+
cmd.command("tool-call <kn-id> <name>").description("Call any MCP tool by name \u2014 current or future (use `tools` to discover)").option(
|
|
2049
|
+
"--args <json>",
|
|
2050
|
+
"tool arguments as JSON; kn_id is filled from <kn-id> \u2014 input schema comes from `context tools <kn-id>`"
|
|
2051
|
+
).option(
|
|
1822
2052
|
"--arg <key=value>",
|
|
1823
2053
|
"one argument (repeatable; value parsed as JSON, else string)",
|
|
1824
2054
|
collectArg,
|
|
1825
2055
|
[]
|
|
2056
|
+
).option(
|
|
2057
|
+
"--schema",
|
|
2058
|
+
"print the named tool's argument schema from the deploy instead of calling it"
|
|
1826
2059
|
).action(async (knId, name, opts, cmd2) => {
|
|
2060
|
+
if (opts.schema) return printToolSchema(cmd2, knId, name);
|
|
1827
2061
|
printJson(
|
|
1828
2062
|
await clientFrom(cmd2).context.toolCall(knId, name, buildArgs(opts)),
|
|
1829
2063
|
outputOptions(cmd2)
|
|
@@ -1831,7 +2065,7 @@ function contextCommand() {
|
|
|
1831
2065
|
});
|
|
1832
2066
|
cmd.command("call-method <kn-id> <method>").description(
|
|
1833
2067
|
"Call any MCP method by name (e.g. tools/list, resources/read) \u2014 current or future"
|
|
1834
|
-
).option("--args <json>", "method params as JSON").option(
|
|
2068
|
+
).option("--args <json>", "method params as JSON \u2014 see `context call-method <kn-id> tools/list`").option(
|
|
1835
2069
|
"--arg <key=value>",
|
|
1836
2070
|
"one param (repeatable; value parsed as JSON, else string)",
|
|
1837
2071
|
collectArg,
|
|
@@ -1854,7 +2088,10 @@ function contextCommand() {
|
|
|
1854
2088
|
cmd.command("prompts <kn-id>").description("List MCP prompts").action(async (knId, _opts, cmd2) => {
|
|
1855
2089
|
printJson(await clientFrom(cmd2).context.prompts(knId), outputOptions(cmd2));
|
|
1856
2090
|
});
|
|
1857
|
-
cmd.command("prompt <kn-id> <name>").description("Get one MCP prompt (--args JSON for prompt arguments)").option(
|
|
2091
|
+
cmd.command("prompt <kn-id> <name>").description("Get one MCP prompt (--args JSON for prompt arguments)").option(
|
|
2092
|
+
"--args <json>",
|
|
2093
|
+
"prompt arguments as JSON \u2014 argument names come from `context prompts <kn-id>`"
|
|
2094
|
+
).action(async (knId, name, opts, cmd2) => {
|
|
1858
2095
|
let args;
|
|
1859
2096
|
if (opts.args) {
|
|
1860
2097
|
try {
|
|
@@ -1865,124 +2102,978 @@ function contextCommand() {
|
|
|
1865
2102
|
}
|
|
1866
2103
|
printJson(await clientFrom(cmd2).context.prompt(knId, name, args), outputOptions(cmd2));
|
|
1867
2104
|
});
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
}
|
|
1874
|
-
};
|
|
1875
|
-
cmd.command("query-instance-subgraph <kn-id>").description("Query an instance subgraph across relation-type paths").requiredOption("--args <json>", "tool arguments as JSON").action(async (knId, opts, cmd2) => {
|
|
2105
|
+
cmd.command("query-instance-subgraph <kn-id>").description("Query an instance subgraph across relation-type paths").option(
|
|
2106
|
+
"--args <json>",
|
|
2107
|
+
"tool arguments as JSON; kn_id is filled from <kn-id>; --schema prints the shape"
|
|
2108
|
+
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2109
|
+
if (opts.schema) return printToolSchema(cmd2, knId, "query_instance_subgraph");
|
|
1876
2110
|
printJson(
|
|
1877
2111
|
await clientFrom(cmd2).context.queryInstanceSubgraph(knId, jsonArgs(opts.args)),
|
|
1878
2112
|
outputOptions(cmd2)
|
|
1879
2113
|
);
|
|
1880
2114
|
});
|
|
1881
|
-
cmd.command("get-logic-properties <kn-id>").description("Compute logic-property values for instances").
|
|
2115
|
+
cmd.command("get-logic-properties <kn-id>").description("Compute logic-property values for instances").option(
|
|
2116
|
+
"--args <json>",
|
|
2117
|
+
"tool arguments as JSON; kn_id is filled from <kn-id>; --schema prints the shape"
|
|
2118
|
+
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2119
|
+
if (opts.schema) return printToolSchema(cmd2, knId, "get_logic_properties_values");
|
|
1882
2120
|
printJson(
|
|
1883
2121
|
await clientFrom(cmd2).context.logicProperties(knId, jsonArgs(opts.args)),
|
|
1884
2122
|
outputOptions(cmd2)
|
|
1885
2123
|
);
|
|
1886
2124
|
});
|
|
1887
|
-
cmd.command("get-action-info <kn-id>").description("Fetch action info / dynamic tools for an instance").
|
|
2125
|
+
cmd.command("get-action-info <kn-id>").description("Fetch action info / dynamic tools for an instance").option(
|
|
2126
|
+
"--args <json>",
|
|
2127
|
+
"tool arguments as JSON; kn_id is filled from <kn-id>; --schema prints the shape"
|
|
2128
|
+
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2129
|
+
if (opts.schema) return printToolSchema(cmd2, knId, "get_action_info");
|
|
1888
2130
|
printJson(
|
|
1889
2131
|
await clientFrom(cmd2).context.actionInfo(knId, jsonArgs(opts.args)),
|
|
1890
2132
|
outputOptions(cmd2)
|
|
1891
2133
|
);
|
|
1892
2134
|
});
|
|
1893
|
-
|
|
2135
|
+
groupChildren(cmd, {
|
|
2136
|
+
GROUPS: ["conversation"],
|
|
2137
|
+
READ: [
|
|
2138
|
+
"search-schema",
|
|
2139
|
+
"kn-detail",
|
|
2140
|
+
"object-types",
|
|
2141
|
+
"relation-types",
|
|
2142
|
+
"info",
|
|
2143
|
+
"tools",
|
|
2144
|
+
"resources",
|
|
2145
|
+
"resource",
|
|
2146
|
+
"templates",
|
|
2147
|
+
"prompts",
|
|
2148
|
+
"prompt",
|
|
2149
|
+
"find-skills"
|
|
2150
|
+
],
|
|
2151
|
+
RUN: [
|
|
2152
|
+
"query-object-instance",
|
|
2153
|
+
"run-sql",
|
|
2154
|
+
"explore-subgraph",
|
|
2155
|
+
"query-metric",
|
|
2156
|
+
"query-instance-subgraph",
|
|
2157
|
+
"get-logic-properties",
|
|
2158
|
+
"get-action-info",
|
|
2159
|
+
"tool-call",
|
|
2160
|
+
"call-method"
|
|
2161
|
+
]
|
|
2162
|
+
});
|
|
2163
|
+
guide(
|
|
2164
|
+
cmd,
|
|
2165
|
+
`ORDER OF WORK
|
|
2166
|
+
1. search-schema <kn-id> "<question>" find the object/relation/action ids that matter
|
|
2167
|
+
2. kn-detail / object-types drill into the ones you picked
|
|
2168
|
+
3. query-object-instance filter + sort + page one object type
|
|
2169
|
+
query-instance-subgraph follow a known relation path
|
|
2170
|
+
get-logic-properties / get-action-info computed values, runnable actions
|
|
2171
|
+
|
|
2172
|
+
PICKING THE RIGHT QUERY
|
|
2173
|
+
Aggregation, ranking, GROUP BY or joins are not query-object-instance \u2014 send SQL through
|
|
2174
|
+
\`tool-call <kn-id> run_sql\`. Unknown topology is \`tool-call <kn-id> explore_subgraph\`,
|
|
2175
|
+
not a hand-built path.
|
|
2176
|
+
|
|
2177
|
+
THE SAME ID, FOUR NAMES
|
|
2178
|
+
An object type's id is \`concept_id\` in search-schema output, \`id\` in kn-detail and
|
|
2179
|
+
get_object_types, \`ot_id\` in query-object-instance arguments, and \`object_type_id\` on
|
|
2180
|
+
an instance row. Same value throughout \u2014 carry it across, do not look it up again.
|
|
2181
|
+
|
|
2182
|
+
RAW MCP
|
|
2183
|
+
tools <kn-id> lists what this deploy advertises, with each tool's input schema.
|
|
2184
|
+
tool-call / call-method reach anything the named commands above do not cover.`
|
|
2185
|
+
);
|
|
2186
|
+
return group(cmd, "DATA & KNOWLEDGE");
|
|
1894
2187
|
}
|
|
1895
2188
|
|
|
1896
|
-
// src/commands/
|
|
1897
|
-
import {
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
var
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
2189
|
+
// src/commands/describe.ts
|
|
2190
|
+
import { Command as Command8 } from "commander";
|
|
2191
|
+
|
|
2192
|
+
// src/help/returns.json
|
|
2193
|
+
var returns_default = {
|
|
2194
|
+
note: "Top-level keys observed on a live deploy, not a contract. Regenerate with scripts/capture-returns.mjs.",
|
|
2195
|
+
observedAt: "2026-08-29",
|
|
2196
|
+
commands: {
|
|
2197
|
+
"auth status": ["baseUrl", "expired", "hasToken", "userId", "username"],
|
|
2198
|
+
"auth whoami": [
|
|
2199
|
+
"at_hash",
|
|
2200
|
+
"aud",
|
|
2201
|
+
"auth_time",
|
|
2202
|
+
"baseUrl",
|
|
2203
|
+
"exp",
|
|
2204
|
+
"iat",
|
|
2205
|
+
"iss",
|
|
2206
|
+
"jti",
|
|
2207
|
+
"rat",
|
|
2208
|
+
"sid",
|
|
2209
|
+
"sub",
|
|
2210
|
+
"userId",
|
|
2211
|
+
"username"
|
|
2212
|
+
],
|
|
2213
|
+
"auth list": "array",
|
|
2214
|
+
"config show": ["baseUrl"],
|
|
2215
|
+
"appkey list": ["keys"],
|
|
2216
|
+
"appkey admin list": ["keys"],
|
|
2217
|
+
"bkn list": ["entries", "total_count"],
|
|
2218
|
+
"bkn get": [
|
|
2219
|
+
"branch",
|
|
2220
|
+
"business_domain",
|
|
2221
|
+
"color",
|
|
2222
|
+
"comment",
|
|
2223
|
+
"create_time",
|
|
2224
|
+
"creator",
|
|
2225
|
+
"icon",
|
|
2226
|
+
"id",
|
|
2227
|
+
"module_type",
|
|
2228
|
+
"name",
|
|
2229
|
+
"operations",
|
|
2230
|
+
"tags",
|
|
2231
|
+
"update_time",
|
|
2232
|
+
"updater"
|
|
2233
|
+
],
|
|
2234
|
+
"bkn object-type list": ["entries", "total_count"],
|
|
2235
|
+
"bkn object-type get": ["entries"],
|
|
2236
|
+
"bkn relation-type list": ["entries", "total_count"],
|
|
2237
|
+
"bkn relation-type get": ["entries"],
|
|
2238
|
+
"bkn action-type list": ["entries", "total_count"],
|
|
2239
|
+
"bkn action-type get": ["entries"],
|
|
2240
|
+
"bkn stats": [
|
|
2241
|
+
"branch",
|
|
2242
|
+
"business_domain",
|
|
2243
|
+
"color",
|
|
2244
|
+
"comment",
|
|
2245
|
+
"create_time",
|
|
2246
|
+
"creator",
|
|
2247
|
+
"icon",
|
|
2248
|
+
"id",
|
|
2249
|
+
"module_type",
|
|
2250
|
+
"name",
|
|
2251
|
+
"operations",
|
|
2252
|
+
"statistics",
|
|
2253
|
+
"tags",
|
|
2254
|
+
"update_time",
|
|
2255
|
+
"updater"
|
|
2256
|
+
],
|
|
2257
|
+
"bkn action-log list": ["entries"],
|
|
2258
|
+
"bkn metric list": ["entries", "total_count"],
|
|
2259
|
+
"bkn concept-group list": ["entries", "total_count"],
|
|
2260
|
+
"bkn concept-group get": [
|
|
2261
|
+
"branch",
|
|
2262
|
+
"color",
|
|
2263
|
+
"comment",
|
|
2264
|
+
"create_time",
|
|
2265
|
+
"creator",
|
|
2266
|
+
"icon",
|
|
2267
|
+
"id",
|
|
2268
|
+
"kn_id",
|
|
2269
|
+
"module_type",
|
|
2270
|
+
"name",
|
|
2271
|
+
"object_types",
|
|
2272
|
+
"relation_types",
|
|
2273
|
+
"tags",
|
|
2274
|
+
"update_time",
|
|
2275
|
+
"updater"
|
|
2276
|
+
],
|
|
2277
|
+
"bkn action-schedule list": ["entries", "total_count"],
|
|
2278
|
+
"vega catalog list": ["entries", "total_count"],
|
|
2279
|
+
"vega catalog resources": ["entries", "total_count"],
|
|
2280
|
+
"vega catalog health": ["health_check_result", "health_check_status", "id", "last_check_time"],
|
|
2281
|
+
"vega discover-schedule list": ["entries", "total_count"],
|
|
2282
|
+
"vega discover-schedule get": [
|
|
2283
|
+
"catalog_id",
|
|
2284
|
+
"create_time",
|
|
2285
|
+
"creator",
|
|
2286
|
+
"cron_expr",
|
|
2287
|
+
"enabled",
|
|
2288
|
+
"end_time",
|
|
2289
|
+
"id",
|
|
2290
|
+
"last_run",
|
|
2291
|
+
"name",
|
|
2292
|
+
"next_run",
|
|
2293
|
+
"start_time",
|
|
2294
|
+
"strategy",
|
|
2295
|
+
"update_time",
|
|
2296
|
+
"updater"
|
|
2297
|
+
],
|
|
2298
|
+
"vega discover-task list": ["entries", "total_count"],
|
|
2299
|
+
"vega discover-task get": [
|
|
2300
|
+
"catalog_id",
|
|
2301
|
+
"catalog_name",
|
|
2302
|
+
"create_time",
|
|
2303
|
+
"creator",
|
|
2304
|
+
"finish_time",
|
|
2305
|
+
"id",
|
|
2306
|
+
"last_progress_time",
|
|
2307
|
+
"message",
|
|
2308
|
+
"progress",
|
|
2309
|
+
"queue_priority",
|
|
2310
|
+
"result",
|
|
2311
|
+
"schedule_id",
|
|
2312
|
+
"start_time",
|
|
2313
|
+
"status",
|
|
2314
|
+
"strategy",
|
|
2315
|
+
"trigger_type"
|
|
2316
|
+
],
|
|
2317
|
+
"vega semantic-task list": ["entries", "total_count"],
|
|
2318
|
+
"vega semantic-task get": [
|
|
2319
|
+
"agent_id",
|
|
2320
|
+
"agent_task_id",
|
|
2321
|
+
"applied",
|
|
2322
|
+
"apply_detail_json",
|
|
2323
|
+
"apply_mode",
|
|
2324
|
+
"catalog_id",
|
|
2325
|
+
"catalog_name",
|
|
2326
|
+
"confidence",
|
|
2327
|
+
"confidence_detail_json",
|
|
2328
|
+
"confidence_threshold",
|
|
2329
|
+
"create_time",
|
|
2330
|
+
"creator",
|
|
2331
|
+
"id",
|
|
2332
|
+
"input",
|
|
2333
|
+
"input_hash",
|
|
2334
|
+
"resource_id",
|
|
2335
|
+
"resource_name",
|
|
2336
|
+
"result_json",
|
|
2337
|
+
"scope",
|
|
2338
|
+
"status"
|
|
2339
|
+
],
|
|
2340
|
+
"vega connector-type list": ["entries", "total_count"],
|
|
2341
|
+
"vega resource list": ["entries", "total_count"],
|
|
2342
|
+
"vega resource get": ["entries"],
|
|
2343
|
+
"resource list": ["entries", "total_count"],
|
|
2344
|
+
"resource get": ["entries"],
|
|
2345
|
+
"context kn-detail": [
|
|
2346
|
+
"action_types",
|
|
2347
|
+
"comment",
|
|
2348
|
+
"concept_groups",
|
|
2349
|
+
"id",
|
|
2350
|
+
"name",
|
|
2351
|
+
"object_types",
|
|
2352
|
+
"relation_types"
|
|
2353
|
+
],
|
|
2354
|
+
"context info": [
|
|
2355
|
+
"auth",
|
|
2356
|
+
"client_config_example",
|
|
2357
|
+
"endpoint",
|
|
2358
|
+
"language",
|
|
2359
|
+
"protocol",
|
|
2360
|
+
"service",
|
|
2361
|
+
"supported_languages",
|
|
2362
|
+
"tool_count",
|
|
2363
|
+
"tools",
|
|
2364
|
+
"transport"
|
|
2365
|
+
],
|
|
2366
|
+
"context tools": ["tools"],
|
|
2367
|
+
"model llm list": ["count", "data"],
|
|
2368
|
+
"model llm get": [
|
|
2369
|
+
"max_model_len",
|
|
2370
|
+
"model_config",
|
|
2371
|
+
"model_id",
|
|
2372
|
+
"model_name",
|
|
2373
|
+
"model_series",
|
|
2374
|
+
"model_type"
|
|
2375
|
+
],
|
|
2376
|
+
"model small list": ["count", "data"],
|
|
2377
|
+
"model small get": [
|
|
2378
|
+
"adapter",
|
|
2379
|
+
"adapter_code",
|
|
2380
|
+
"batch_size",
|
|
2381
|
+
"create_time",
|
|
2382
|
+
"default",
|
|
2383
|
+
"embedding_dim",
|
|
2384
|
+
"max_tokens",
|
|
2385
|
+
"model_config",
|
|
2386
|
+
"model_id",
|
|
2387
|
+
"model_name",
|
|
2388
|
+
"model_type",
|
|
2389
|
+
"update_time"
|
|
2390
|
+
],
|
|
2391
|
+
"model small get-default": [
|
|
2392
|
+
"batch_size",
|
|
2393
|
+
"default",
|
|
2394
|
+
"embedding_dim",
|
|
2395
|
+
"max_tokens",
|
|
2396
|
+
"model_config",
|
|
2397
|
+
"model_id",
|
|
2398
|
+
"model_name",
|
|
2399
|
+
"model_type"
|
|
2400
|
+
],
|
|
2401
|
+
"skill list": ["data", "has_next", "has_prev", "page", "page_size", "total", "total_pages"],
|
|
2402
|
+
"skill get": [
|
|
2403
|
+
"business_domain_id",
|
|
2404
|
+
"category",
|
|
2405
|
+
"category_name",
|
|
2406
|
+
"create_time",
|
|
2407
|
+
"create_user",
|
|
2408
|
+
"description",
|
|
2409
|
+
"name",
|
|
2410
|
+
"skill_id",
|
|
2411
|
+
"source",
|
|
2412
|
+
"status",
|
|
2413
|
+
"update_time",
|
|
2414
|
+
"update_user",
|
|
2415
|
+
"version"
|
|
2416
|
+
],
|
|
2417
|
+
"skill market": ["data", "has_next", "has_prev", "page", "page_size", "total", "total_pages"],
|
|
2418
|
+
"skill market-get": [
|
|
2419
|
+
"business_domain_id",
|
|
2420
|
+
"category",
|
|
2421
|
+
"category_name",
|
|
2422
|
+
"create_time",
|
|
2423
|
+
"create_user",
|
|
2424
|
+
"description",
|
|
2425
|
+
"name",
|
|
2426
|
+
"release_time",
|
|
2427
|
+
"release_user",
|
|
2428
|
+
"skill_id",
|
|
2429
|
+
"source",
|
|
2430
|
+
"status",
|
|
2431
|
+
"update_time",
|
|
2432
|
+
"update_user",
|
|
2433
|
+
"version"
|
|
2434
|
+
],
|
|
2435
|
+
"skill content": ["files", "skill_id", "status", "url"],
|
|
2436
|
+
"skill files": ["entries", "path", "skillId", "totalFiles", "totalSize"],
|
|
2437
|
+
"skill names": ["entries"],
|
|
2438
|
+
"skill history": "array",
|
|
2439
|
+
"toolbox list": ["data", "has_next", "has_prev", "page", "page_size", "total", "total_pages"],
|
|
2440
|
+
"function deps": ["dependencies", "session_id"],
|
|
2441
|
+
"function template": ["code_template", "template_type"],
|
|
2442
|
+
"trace graph": [
|
|
2443
|
+
"data",
|
|
2444
|
+
"duration_nano",
|
|
2445
|
+
"page",
|
|
2446
|
+
"partial",
|
|
2447
|
+
"partial_reason",
|
|
2448
|
+
"status",
|
|
2449
|
+
"trace_id"
|
|
2450
|
+
],
|
|
2451
|
+
"trace conversations list": ["entries"],
|
|
2452
|
+
"trace conversations get": [
|
|
2453
|
+
"agent_name",
|
|
2454
|
+
"conversation_id",
|
|
2455
|
+
"created_at",
|
|
2456
|
+
"creation_auth_method",
|
|
2457
|
+
"external_conversation_key",
|
|
2458
|
+
"generation",
|
|
2459
|
+
"one_shot",
|
|
2460
|
+
"owner",
|
|
2461
|
+
"row_version",
|
|
2462
|
+
"status",
|
|
2463
|
+
"updated_at"
|
|
2464
|
+
],
|
|
2465
|
+
"trace interactions get": [
|
|
2466
|
+
"closure_manifest",
|
|
2467
|
+
"conversation_id",
|
|
2468
|
+
"created_at",
|
|
2469
|
+
"evidence_status",
|
|
2470
|
+
"execution_status",
|
|
2471
|
+
"interaction_id",
|
|
2472
|
+
"lease_epoch",
|
|
2473
|
+
"lease_expires_at",
|
|
2474
|
+
"lease_token",
|
|
2475
|
+
"lease_version",
|
|
2476
|
+
"ordinal",
|
|
2477
|
+
"row_version",
|
|
2478
|
+
"terminal_at",
|
|
2479
|
+
"updated_at"
|
|
2480
|
+
],
|
|
2481
|
+
"trace operations get": [
|
|
2482
|
+
"attempt",
|
|
2483
|
+
"attempt_status",
|
|
2484
|
+
"conversation_id",
|
|
2485
|
+
"created_at",
|
|
2486
|
+
"interaction_id",
|
|
2487
|
+
"operation_id",
|
|
2488
|
+
"operation_key",
|
|
2489
|
+
"retryable",
|
|
2490
|
+
"row_version",
|
|
2491
|
+
"tool_name",
|
|
2492
|
+
"updated_at"
|
|
2493
|
+
],
|
|
2494
|
+
"trace receipts get": [
|
|
2495
|
+
"artifact_refs",
|
|
2496
|
+
"attempt",
|
|
2497
|
+
"business_refs",
|
|
2498
|
+
"causation_event_ids",
|
|
2499
|
+
"conversation_id",
|
|
2500
|
+
"evidence_durability",
|
|
2501
|
+
"interaction_id",
|
|
2502
|
+
"issued_at",
|
|
2503
|
+
"observed_evidence_refs",
|
|
2504
|
+
"operation_id",
|
|
2505
|
+
"operation_key",
|
|
2506
|
+
"owner",
|
|
2507
|
+
"partial_reasons",
|
|
2508
|
+
"receipt_id",
|
|
2509
|
+
"receipt_status",
|
|
2510
|
+
"request_id",
|
|
2511
|
+
"required",
|
|
2512
|
+
"row_version",
|
|
2513
|
+
"schema_version",
|
|
2514
|
+
"terminal_at",
|
|
2515
|
+
"tool_name",
|
|
2516
|
+
"trace_id"
|
|
2517
|
+
],
|
|
2518
|
+
"trace get": "array",
|
|
2519
|
+
"trace detail": ["graph", "operations", "partial", "summary"],
|
|
2520
|
+
"trace spans": "array",
|
|
2521
|
+
"trace search": [
|
|
2522
|
+
"entries",
|
|
2523
|
+
"next_cursor",
|
|
2524
|
+
"page",
|
|
2525
|
+
"page_size",
|
|
2526
|
+
"partial",
|
|
2527
|
+
"total",
|
|
2528
|
+
"truncated"
|
|
2529
|
+
],
|
|
2530
|
+
"admin auth status": ["baseUrl", "expired", "hasToken", "userId", "username"],
|
|
2531
|
+
"admin auth whoami": [
|
|
2532
|
+
"at_hash",
|
|
2533
|
+
"aud",
|
|
2534
|
+
"auth_time",
|
|
2535
|
+
"baseUrl",
|
|
2536
|
+
"exp",
|
|
2537
|
+
"iat",
|
|
2538
|
+
"iss",
|
|
2539
|
+
"jti",
|
|
2540
|
+
"rat",
|
|
2541
|
+
"sid",
|
|
2542
|
+
"sub",
|
|
2543
|
+
"userId",
|
|
2544
|
+
"username"
|
|
2545
|
+
],
|
|
2546
|
+
"admin auth list": "array",
|
|
2547
|
+
"admin auth export": ["accessToken", "baseUrl", "idToken", "refreshToken"],
|
|
2548
|
+
"admin org list": ["departments", "total"],
|
|
2549
|
+
"admin org get": [
|
|
2550
|
+
"code",
|
|
2551
|
+
"created_at",
|
|
2552
|
+
"id",
|
|
2553
|
+
"manager_id",
|
|
2554
|
+
"manager_name",
|
|
2555
|
+
"name",
|
|
2556
|
+
"parent_id",
|
|
2557
|
+
"type"
|
|
2558
|
+
],
|
|
2559
|
+
"admin org members": ["total", "users"],
|
|
2560
|
+
"admin org tree": "array",
|
|
2561
|
+
"admin user list": ["total", "users"],
|
|
2562
|
+
"admin user get": [
|
|
2563
|
+
"account",
|
|
2564
|
+
"account_type",
|
|
2565
|
+
"departments",
|
|
2566
|
+
"email",
|
|
2567
|
+
"enabled",
|
|
2568
|
+
"id",
|
|
2569
|
+
"name",
|
|
2570
|
+
"roles",
|
|
2571
|
+
"telephone",
|
|
2572
|
+
"updated_at"
|
|
2573
|
+
],
|
|
2574
|
+
"admin user roles": ["roles"],
|
|
2575
|
+
"admin role list": ["roles"],
|
|
2576
|
+
"admin role get": [
|
|
2577
|
+
"built_in",
|
|
2578
|
+
"created_at",
|
|
2579
|
+
"description",
|
|
2580
|
+
"id",
|
|
2581
|
+
"members",
|
|
2582
|
+
"name",
|
|
2583
|
+
"permissions",
|
|
2584
|
+
"source"
|
|
2585
|
+
],
|
|
2586
|
+
"admin role members": ["members"],
|
|
2587
|
+
"admin llm list": ["count", "data"],
|
|
2588
|
+
"admin llm get": [
|
|
2589
|
+
"max_model_len",
|
|
2590
|
+
"model_config",
|
|
2591
|
+
"model_id",
|
|
2592
|
+
"model_name",
|
|
2593
|
+
"model_series",
|
|
2594
|
+
"model_type"
|
|
2595
|
+
],
|
|
2596
|
+
"admin small-model list": ["count", "data"],
|
|
2597
|
+
"admin small-model get": [
|
|
2598
|
+
"adapter",
|
|
2599
|
+
"adapter_code",
|
|
2600
|
+
"batch_size",
|
|
2601
|
+
"create_time",
|
|
2602
|
+
"default",
|
|
2603
|
+
"embedding_dim",
|
|
2604
|
+
"max_tokens",
|
|
2605
|
+
"model_config",
|
|
2606
|
+
"model_id",
|
|
2607
|
+
"model_name",
|
|
2608
|
+
"model_type",
|
|
2609
|
+
"update_time"
|
|
2610
|
+
],
|
|
2611
|
+
"admin license show": [
|
|
2612
|
+
"activated",
|
|
2613
|
+
"contract_expires_at",
|
|
2614
|
+
"customer",
|
|
2615
|
+
"edition",
|
|
2616
|
+
"expires_at",
|
|
2617
|
+
"features",
|
|
2618
|
+
"instance_fp",
|
|
2619
|
+
"issued_at",
|
|
2620
|
+
"lic_id",
|
|
2621
|
+
"limits",
|
|
2622
|
+
"state"
|
|
2623
|
+
],
|
|
2624
|
+
"admin config show": ["baseUrl"]
|
|
2625
|
+
}
|
|
1912
2626
|
};
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
2627
|
+
|
|
2628
|
+
// src/commands/probe.ts
|
|
2629
|
+
var SERVICE_PROBES = [
|
|
2630
|
+
{ service: "bkn-backend", path: "/api/bkn-backend/v1/knowledge-networks?limit=1" },
|
|
2631
|
+
{ service: "vega-backend", path: "/api/vega-backend/v1/catalogs?limit=1" },
|
|
2632
|
+
{
|
|
2633
|
+
service: "agent-operator-integration",
|
|
2634
|
+
path: "/api/agent-operator-integration/v1/tool-box/list?page=1&size=1"
|
|
2635
|
+
},
|
|
2636
|
+
{ service: "agent-observability", path: "/api/agent-observability/v1/conversations?limit=1" },
|
|
2637
|
+
{ service: "mf-model-manager", path: "/api/mf-model-manager/v1/llm/list" },
|
|
2638
|
+
{ service: "safe", path: "/api/safe/v1/me/api-keys" },
|
|
2639
|
+
{ service: "agent-retrieval", path: "/api/agent-retrieval/v1/mcp/info" }
|
|
2640
|
+
];
|
|
2641
|
+
var COMMAND_SERVICE = [
|
|
2642
|
+
[/^bkn\b/, "bkn-backend"],
|
|
2643
|
+
[/^vega\b/, "vega-backend"],
|
|
2644
|
+
[/^resource\b/, "vega-backend"],
|
|
2645
|
+
[/^context\b/, "agent-retrieval"],
|
|
2646
|
+
[/^trace\b/, "agent-observability"],
|
|
2647
|
+
[/^(skill|toolbox|tool|function)\b/, "agent-operator-integration"],
|
|
2648
|
+
[/^model\b/, "mf-model-manager"],
|
|
2649
|
+
[/^(auth|appkey)\b/, "safe"],
|
|
2650
|
+
[/^admin (llm|small-model)\b/, "mf-model-manager"],
|
|
2651
|
+
[/^admin\b/, "safe"]
|
|
2652
|
+
];
|
|
2653
|
+
var COMMAND_TOOL = {
|
|
2654
|
+
"context search-schema": "search_schema",
|
|
2655
|
+
"context query-object-instance": "query_object_instance",
|
|
2656
|
+
"context query-instance-subgraph": "query_instance_subgraph",
|
|
2657
|
+
"context explore-subgraph": "explore_subgraph",
|
|
2658
|
+
"context run-sql": "run_sql",
|
|
2659
|
+
"context query-metric": "query_metric",
|
|
2660
|
+
"context get-logic-properties": "get_logic_properties_values",
|
|
2661
|
+
"context get-action-info": "get_action_info",
|
|
2662
|
+
"context find-skills": "find_skills",
|
|
2663
|
+
"context kn-detail": "get_kn_detail",
|
|
2664
|
+
"context object-types": "get_object_types",
|
|
2665
|
+
"context relation-types": "get_relation_types"
|
|
2666
|
+
};
|
|
2667
|
+
async function probeDeploy(cmd, now) {
|
|
2668
|
+
const client = clientFrom(cmd);
|
|
2669
|
+
const services = {};
|
|
2670
|
+
for (const { service, path } of SERVICE_PROBES) {
|
|
2671
|
+
try {
|
|
2672
|
+
const res = await client.call(path);
|
|
2673
|
+
services[service] = res.status === 404 || res.status === 501 || res.status >= 502 ? { available: false, reason: `HTTP ${res.status} ${res.statusText}`.trim() } : { available: true };
|
|
2674
|
+
} catch (err) {
|
|
2675
|
+
services[service] = {
|
|
2676
|
+
available: false,
|
|
2677
|
+
reason: err instanceof Error ? firstLine(err.message) : "unreachable"
|
|
2678
|
+
};
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
let mcpTools = [];
|
|
2682
|
+
if (services["agent-retrieval"]?.available) {
|
|
2683
|
+
try {
|
|
2684
|
+
const info = await client.context.info();
|
|
2685
|
+
mcpTools = (info.tools ?? []).map((t) => typeof t === "string" ? t : t.name ?? "").filter(Boolean);
|
|
2686
|
+
} catch {
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
return { baseUrl: client.ctx.baseUrl, checkedAt: now, services, mcpTools };
|
|
2690
|
+
}
|
|
2691
|
+
function firstLine(message) {
|
|
2692
|
+
return (message.split("\n")[0] ?? message).slice(0, 160);
|
|
2693
|
+
}
|
|
2694
|
+
function availabilityOf(path, probe) {
|
|
2695
|
+
if (!probe) return { available: "unknown" };
|
|
2696
|
+
const tool = COMMAND_TOOL[path];
|
|
2697
|
+
if (tool && probe.mcpTools.length) {
|
|
2698
|
+
return probe.mcpTools.includes(tool) ? { available: true } : { available: false, reason: `this deploy's MCP server does not advertise ${tool}` };
|
|
2699
|
+
}
|
|
2700
|
+
const service = COMMAND_SERVICE.find(([re]) => re.test(path))?.[1];
|
|
2701
|
+
if (!service) return { available: "unknown", reason: "no single service to check" };
|
|
2702
|
+
const state = probe.services[service];
|
|
2703
|
+
if (!state) return { available: "unknown" };
|
|
2704
|
+
return state.available ? { available: true } : { available: false, reason: `${service}: ${state.reason ?? "unreachable"}` };
|
|
1937
2705
|
}
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
2706
|
+
|
|
2707
|
+
// src/commands/describe.ts
|
|
2708
|
+
var DEFAULT_SECTION = "COMMANDS";
|
|
2709
|
+
var ID_SOURCES = {
|
|
2710
|
+
"kn-id": "openbkn bkn list",
|
|
2711
|
+
"catalog-id": "openbkn vega catalog list",
|
|
2712
|
+
"resource-id": "openbkn vega catalog resources <catalog-id>",
|
|
2713
|
+
"ot-id": 'openbkn context search-schema <kn-id> "<q>"',
|
|
2714
|
+
"at-id": "openbkn bkn action-type list <kn-id>",
|
|
2715
|
+
"metric-id": "openbkn bkn metric list <kn-id>",
|
|
2716
|
+
"skill-id": "openbkn skill list",
|
|
2717
|
+
"box-id": "openbkn toolbox list",
|
|
2718
|
+
"tool-id": "openbkn tool list --toolbox <box-id>",
|
|
2719
|
+
"conversation-id": "openbkn trace conversations list",
|
|
2720
|
+
"trace-id": "openbkn trace search",
|
|
2721
|
+
"interaction-id": "openbkn trace search",
|
|
2722
|
+
"operation-id": "openbkn trace interactions operations <interaction-id>",
|
|
2723
|
+
"ot-ids": 'openbkn context search-schema <kn-id> "<q>"',
|
|
2724
|
+
"object-type-id": 'openbkn context search-schema <kn-id> "<q>"',
|
|
2725
|
+
"execution-id": "openbkn bkn action-log list <kn-id>",
|
|
2726
|
+
"receipt-id": "openbkn trace interactions operations <interaction-id>",
|
|
2727
|
+
"conversation-ids": "openbkn trace conversations list",
|
|
2728
|
+
"model-ids": "openbkn model llm list",
|
|
2729
|
+
"tool-ids": "openbkn tool list --toolbox <box-id>",
|
|
2730
|
+
"document-id": "openbkn vega resource document-get <resource-id> <document-id>",
|
|
2731
|
+
"document-ids": "openbkn vega resource document-get <resource-id> <document-id>",
|
|
2732
|
+
// Named entities, wherever they appear; the overrides below cover the cases
|
|
2733
|
+
// where the same word means something else.
|
|
2734
|
+
role: "openbkn admin role list",
|
|
2735
|
+
user: "openbkn admin user list"
|
|
2736
|
+
};
|
|
2737
|
+
var ARGUMENT_OVERRIDES = {
|
|
2738
|
+
"admin role add-member|id": "openbkn admin user list",
|
|
2739
|
+
"admin role remove-member|id": "openbkn admin user list",
|
|
2740
|
+
"admin user assign-role|role": "openbkn admin role list",
|
|
2741
|
+
"admin user revoke-role|role": "openbkn admin role list",
|
|
2742
|
+
"admin user roles|user": "openbkn admin user list",
|
|
2743
|
+
"admin role members|role": "openbkn admin role list",
|
|
2744
|
+
"auth switch|user": "openbkn auth users <url>",
|
|
2745
|
+
"admin auth switch|user": "openbkn admin auth users <url>"
|
|
2746
|
+
};
|
|
2747
|
+
var GROUP_ID_SOURCES = [
|
|
2748
|
+
[/^vega catalog\b/, "openbkn vega catalog list"],
|
|
2749
|
+
[/^vega resource\b/, "openbkn vega catalog resources <catalog-id>"],
|
|
2750
|
+
[/^vega discover-schedule\b/, "openbkn vega discover-schedule list"],
|
|
2751
|
+
[/^vega discover-task\b/, "openbkn vega discover-task list"],
|
|
2752
|
+
[/^vega semantic-task\b/, "openbkn vega semantic-task list"],
|
|
2753
|
+
[/^vega dataset\b/, "openbkn vega dataset build-list"],
|
|
2754
|
+
[/^bkn action-schedule\b/, "openbkn bkn action-schedule list <kn-id>"],
|
|
2755
|
+
[/^vega connector-type\b/, "openbkn vega connector-type list"],
|
|
2756
|
+
[/^resource\b/, "openbkn resource list"],
|
|
2757
|
+
[/^skill\b/, "openbkn skill list"],
|
|
2758
|
+
[/^toolbox\b/, "openbkn toolbox list"],
|
|
2759
|
+
[/^tool\b/, "openbkn tool list --toolbox <box-id>"],
|
|
2760
|
+
[/^appkey\b/, "openbkn appkey list"],
|
|
2761
|
+
[/^admin org\b/, "openbkn admin org list"],
|
|
2762
|
+
[/^auth\b/, "openbkn auth list"],
|
|
2763
|
+
[/^admin user\b/, "openbkn admin user list"],
|
|
2764
|
+
[/^admin role\b/, "openbkn admin role list"],
|
|
2765
|
+
[/^admin llm\b/, "openbkn admin llm list"],
|
|
2766
|
+
[/^admin small-model\b/, "openbkn admin small-model list"],
|
|
2767
|
+
[/^model llm\b/, "openbkn model llm list"],
|
|
2768
|
+
[/^model small\b/, "openbkn model small list"],
|
|
2769
|
+
[/^bkn object-type\b/, "openbkn bkn object-type list <kn-id>"],
|
|
2770
|
+
[/^bkn relation-type\b/, "openbkn bkn relation-type list <kn-id>"],
|
|
2771
|
+
[/^bkn action-type\b/, "openbkn bkn action-type list <kn-id>"],
|
|
2772
|
+
[/^bkn concept-group\b/, "openbkn bkn concept-group list <kn-id>"],
|
|
2773
|
+
[/^bkn action-schedule\b/, "openbkn bkn action-schedule list <kn-id>"],
|
|
2774
|
+
[/^bkn action-log\b/, "openbkn bkn action-log list <kn-id>"]
|
|
2775
|
+
];
|
|
2776
|
+
function sourceOf(argName, path, isLast) {
|
|
2777
|
+
const override = ARGUMENT_OVERRIDES[`${path.join(" ")}|${argName}`];
|
|
2778
|
+
if (override !== void 0) return override ?? void 0;
|
|
2779
|
+
const byName = ID_SOURCES[argName];
|
|
2780
|
+
if (byName) return byName;
|
|
2781
|
+
if (!isLast) return void 0;
|
|
2782
|
+
const generic = /^(id|ids|cg-id|modelid|role|user|schedule-id|schedule-ids|task-id|log-id)$/i.test(argName);
|
|
2783
|
+
if (!generic) return void 0;
|
|
2784
|
+
const parent = path.slice(0, -1).join(" ");
|
|
2785
|
+
return GROUP_ID_SOURCES.find(([re]) => re.test(parent))?.[1];
|
|
2786
|
+
}
|
|
2787
|
+
function describeOption(opt) {
|
|
2788
|
+
return {
|
|
2789
|
+
flags: opt.flags,
|
|
2790
|
+
description: opt.description,
|
|
2791
|
+
...opt.mandatory ? { mandatory: true } : {},
|
|
2792
|
+
...opt.required || opt.optional ? { takesValue: true } : {},
|
|
2793
|
+
...opt.defaultValue === void 0 ? {} : { default: opt.defaultValue }
|
|
2794
|
+
};
|
|
2795
|
+
}
|
|
2796
|
+
var RETURN_SHAPES = returns_default.commands;
|
|
2797
|
+
function shapeOf(path) {
|
|
2798
|
+
return RETURN_SHAPES[path];
|
|
2799
|
+
}
|
|
2800
|
+
var activeProbe;
|
|
2801
|
+
function describeNode(cmd, parentPath, depth) {
|
|
2802
|
+
const path = [...parentPath, cmd.name()];
|
|
2803
|
+
const children = cmd.commands.filter((c) => !c.name().startsWith("help"));
|
|
2804
|
+
const state = activeProbe ? availabilityOf(path.join(" "), activeProbe) : void 0;
|
|
2805
|
+
const skeleton = {
|
|
2806
|
+
path: path.join(" "),
|
|
2807
|
+
name: cmd.name(),
|
|
2808
|
+
section: sectionOf(cmd),
|
|
2809
|
+
summary: cmd.description(),
|
|
2810
|
+
...shapeOf(path.join(" ")) ? { returns: shapeOf(path.join(" ")) } : {},
|
|
2811
|
+
...state ? { available: state.available } : {},
|
|
2812
|
+
...state?.reason ? { unavailable: state.reason } : {}
|
|
2813
|
+
};
|
|
2814
|
+
if (depth <= 0) return children.length ? { ...skeleton, hasCommands: true } : skeleton;
|
|
2815
|
+
const aliases = cmd.aliases();
|
|
2816
|
+
const options = cmd.options.filter((o) => o.long !== "--help");
|
|
2817
|
+
return {
|
|
2818
|
+
...skeleton,
|
|
2819
|
+
...aliases.length ? { aliases } : {},
|
|
2820
|
+
...cmd.registeredArguments.length ? {
|
|
2821
|
+
arguments: cmd.registeredArguments.map((arg, index, all) => {
|
|
2822
|
+
const from = sourceOf(arg.name(), path, index === all.length - 1);
|
|
2823
|
+
return {
|
|
2824
|
+
name: arg.name(),
|
|
2825
|
+
required: arg.required,
|
|
2826
|
+
variadic: arg.variadic,
|
|
2827
|
+
...arg.description ? { description: arg.description } : {},
|
|
2828
|
+
...from ? { from } : {}
|
|
2829
|
+
};
|
|
2830
|
+
})
|
|
2831
|
+
} : {},
|
|
2832
|
+
...options.length ? { options: options.map(describeOption) } : {},
|
|
2833
|
+
...guideOf(cmd) ? { guide: guideOf(cmd) } : {},
|
|
2834
|
+
...children.length ? { commands: children.map((child) => describeNode(child, path, depth - 1)) } : {}
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
var FIELD_MEANINGS = {
|
|
2838
|
+
returns: "top-level keys observed on a live deploy \u2014 evidence for parsing, not a contract; absent where nothing was recorded",
|
|
2839
|
+
available: "whether this deploy can answer the command (only after --probe). Checked per service and per MCP tool, so a command can still be refused for a capability the probe cannot see",
|
|
2840
|
+
unavailable: "why it cannot; absent when it can",
|
|
2841
|
+
probe: "what the probe asked and found: one read per service, plus the MCP tool catalog",
|
|
2842
|
+
path: "full command path \u2014 run it as `openbkn <path>`",
|
|
2843
|
+
section: "which section the command sits in; see `sections`",
|
|
2844
|
+
summary: "what the command does; often names the shape it answers with",
|
|
2845
|
+
hasCommands: "this walk stopped here \u2014 ask for this path to see deeper",
|
|
2846
|
+
arguments: "positional arguments, in order",
|
|
2847
|
+
"arguments[].from": "the command that hands out this argument's value",
|
|
2848
|
+
options: "flags; `mandatory` and `takesValue` appear only when true",
|
|
2849
|
+
guide: "prose the command's own --help prints under its command list",
|
|
2850
|
+
commands: "nested commands"
|
|
2851
|
+
};
|
|
2852
|
+
function resolve2(program2, path) {
|
|
2853
|
+
let node = program2;
|
|
2854
|
+
for (const name of path) {
|
|
2855
|
+
const child = node.commands.find((c) => c.name() === name || c.aliases().includes(name));
|
|
2856
|
+
if (!child) throw new InputError(`no such command: ${path.join(" ")}`);
|
|
2857
|
+
node = child;
|
|
2858
|
+
}
|
|
2859
|
+
return node;
|
|
2860
|
+
}
|
|
2861
|
+
function describeCommandTree(program2, opts = {}) {
|
|
2862
|
+
activeProbe = opts.probe;
|
|
2863
|
+
const depth = opts.depth === void 0 ? Number.MAX_SAFE_INTEGER : opts.depth - 1;
|
|
2864
|
+
if (opts.path?.length) {
|
|
2865
|
+
return {
|
|
2866
|
+
sections: SECTION_MEANINGS,
|
|
2867
|
+
fields: FIELD_MEANINGS,
|
|
2868
|
+
...describeNode(resolve2(program2, opts.path), opts.path.slice(0, -1), depth + 1)
|
|
2869
|
+
};
|
|
2870
|
+
}
|
|
2871
|
+
const top = program2.commands.filter(
|
|
2872
|
+
(c) => !c.name().startsWith("help") && c.name() !== "describe"
|
|
1945
2873
|
);
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
2874
|
+
return {
|
|
2875
|
+
name: program2.name(),
|
|
2876
|
+
version: program2.version(),
|
|
2877
|
+
summary: program2.description(),
|
|
2878
|
+
sections: SECTION_MEANINGS,
|
|
2879
|
+
fields: FIELD_MEANINGS,
|
|
2880
|
+
...opts.probe ? { probe: opts.probe } : {},
|
|
2881
|
+
commands: top.map((cmd) => describeNode(cmd, [], depth)),
|
|
2882
|
+
globalOptions: program2.options.filter((o) => o.long !== "--help").map(describeOption),
|
|
2883
|
+
guide: guideOf(program2)
|
|
2884
|
+
};
|
|
1957
2885
|
}
|
|
1958
|
-
|
|
1959
|
-
const
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
2886
|
+
function rows(node, indent = "") {
|
|
2887
|
+
const out = [
|
|
2888
|
+
{
|
|
2889
|
+
indent,
|
|
2890
|
+
name: `${node.path.split(" ").pop()}${node.hasCommands ? " \u2026" : ""}`,
|
|
2891
|
+
section: node.section === DEFAULT_SECTION ? "" : node.section,
|
|
2892
|
+
summary: node.available === false ? `[unavailable] ${node.unavailable ?? ""} \u2014 ${node.summary}` : node.summary
|
|
2893
|
+
}
|
|
2894
|
+
];
|
|
2895
|
+
for (const child of node.commands ?? []) out.push(...rows(child, `${indent} `));
|
|
2896
|
+
return out;
|
|
2897
|
+
}
|
|
2898
|
+
function renderText(tree) {
|
|
2899
|
+
const root = tree;
|
|
2900
|
+
const out = [];
|
|
2901
|
+
if (root.sections) {
|
|
2902
|
+
const width = Math.max(...Object.keys(root.sections).map((k) => k.length));
|
|
2903
|
+
out.push("SECTIONS");
|
|
2904
|
+
for (const [name, meaning] of Object.entries(root.sections)) {
|
|
2905
|
+
out.push(` ${name.padEnd(width)} ${meaning}`);
|
|
2906
|
+
}
|
|
2907
|
+
out.push("");
|
|
1965
2908
|
}
|
|
1966
|
-
const
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
2909
|
+
const nodes = root.path ? [tree] : root.commands ?? [];
|
|
2910
|
+
const truncated = nodes.some(function deeper(n) {
|
|
2911
|
+
return Boolean(n.hasCommands) || (n.commands ?? []).some(deeper);
|
|
2912
|
+
});
|
|
2913
|
+
const table = nodes.flatMap((node) => rows(node));
|
|
2914
|
+
const nameWidth = Math.max(...table.map((r) => r.indent.length + r.name.length));
|
|
2915
|
+
const sectionWidth = Math.max(...table.map((r) => r.section.length));
|
|
2916
|
+
for (const r of table) {
|
|
2917
|
+
const name = `${r.indent}${r.name}`.padEnd(nameWidth);
|
|
2918
|
+
out.push(`${name} ${r.section.padEnd(sectionWidth)} ${r.summary}`.trimEnd());
|
|
1971
2919
|
}
|
|
2920
|
+
if (truncated) {
|
|
2921
|
+
out.push("", "\u2026 has subcommands \u2014 `openbkn describe <command>`, or raise --depth");
|
|
2922
|
+
}
|
|
2923
|
+
return out.join("\n");
|
|
2924
|
+
}
|
|
2925
|
+
function describeCommand(program2) {
|
|
2926
|
+
const cmd = new Command8("describe").description("Print the command tree \u2014 paths, sections, flags (--json for the data)").argument("[command...]", "only this subtree, e.g. `describe bkn metric`").option(
|
|
2927
|
+
"--depth <n>",
|
|
2928
|
+
"how many levels to walk (1 = this level only)",
|
|
2929
|
+
(v) => Number.parseInt(v, 10)
|
|
2930
|
+
).option("--pretty", "indent the JSON instead of packing it onto one line").option("--probe", "ask this deploy which commands it can answer (read-only, ~7 requests)").action(async (path, opts, self) => {
|
|
2931
|
+
const probe = opts.probe ? await probeDeploy(self, (/* @__PURE__ */ new Date()).toISOString()) : void 0;
|
|
2932
|
+
const tree = describeCommandTree(program2, { path, depth: opts.depth, probe });
|
|
2933
|
+
const out = outputOptions(self);
|
|
2934
|
+
if (!out.json && !out.compact && !opts.pretty) {
|
|
2935
|
+
process.stdout.write(`${renderText(tree)}
|
|
2936
|
+
`);
|
|
2937
|
+
return;
|
|
2938
|
+
}
|
|
2939
|
+
printJson(tree, { ...out, json: Boolean(opts.pretty), compact: !opts.pretty });
|
|
2940
|
+
});
|
|
2941
|
+
return group(cmd, "COMMANDS");
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
// src/commands/function.ts
|
|
2945
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
2946
|
+
import { Command as Command9 } from "commander";
|
|
2947
|
+
var int5 = (v) => Number.parseInt(v, 10);
|
|
2948
|
+
function readCode(file) {
|
|
1972
2949
|
try {
|
|
1973
|
-
|
|
1974
|
-
const data = await handler(client, url.searchParams, body);
|
|
1975
|
-
res.writeHead(200, { "content-type": "application/json" });
|
|
1976
|
-
res.end(stringifyBigIntJSON(data ?? null));
|
|
2950
|
+
return readFileSync4(file === "-" ? 0 : file, "utf8");
|
|
1977
2951
|
} catch (err) {
|
|
1978
|
-
|
|
1979
|
-
|
|
2952
|
+
throw new InputError(
|
|
2953
|
+
`Cannot read ${file === "-" ? "stdin" : file}: ${err instanceof Error ? err.message : err}`
|
|
2954
|
+
);
|
|
1980
2955
|
}
|
|
1981
2956
|
}
|
|
2957
|
+
function collectDep(value, previous = []) {
|
|
2958
|
+
const at = value.lastIndexOf("@");
|
|
2959
|
+
const name = at > 0 ? value.slice(0, at) : value;
|
|
2960
|
+
const version = at > 0 ? value.slice(at + 1) : void 0;
|
|
2961
|
+
if (!name) throw new InputError("--dep takes <name> or <name>@<version>");
|
|
2962
|
+
return [...previous, version ? { name, version } : { name }];
|
|
2963
|
+
}
|
|
2964
|
+
function parseJsonOption(raw, label) {
|
|
2965
|
+
if (raw === void 0) return void 0;
|
|
2966
|
+
try {
|
|
2967
|
+
return parseBigIntJSON(raw);
|
|
2968
|
+
} catch {
|
|
2969
|
+
throw new InputError(`--${label} must be valid JSON`);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
function definitionFlags(c) {
|
|
2973
|
+
return c.option("--name <n>", "name; required when the definition is a function").option("--description <d>", "what it does \u2014 the model reads this to decide when to call it").option("--type <t>", "function | openapi", "function").option("--inputs <json>", "input parameters: [{name,type,required,description}]").option("--outputs <json>", "output parameters, same shape as --inputs").option("--dep <name@version>", "package to install before running (repeatable)", collectDep).option("--index-url <url>", "package index to install from");
|
|
2974
|
+
}
|
|
2975
|
+
function parameterList(raw, label) {
|
|
2976
|
+
const parsed = parseJsonOption(raw, label);
|
|
2977
|
+
if (parsed === void 0) return void 0;
|
|
2978
|
+
if (!Array.isArray(parsed)) throw new InputError(`--${label} must be a JSON array of parameters`);
|
|
2979
|
+
return parsed;
|
|
2980
|
+
}
|
|
2981
|
+
function functionDefinitionFrom(file, opts) {
|
|
2982
|
+
if (!opts.name) throw new InputError("--name is required for a function");
|
|
2983
|
+
return {
|
|
2984
|
+
name: opts.name,
|
|
2985
|
+
description: opts.description,
|
|
2986
|
+
code: readCode(file),
|
|
2987
|
+
inputs: parameterList(opts.inputs, "inputs"),
|
|
2988
|
+
outputs: parameterList(opts.outputs, "outputs"),
|
|
2989
|
+
dependencies: opts.dep,
|
|
2990
|
+
dependenciesUrl: opts.indexUrl
|
|
2991
|
+
};
|
|
2992
|
+
}
|
|
2993
|
+
function functionCommand() {
|
|
2994
|
+
const cmd = new Command9("function").description(
|
|
2995
|
+
"Sandbox functions: run Python on the platform without registering anything"
|
|
2996
|
+
);
|
|
2997
|
+
cmd.command("run <file>").description("Run a file (or `-` for stdin) in the sandbox; exits non-zero when the code does").option("--event <json>", "the single argument handler() receives", "{}").option("--timeout <s>", "sandbox timeout in seconds", int5).option("--dep <name@version>", "install a package first (repeatable)", collectDep).option("--index-url <url>", "package index to install from (default PyPI)").option(
|
|
2998
|
+
"--pass-token",
|
|
2999
|
+
"put your credential in the sandbox's BKN_TOKEN so `sandbox_sdk.bkn` calls BKN as you"
|
|
3000
|
+
).action(async (file, opts, cmd2) => {
|
|
3001
|
+
const client = clientFrom(cmd2);
|
|
3002
|
+
const result = await client.functions.run({
|
|
3003
|
+
code: readCode(file),
|
|
3004
|
+
event: parseJsonOption(opts.event, "event") ?? {},
|
|
3005
|
+
timeout: opts.timeout,
|
|
3006
|
+
dependencies: opts.dep,
|
|
3007
|
+
dependenciesUrl: opts.indexUrl,
|
|
3008
|
+
source: "openbkn_cli",
|
|
3009
|
+
// The request headers carry these too, but they stop at the service:
|
|
3010
|
+
// the sandbox reads its own environment, which only these fields fill.
|
|
3011
|
+
conversationId: client.ctx.trace?.conversationId,
|
|
3012
|
+
interactionId: client.ctx.trace?.interactionId,
|
|
3013
|
+
...opts.passToken ? { bknToken: client.ctx.token } : {}
|
|
3014
|
+
});
|
|
3015
|
+
printJson(result, outputOptions(cmd2));
|
|
3016
|
+
if (result.exit_code !== void 0 && result.exit_code !== 0) process.exitCode = 1;
|
|
3017
|
+
});
|
|
3018
|
+
cmd.command("infer-schema <file>").description(
|
|
3019
|
+
"Derive a tool contract from @tool-decorated code; runs it, answers supported:false when it cannot"
|
|
3020
|
+
).action(async (file, _opts, cmd2) => {
|
|
3021
|
+
printJson(await clientFrom(cmd2).functions.inferSchema(readCode(file)), outputOptions(cmd2));
|
|
3022
|
+
});
|
|
3023
|
+
cmd.command("deps").description("Libraries already installed in the sandbox \u2014 import these without --dep").action(async (_opts, cmd2) => {
|
|
3024
|
+
printJson(await clientFrom(cmd2).functions.dependencies(), outputOptions(cmd2));
|
|
3025
|
+
});
|
|
3026
|
+
cmd.command("versions <package>").description("Versions of one package, asked of the package index live").option("--python <v>", "keep only versions compatible with this Python").option("--index-url <url>", "package index to ask (default PyPI)").action(async (pkg, opts, cmd2) => {
|
|
3027
|
+
printJson(
|
|
3028
|
+
await clientFrom(cmd2).functions.dependencyVersions(pkg, {
|
|
3029
|
+
pythonVersion: opts.python,
|
|
3030
|
+
pypiRepoUrl: opts.indexUrl
|
|
3031
|
+
}),
|
|
3032
|
+
outputOptions(cmd2)
|
|
3033
|
+
);
|
|
3034
|
+
});
|
|
3035
|
+
cmd.command("template").description("The handler() skeleton to start from").option("--type <t>", "template type (python)", "python").action(async (opts, cmd2) => {
|
|
3036
|
+
printJson(await clientFrom(cmd2).functions.template(opts.type), outputOptions(cmd2));
|
|
3037
|
+
});
|
|
3038
|
+
groupChildren(cmd, {
|
|
3039
|
+
READ: ["deps", "versions", "template"],
|
|
3040
|
+
RUN: ["run", "infer-schema"]
|
|
3041
|
+
});
|
|
3042
|
+
guide(
|
|
3043
|
+
cmd,
|
|
3044
|
+
`THE ONE HARD RULE
|
|
3045
|
+
The entry point must be a function named \`handler\`, taking one argument:
|
|
3046
|
+
|
|
3047
|
+
def handler(event: Dict[str, Any]) -> Any:
|
|
3048
|
+
return {"sum": event.get("a", 0) + event.get("b", 0)}
|
|
3049
|
+
|
|
3050
|
+
\`--event\` is that argument, the return value comes back as \`result\`, and
|
|
3051
|
+
\`print\` output as \`stdout\`. \`function template\` prints the skeleton.
|
|
3052
|
+
|
|
3053
|
+
READING THE ANSWER
|
|
3054
|
+
Code that raises still answers HTTP 200 \u2014 \`exit_code\` is the verdict and the
|
|
3055
|
+
traceback is in \`stderr\`. This command exits non-zero to match, so \`&&\` works.
|
|
3056
|
+
|
|
3057
|
+
CONTEXT INSIDE THE SANDBOX
|
|
3058
|
+
--conversation-id / --interaction-id reach the sandbox as BKN_CONVERSATION_ID
|
|
3059
|
+
and BKN_INTERACTION_ID, which is how \`sandbox_sdk.bkn\` hangs its own BKN calls
|
|
3060
|
+
under your interaction. The credential does not travel unless you say so:
|
|
3061
|
+
--pass-token puts it in BKN_TOKEN so that code runs as you.
|
|
3062
|
+
|
|
3063
|
+
ORDER OF WORK
|
|
3064
|
+
function deps what is already importable
|
|
3065
|
+
function run ./add.py --event ... iterate here; nothing is kept
|
|
3066
|
+
toolbox create --type function a box to keep it in
|
|
3067
|
+
tool create ./add.py --toolbox the same code, now a tool
|
|
3068
|
+
tool enable <tool-id> --toolbox a tool is off until enabled, then agents
|
|
3069
|
+
can call it`
|
|
3070
|
+
);
|
|
3071
|
+
return group(cmd, "TOOLS & SKILLS");
|
|
3072
|
+
}
|
|
1982
3073
|
|
|
1983
3074
|
// src/commands/model.ts
|
|
1984
3075
|
import { Command as Command10 } from "commander";
|
|
1985
|
-
var
|
|
3076
|
+
var int6 = (v) => Number.parseInt(v, 10);
|
|
1986
3077
|
async function resolveLlmModelName(client, model) {
|
|
1987
3078
|
if (!/^\d+$/.test(model)) return model;
|
|
1988
3079
|
const detail = await client.models.llm.get(model);
|
|
@@ -1990,25 +3081,34 @@ async function resolveLlmModelName(client, model) {
|
|
|
1990
3081
|
return detail.model_name;
|
|
1991
3082
|
}
|
|
1992
3083
|
function addManagementCommands(parent, kind) {
|
|
1993
|
-
parent.command("add").description("Register a model (definition JSON via --body / --body-file)").option(
|
|
3084
|
+
parent.command("add").description("Register a model (definition JSON via --body / --body-file)").option(
|
|
3085
|
+
"--body <json>",
|
|
3086
|
+
"model definition JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (mf-model-manager)"
|
|
3087
|
+
).option("--body-file <path>", "read model definition JSON from a file").action(async (opts, cmd) => {
|
|
1994
3088
|
printJson(await clientFrom(cmd).models[kind].add(readBody(opts)), outputOptions(cmd));
|
|
1995
3089
|
});
|
|
1996
|
-
parent.command("edit").description("Update a model definition (JSON via --body / --body-file)").option(
|
|
3090
|
+
parent.command("edit").description("Update a model definition (JSON via --body / --body-file)").option(
|
|
3091
|
+
"--body <json>",
|
|
3092
|
+
"model definition JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (mf-model-manager)"
|
|
3093
|
+
).option("--body-file <path>", "read model definition JSON from a file").action(async (opts, cmd) => {
|
|
1997
3094
|
printJson(await clientFrom(cmd).models[kind].edit(readBody(opts)), outputOptions(cmd));
|
|
1998
3095
|
});
|
|
1999
3096
|
parent.command("delete <model-ids>").description("Delete model(s) (comma-joined ids)").action(async (ids, _o, cmd) => {
|
|
2000
3097
|
printJson(await clientFrom(cmd).models[kind].delete(csv(ids) ?? []), outputOptions(cmd));
|
|
2001
3098
|
});
|
|
2002
|
-
parent.command("test").description("Test a model's connectivity / inference (JSON via --body / --body-file)").option(
|
|
3099
|
+
parent.command("test").description("Test a model's connectivity / inference (JSON via --body / --body-file)").option(
|
|
3100
|
+
"--body <json>",
|
|
3101
|
+
"test request JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (mf-model-manager)"
|
|
3102
|
+
).option("--body-file <path>", "read test request JSON from a file").action(async (opts, cmd) => {
|
|
2003
3103
|
printJson(await clientFrom(cmd).models[kind].test(readBody(opts)), outputOptions(cmd));
|
|
2004
3104
|
});
|
|
2005
3105
|
}
|
|
2006
3106
|
function modelCommand() {
|
|
2007
3107
|
const model = new Command10("model").description(
|
|
2008
|
-
"
|
|
3108
|
+
"Large and small models: chat, embeddings, rerank, defaults"
|
|
2009
3109
|
);
|
|
2010
3110
|
const llm = model.command("llm").description("Large language models");
|
|
2011
|
-
llm.command("list").description("List LLM models").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size",
|
|
3111
|
+
llm.command("list").description("List LLM models \u2192 {data, count}").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size", int6, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int6, 1).action(async (opts, cmd) => {
|
|
2012
3112
|
printJson(
|
|
2013
3113
|
await clientFrom(cmd).models.llm.list({
|
|
2014
3114
|
name: opts.name,
|
|
@@ -2041,7 +3141,7 @@ function modelCommand() {
|
|
|
2041
3141
|
});
|
|
2042
3142
|
addManagementCommands(llm, "llm");
|
|
2043
3143
|
const small = model.command("small").description("Small models (embedding / reranker)");
|
|
2044
|
-
small.command("list").description("List small models").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size",
|
|
3144
|
+
small.command("list").description("List small models \u2192 {data, count}").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size", int6, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int6, 1).action(async (opts, cmd) => {
|
|
2045
3145
|
printJson(
|
|
2046
3146
|
await clientFrom(cmd).models.small.list({
|
|
2047
3147
|
name: opts.name,
|
|
@@ -2092,15 +3192,22 @@ Examples:
|
|
|
2092
3192
|
$ openbkn model small get-default --type embedding # current default
|
|
2093
3193
|
$ openbkn model small set-default <id> # default embedding/reranker`
|
|
2094
3194
|
);
|
|
2095
|
-
|
|
3195
|
+
for (const kind of [llm, small]) {
|
|
3196
|
+
groupChildren(kind, {
|
|
3197
|
+
READ: ["list", "get", "get-default"],
|
|
3198
|
+
RUN: ["chat", "embeddings", "rerank", "test"],
|
|
3199
|
+
WRITE: ["add", "edit", "delete", "set-default", "unset-default"]
|
|
3200
|
+
});
|
|
3201
|
+
}
|
|
3202
|
+
return group(model, "MODELS");
|
|
2096
3203
|
}
|
|
2097
3204
|
|
|
2098
3205
|
// src/commands/resource.ts
|
|
2099
3206
|
import { Command as Command11 } from "commander";
|
|
2100
|
-
var
|
|
3207
|
+
var int7 = (v) => Number.parseInt(v, 10);
|
|
2101
3208
|
function resourceCommand() {
|
|
2102
|
-
const cmd = new Command11("resource").alias("res").description("
|
|
2103
|
-
cmd.command("list").description("List resources under a catalog").option("--catalog-id <id>", "filter by catalog id").option("--category <c>", "resource category (table | logicview | dataset)").option("--type <c>", "alias of --category").option("--status <status>", "filter by status").option("--schema <name>", "filter by source schema").option("--limit <n>", "page size",
|
|
3209
|
+
const cmd = new Command11("resource").alias("res").description("Tables and views behind a network: find, inspect, sample, enable, disable");
|
|
3210
|
+
cmd.command("list").description("List resources under a catalog").option("--catalog-id <id>", "filter by catalog id").option("--category <c>", "resource category (table | logicview | dataset)").option("--type <c>", "alias of --category").option("--status <status>", "filter by status").option("--schema <name>", "filter by source schema").option("--limit <n>", "page size", int7, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int7, 0).option("--sort <field>", "sort field: name | create_time | update_time").option("--direction <dir>", "sort direction: asc | desc").action(async (opts, cmd2) => {
|
|
2104
3211
|
const data = await clientFrom(cmd2).resource.list({
|
|
2105
3212
|
catalogId: opts.catalogId,
|
|
2106
3213
|
category: opts.category ?? opts.type,
|
|
@@ -2113,7 +3220,7 @@ function resourceCommand() {
|
|
|
2113
3220
|
});
|
|
2114
3221
|
printJson(data, outputOptions(cmd2));
|
|
2115
3222
|
});
|
|
2116
|
-
cmd.command("find").description("Search resources by name
|
|
3223
|
+
cmd.command("find").description("Search resources by name, fuzzy unless --exact \u2192 a bare array, not an envelope").requiredOption("--name <name>", "resource name to search").option("--exact", "exact name match").option("--catalog-id <id>", "limit to a catalog").option("--limit <n>", "rows to scan before filtering", int7, DEFAULT_LIST_LIMIT).action(async (opts, cmd2) => {
|
|
2117
3224
|
const data = await clientFrom(cmd2).resource.find(opts.name, {
|
|
2118
3225
|
exact: opts.exact,
|
|
2119
3226
|
catalogId: opts.catalogId,
|
|
@@ -2124,7 +3231,14 @@ function resourceCommand() {
|
|
|
2124
3231
|
cmd.command("get <id>").description("Get resource details").action(async (id, _opts, cmd2) => {
|
|
2125
3232
|
printJson(await clientFrom(cmd2).resource.get(id), outputOptions(cmd2));
|
|
2126
3233
|
});
|
|
2127
|
-
|
|
3234
|
+
for (const action of ["enable", "disable"]) {
|
|
3235
|
+
cmd.command(`${action} <id>`).description(`${action[0]?.toUpperCase()}${action.slice(1)} a resource`).action(async (id, _opts, cmd2) => {
|
|
3236
|
+
const api = clientFrom(cmd2).resource;
|
|
3237
|
+
const result = action === "enable" ? await api.enable(id) : await api.disable(id);
|
|
3238
|
+
printJson(result, outputOptions(cmd2));
|
|
3239
|
+
});
|
|
3240
|
+
}
|
|
3241
|
+
cmd.command("query <id>").description("Fetch data rows from a resource").option("--limit <n>", "row limit", int7, DEFAULT_QUERY_LIMIT).option("--offset <n>", "row offset", int7, 0).option("--paging-mode <mode>", "paging mode: single | cursor").option("--keep-alive-sec <s>", "cursor keep-alive in seconds (60\u20133600)", int7).option("--cursor <cursor>", "opaque cursor returned by the previous page").option("--need-total", "include total count").action(async (id, opts, cmd2) => {
|
|
2128
3242
|
const data = await clientFrom(cmd2).resource.query(id, {
|
|
2129
3243
|
limit: opts.limit,
|
|
2130
3244
|
offset: opts.offset,
|
|
@@ -2138,12 +3252,17 @@ function resourceCommand() {
|
|
|
2138
3252
|
cmd.command("delete <id>").description("Delete a resource").option("-y, --yes", "skip confirmation").action(async (id, _opts, cmd2) => {
|
|
2139
3253
|
printJson(await clientFrom(cmd2).resource.delete(id), outputOptions(cmd2));
|
|
2140
3254
|
});
|
|
2141
|
-
|
|
3255
|
+
groupChildren(cmd, {
|
|
3256
|
+
READ: ["list", "find", "get"],
|
|
3257
|
+
RUN: ["query"],
|
|
3258
|
+
WRITE: ["enable", "disable", "delete"]
|
|
3259
|
+
});
|
|
3260
|
+
return group(cmd, "DATA & KNOWLEDGE");
|
|
2142
3261
|
}
|
|
2143
3262
|
|
|
2144
3263
|
// src/commands/skill.ts
|
|
2145
3264
|
import { Command as Command12 } from "commander";
|
|
2146
|
-
var
|
|
3265
|
+
var int8 = (v) => Number.parseInt(v, 10);
|
|
2147
3266
|
var positiveInt = (flag) => (v) => {
|
|
2148
3267
|
if (!/^\d+$/.test(v)) {
|
|
2149
3268
|
throw new InputError(`${flag} must be a positive integer (got '${v}')`);
|
|
@@ -2168,9 +3287,15 @@ function checkSource(source) {
|
|
|
2168
3287
|
}
|
|
2169
3288
|
var draftOption = (c) => c.option("--draft", "read the draft (management) version instead of the published one");
|
|
2170
3289
|
function skillCommand() {
|
|
2171
|
-
const cmd = new Command12("skill").description(
|
|
2172
|
-
|
|
2173
|
-
|
|
3290
|
+
const cmd = new Command12("skill").description(
|
|
3291
|
+
"Skill packages (SKILL.md + files) agents load on demand"
|
|
3292
|
+
);
|
|
3293
|
+
const listOpts = (c) => c.option("--name <s>", "filter by name").option("--source <s>", "filter by source").option("--status <s>", "filter by status").option("--limit <n>", "page size", int8, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int8, 1);
|
|
3294
|
+
listOpts(
|
|
3295
|
+
cmd.command("list").description(
|
|
3296
|
+
"List skills \u2192 {data, total, page, page_size, has_next}; the id to reuse is `skill_id`"
|
|
3297
|
+
)
|
|
3298
|
+
).option("--create-user <s>", "filter by creator").action(async (opts, cmd2) => {
|
|
2174
3299
|
printJson(
|
|
2175
3300
|
await clientFrom(cmd2).skills.list({
|
|
2176
3301
|
name: opts.name,
|
|
@@ -2186,19 +3311,19 @@ function skillCommand() {
|
|
|
2186
3311
|
cmd.command("get <skill-id>").description("Get a skill by id").action(async (id, _opts, cmd2) => {
|
|
2187
3312
|
printJson(await clientFrom(cmd2).skills.get(id), outputOptions(cmd2));
|
|
2188
3313
|
});
|
|
2189
|
-
listOpts(
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
)
|
|
2200
|
-
|
|
2201
|
-
);
|
|
3314
|
+
listOpts(
|
|
3315
|
+
cmd.command("market").description("Browse the skill market \u2192 {data, total, page, has_next}")
|
|
3316
|
+
).action(async (opts, cmd2) => {
|
|
3317
|
+
printJson(
|
|
3318
|
+
await clientFrom(cmd2).skills.market({
|
|
3319
|
+
name: opts.name,
|
|
3320
|
+
source: opts.source,
|
|
3321
|
+
pageSize: opts.limit,
|
|
3322
|
+
page: opts.page
|
|
3323
|
+
}),
|
|
3324
|
+
outputOptions(cmd2)
|
|
3325
|
+
);
|
|
3326
|
+
});
|
|
2202
3327
|
cmd.command("market-get <skill-id>").description("Get a market skill by id").action(async (id, _opts, cmd2) => {
|
|
2203
3328
|
printJson(await clientFrom(cmd2).skills.marketGet(id), outputOptions(cmd2));
|
|
2204
3329
|
});
|
|
@@ -2325,7 +3450,10 @@ ${files.length} files, ${bytes} B
|
|
|
2325
3450
|
cmd.command("install <skill-id> [directory]").description("Download a skill archive and extract it locally").action(async (skillId, dir, _o, cmd2) => {
|
|
2326
3451
|
printJson(await clientFrom(cmd2).skills.install(skillId, dir), outputOptions(cmd2));
|
|
2327
3452
|
});
|
|
2328
|
-
cmd.command("update-metadata <skill-id>").description("Update a skill's metadata (--body / --body-file JSON)").option(
|
|
3453
|
+
cmd.command("update-metadata <skill-id>").description("Update a skill's metadata (--body / --body-file JSON)").option(
|
|
3454
|
+
"--body <json>",
|
|
3455
|
+
"metadata JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (execution-factory)"
|
|
3456
|
+
).option("--body-file <path>", "read metadata JSON from a file").action(async (skillId, opts, cmd2) => {
|
|
2329
3457
|
printJson(
|
|
2330
3458
|
await clientFrom(cmd2).skills.updateMetadata(skillId, readBody(opts)),
|
|
2331
3459
|
outputOptions(cmd2)
|
|
@@ -2343,15 +3471,53 @@ ${files.length} files, ${bytes} B
|
|
|
2343
3471
|
outputOptions(cmd2)
|
|
2344
3472
|
);
|
|
2345
3473
|
});
|
|
2346
|
-
|
|
3474
|
+
groupChildren(cmd, {
|
|
3475
|
+
READ: [
|
|
3476
|
+
"list",
|
|
3477
|
+
"market",
|
|
3478
|
+
"get",
|
|
3479
|
+
"market-get",
|
|
3480
|
+
"names",
|
|
3481
|
+
"content",
|
|
3482
|
+
"read-file",
|
|
3483
|
+
"files",
|
|
3484
|
+
"history"
|
|
3485
|
+
],
|
|
3486
|
+
RUN: ["execute", "download", "install"],
|
|
3487
|
+
WRITE: [
|
|
3488
|
+
"register",
|
|
3489
|
+
"update-metadata",
|
|
3490
|
+
"update-package",
|
|
3491
|
+
"set-status",
|
|
3492
|
+
"republish",
|
|
3493
|
+
"publish-history",
|
|
3494
|
+
"delete"
|
|
3495
|
+
]
|
|
3496
|
+
});
|
|
3497
|
+
guide(
|
|
3498
|
+
cmd,
|
|
3499
|
+
`READING A SKILL
|
|
3500
|
+
content <id> gives the SKILL.md index; files <id> [path] walks the package; read-file
|
|
3501
|
+
pulls one file. Read progressively \u2014 do not download the whole archive to answer a question.
|
|
3502
|
+
|
|
3503
|
+
PUBLISHED VS DRAFT
|
|
3504
|
+
Read commands return the published version. --draft reads the editing copy instead, which
|
|
3505
|
+
is what a Studio user sees. The two differ whenever changes are unpublished.
|
|
3506
|
+
|
|
3507
|
+
AUTHORING
|
|
3508
|
+
register <dir> zips and registers; update-package replaces the files; update-metadata
|
|
3509
|
+
changes only the metadata. set-status and republish move versions around.`
|
|
3510
|
+
);
|
|
3511
|
+
return group(cmd, "TOOLS & SKILLS");
|
|
2347
3512
|
}
|
|
2348
3513
|
|
|
2349
3514
|
// src/commands/toolbox.ts
|
|
2350
3515
|
import { Command as Command13 } from "commander";
|
|
2351
|
-
|
|
3516
|
+
import yaml from "js-yaml";
|
|
3517
|
+
var int9 = (v) => Number.parseInt(v, 10);
|
|
2352
3518
|
function toolboxCommand() {
|
|
2353
|
-
const cmd = new Command13("toolbox").description("
|
|
2354
|
-
cmd.command("list").description("List toolboxes").option("--keyword <s>", "filter by keyword").option("--limit <n>", "page size",
|
|
3519
|
+
const cmd = new Command13("toolbox").description("Toolboxes: group tools into one publishable box");
|
|
3520
|
+
cmd.command("list").description("List toolboxes").option("--keyword <s>", "filter by keyword").option("--limit <n>", "page size", int9, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int9, 0).action(async (opts, cmd2) => {
|
|
2355
3521
|
printJson(
|
|
2356
3522
|
await clientFrom(cmd2).toolboxes.list({
|
|
2357
3523
|
keyword: opts.keyword,
|
|
@@ -2361,12 +3527,21 @@ function toolboxCommand() {
|
|
|
2361
3527
|
outputOptions(cmd2)
|
|
2362
3528
|
);
|
|
2363
3529
|
});
|
|
2364
|
-
cmd.command("create").description(
|
|
3530
|
+
cmd.command("create").description(
|
|
3531
|
+
"Create a toolbox \u2014 openapi proxies to a service, function holds platform functions"
|
|
3532
|
+
).requiredOption("--name <name>", "toolbox name").option("--service-url <url>", "where an openapi box proxies its tools; required for that type").option("--type <t>", "openapi | function", "openapi").option("--description <d>", "description").action(async (opts, cmd2) => {
|
|
3533
|
+
if (opts.type !== "openapi" && opts.type !== "function") {
|
|
3534
|
+
throw new InputError("--type must be openapi or function");
|
|
3535
|
+
}
|
|
3536
|
+
if (opts.type === "openapi" && !opts.serviceUrl) {
|
|
3537
|
+
throw new InputError("--service-url is required for an openapi toolbox");
|
|
3538
|
+
}
|
|
2365
3539
|
printJson(
|
|
2366
3540
|
await clientFrom(cmd2).toolboxes.create({
|
|
2367
3541
|
name: opts.name,
|
|
2368
3542
|
serviceUrl: opts.serviceUrl,
|
|
2369
|
-
description: opts.description
|
|
3543
|
+
description: opts.description,
|
|
3544
|
+
metadataType: opts.type
|
|
2370
3545
|
}),
|
|
2371
3546
|
outputOptions(cmd2)
|
|
2372
3547
|
);
|
|
@@ -2389,11 +3564,36 @@ function toolboxCommand() {
|
|
|
2389
3564
|
cmd.command("import <file>").description("Import a toolbox config from a local .adp file").option("--type <t>", "impex type: toolbox | mcp | operator", "toolbox").action(async (file, opts, cmd2) => {
|
|
2390
3565
|
printJson(await clientFrom(cmd2).toolboxes.import(file, opts.type), outputOptions(cmd2));
|
|
2391
3566
|
});
|
|
2392
|
-
|
|
3567
|
+
groupChildren(cmd, {
|
|
3568
|
+
READ: ["list", "export"],
|
|
3569
|
+
WRITE: ["create", "publish", "unpublish", "delete", "import"]
|
|
3570
|
+
});
|
|
3571
|
+
guide(
|
|
3572
|
+
cmd,
|
|
3573
|
+
`TWO KINDS OF BOX
|
|
3574
|
+
--type openapi its tools proxy to --service-url; they come from a spec
|
|
3575
|
+
--type function its tools are platform functions, no service URL to give
|
|
3576
|
+
|
|
3577
|
+
ORDER OF WORK
|
|
3578
|
+
toolbox create --name "<n>" an empty box, in draft
|
|
3579
|
+
tool create ./add.py --toolbox a function tool, or --type openapi for a spec
|
|
3580
|
+
tool enable <tool-ids...> a tool is off until enabled
|
|
3581
|
+
toolbox publish <box-id> the box becomes visible in the market
|
|
3582
|
+
tool execute <tool-id> call an enabled tool
|
|
3583
|
+
tool debug <tool-id> call one that is not, while building it
|
|
3584
|
+
|
|
3585
|
+
Publishing the box is about the market, not about calling: an enabled tool in
|
|
3586
|
+
an unpublished box executes. \`tool enable\` is the gate.
|
|
3587
|
+
|
|
3588
|
+
export / import move a whole box between deploys as an .adp file.`
|
|
3589
|
+
);
|
|
3590
|
+
return group(cmd, "TOOLS & SKILLS");
|
|
2393
3591
|
}
|
|
2394
3592
|
function toolCommand() {
|
|
2395
|
-
const cmd = new Command13("tool").description(
|
|
2396
|
-
|
|
3593
|
+
const cmd = new Command13("tool").description(
|
|
3594
|
+
"Tools in a box: add one from code or a spec, enable it, call it"
|
|
3595
|
+
);
|
|
3596
|
+
cmd.command("list").description("List tools in a toolbox").requiredOption("--toolbox <box-id>", "toolbox id").option("--limit <n>", "page size (backend default 10, max 100)", int9).option("--page <n>", "page (1-based; backend default 1)", int9).option("--all", "return every tool, ignoring page size").action(async (opts, cmd2) => {
|
|
2397
3597
|
printJson(
|
|
2398
3598
|
await clientFrom(cmd2).toolboxes.tools(opts.toolbox, {
|
|
2399
3599
|
page: opts.page,
|
|
@@ -2415,7 +3615,10 @@ function toolCommand() {
|
|
|
2415
3615
|
outputOptions(cmd2)
|
|
2416
3616
|
);
|
|
2417
3617
|
});
|
|
2418
|
-
const invokeOpts = (c) => c.requiredOption("--toolbox <box-id>", "toolbox id").option(
|
|
3618
|
+
const invokeOpts = (c) => c.requiredOption("--toolbox <box-id>", "toolbox id").option(
|
|
3619
|
+
"--body <json>",
|
|
3620
|
+
"request body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (execution-factory)"
|
|
3621
|
+
).option("--header <json>", "headers map JSON").option("--query <json>", "query params JSON").option("--path <json>", "path params JSON").option("--timeout <s>", "per-call timeout seconds", int9);
|
|
2419
3622
|
const parseJson = (s, label) => {
|
|
2420
3623
|
if (!s) return void 0;
|
|
2421
3624
|
try {
|
|
@@ -2431,39 +3634,101 @@ function toolCommand() {
|
|
|
2431
3634
|
path: parseJson(opts.path, "path"),
|
|
2432
3635
|
timeout: opts.timeout ? Number(opts.timeout) : void 0
|
|
2433
3636
|
});
|
|
3637
|
+
invokeOpts(cmd.command("execute <tool-id>").description("Invoke an enabled tool")).action(
|
|
3638
|
+
async (toolId, opts, cmd2) => {
|
|
3639
|
+
printJson(
|
|
3640
|
+
await clientFrom(cmd2).toolboxes.execute(opts.toolbox, toolId, buildEnvelope(opts)),
|
|
3641
|
+
outputOptions(cmd2)
|
|
3642
|
+
);
|
|
3643
|
+
}
|
|
3644
|
+
);
|
|
2434
3645
|
invokeOpts(
|
|
2435
|
-
cmd.command("
|
|
3646
|
+
cmd.command("debug <tool-id>").description("Invoke a tool that is not enabled yet")
|
|
2436
3647
|
).action(async (toolId, opts, cmd2) => {
|
|
2437
3648
|
printJson(
|
|
2438
|
-
await clientFrom(cmd2).toolboxes.
|
|
3649
|
+
await clientFrom(cmd2).toolboxes.debug(opts.toolbox, toolId, buildEnvelope(opts)),
|
|
2439
3650
|
outputOptions(cmd2)
|
|
2440
3651
|
);
|
|
2441
3652
|
});
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
3653
|
+
const toolFrom = (file, opts) => {
|
|
3654
|
+
if (opts.type === "openapi") {
|
|
3655
|
+
let data;
|
|
3656
|
+
try {
|
|
3657
|
+
data = yaml.load(readCode(file));
|
|
3658
|
+
} catch (err) {
|
|
3659
|
+
throw new InputError(
|
|
3660
|
+
`${file} is not valid JSON or YAML: ${err instanceof Error ? err.message : err}`
|
|
3661
|
+
);
|
|
3662
|
+
}
|
|
3663
|
+
return { metadataType: "openapi", data, useRule: opts.useRule };
|
|
3664
|
+
}
|
|
3665
|
+
if (opts.type !== "function") throw new InputError("--type must be function or openapi");
|
|
3666
|
+
return {
|
|
3667
|
+
metadataType: "function",
|
|
3668
|
+
function: functionDefinitionFrom(file, opts),
|
|
3669
|
+
useRule: opts.useRule
|
|
3670
|
+
};
|
|
3671
|
+
};
|
|
3672
|
+
definitionFlags(
|
|
3673
|
+
cmd.command("create <file>").description(
|
|
3674
|
+
"Create a tool from code (or a spec) \u2014 the only way to add a function tool to a box"
|
|
3675
|
+
).requiredOption("--toolbox <box-id>", "target toolbox id").option("--use-rule <s>", "usage rule carried onto the tool")
|
|
3676
|
+
).action(async (file, opts, cmd2) => {
|
|
3677
|
+
const result = await clientFrom(cmd2).toolboxes.createTool(
|
|
3678
|
+
opts.toolbox,
|
|
3679
|
+
toolFrom(file, opts)
|
|
3680
|
+
);
|
|
3681
|
+
printJson(result, outputOptions(cmd2));
|
|
3682
|
+
if (result?.failure_count) process.exitCode = 1;
|
|
3683
|
+
});
|
|
3684
|
+
cmd.command("get <tool-id>").description("One tool in full: metadata, parameters, usage rule").requiredOption("--toolbox <box-id>", "toolbox id").action(async (toolId, opts, cmd2) => {
|
|
3685
|
+
printJson(await clientFrom(cmd2).toolboxes.getTool(opts.toolbox, toolId), outputOptions(cmd2));
|
|
3686
|
+
});
|
|
3687
|
+
definitionFlags(
|
|
3688
|
+
cmd.command("update <tool-id> <file>").description("Replace a tool's definition; the id survives and an enabled tool stays enabled").requiredOption("--toolbox <box-id>", "toolbox id").option("--use-rule <s>", "usage rule carried onto the tool")
|
|
3689
|
+
).action(async (toolId, file, opts, cmd2) => {
|
|
3690
|
+
if (!opts.name || !opts.description) {
|
|
3691
|
+
throw new InputError(
|
|
3692
|
+
"--name and --description are required: update replaces the tool, it does not patch it"
|
|
3693
|
+
);
|
|
3694
|
+
}
|
|
2445
3695
|
printJson(
|
|
2446
|
-
await clientFrom(cmd2).toolboxes.
|
|
3696
|
+
await clientFrom(cmd2).toolboxes.updateTool(opts.toolbox, toolId, {
|
|
3697
|
+
...toolFrom(file, opts),
|
|
3698
|
+
name: opts.name,
|
|
3699
|
+
description: opts.description
|
|
3700
|
+
}),
|
|
2447
3701
|
outputOptions(cmd2)
|
|
2448
3702
|
);
|
|
2449
3703
|
});
|
|
2450
|
-
cmd.command("
|
|
3704
|
+
cmd.command("delete <tool-ids...>").description("Delete tools from a toolbox").requiredOption("--toolbox <box-id>", "toolbox id").option("-y, --yes", "skip confirmation").action(async (toolIds, opts, cmd2) => {
|
|
3705
|
+
printJson(
|
|
3706
|
+
await clientFrom(cmd2).toolboxes.deleteTools(opts.toolbox, toolIds),
|
|
3707
|
+
outputOptions(cmd2)
|
|
3708
|
+
);
|
|
3709
|
+
});
|
|
3710
|
+
cmd.command("upload <file>").description("Add tools from an OpenAPI file \u2014 `tool create` is the same endpoint, as JSON").requiredOption("--toolbox <id>", "target toolbox id").option("--metadata-type <t>", "metadata type", "openapi").action(async (file, opts, cmd2) => {
|
|
2451
3711
|
printJson(
|
|
2452
3712
|
await clientFrom(cmd2).toolboxes.upload(opts.toolbox, file, opts.metadataType),
|
|
2453
3713
|
outputOptions(cmd2)
|
|
2454
3714
|
);
|
|
2455
3715
|
});
|
|
2456
|
-
|
|
3716
|
+
groupChildren(cmd, {
|
|
3717
|
+
READ: ["list", "get"],
|
|
3718
|
+
RUN: ["execute", "debug"],
|
|
3719
|
+
WRITE: ["create", "update", "delete", "enable", "disable", "upload"]
|
|
3720
|
+
});
|
|
3721
|
+
return group(cmd, "TOOLS & SKILLS");
|
|
2457
3722
|
}
|
|
2458
3723
|
|
|
2459
3724
|
// src/commands/trace.ts
|
|
2460
|
-
import { readFileSync as
|
|
3725
|
+
import { readFileSync as readFileSync6, writeFileSync } from "fs";
|
|
2461
3726
|
import { Command as Command14 } from "commander";
|
|
2462
3727
|
|
|
2463
3728
|
// src/bkn-trace/schema-validate.ts
|
|
2464
|
-
import { readFileSync as
|
|
3729
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
2465
3730
|
import { extname } from "path";
|
|
2466
|
-
import
|
|
3731
|
+
import yaml2 from "js-yaml";
|
|
2467
3732
|
import { z } from "zod";
|
|
2468
3733
|
var Assertion = z.object({
|
|
2469
3734
|
type: z.enum([
|
|
@@ -2498,9 +3763,9 @@ var DiagnosisRule = z.object({
|
|
|
2498
3763
|
params: z.record(z.string(), z.unknown()).optional()
|
|
2499
3764
|
});
|
|
2500
3765
|
function parseFile(file) {
|
|
2501
|
-
const text =
|
|
3766
|
+
const text = readFileSync5(file, "utf8");
|
|
2502
3767
|
const ext = extname(file).toLowerCase();
|
|
2503
|
-
if (ext === ".yaml" || ext === ".yml") return
|
|
3768
|
+
if (ext === ".yaml" || ext === ".yml") return yaml2.load(text);
|
|
2504
3769
|
return parseBigIntJSON(text);
|
|
2505
3770
|
}
|
|
2506
3771
|
function inferKind(data) {
|
|
@@ -2572,7 +3837,7 @@ function renderTechnicalTraceDetail(detail) {
|
|
|
2572
3837
|
}
|
|
2573
3838
|
function traceCommand() {
|
|
2574
3839
|
const cmd = new Command14("trace").description(
|
|
2575
|
-
"
|
|
3840
|
+
"Inspect what an agent actually did, and diagnose bad answers"
|
|
2576
3841
|
);
|
|
2577
3842
|
cmd.command("graph <trace-id>").description("Fetch normalized trace graph by trace id").action(async (traceId, _opts, cmd2) => {
|
|
2578
3843
|
printJson(await clientFrom(cmd2).trace.graph(traceId), outputOptions(cmd2));
|
|
@@ -2653,7 +3918,10 @@ function traceCommand() {
|
|
|
2653
3918
|
);
|
|
2654
3919
|
});
|
|
2655
3920
|
for (const action of ["complete", "fail", "cancel", "handoff"]) {
|
|
2656
|
-
interactions.command(`${action} <interaction-id>`).description(`${action} a managed interaction using a 3.0 completion manifest`).requiredOption(
|
|
3921
|
+
interactions.command(`${action} <interaction-id>`).description(`${action} a managed interaction using a 3.0 completion manifest`).requiredOption(
|
|
3922
|
+
"--body-file <path>",
|
|
3923
|
+
"read completion manifest JSON from a protected file \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (agent-observability)"
|
|
3924
|
+
).action(async (interactionId, opts, cmd2) => {
|
|
2657
3925
|
const input = readBody(opts);
|
|
2658
3926
|
const lifecycle = clientFrom(cmd2).trace.lifecycle;
|
|
2659
3927
|
const terminal = {
|
|
@@ -2682,7 +3950,10 @@ function traceCommand() {
|
|
|
2682
3950
|
outputOptions(cmd2)
|
|
2683
3951
|
);
|
|
2684
3952
|
});
|
|
2685
|
-
operations.command("retry <operation-id>").description("Create the next retry attempt for an eligible failed operation").requiredOption(
|
|
3953
|
+
operations.command("retry <operation-id>").description("Create the next retry attempt for an eligible failed operation").requiredOption(
|
|
3954
|
+
"--body-file <path>",
|
|
3955
|
+
"read retry request JSON from a protected file \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (agent-observability)"
|
|
3956
|
+
).action(async (operationId, opts, cmd2) => {
|
|
2686
3957
|
printJson(
|
|
2687
3958
|
await clientFrom(cmd2).trace.lifecycle.retryOperationAttempt(
|
|
2688
3959
|
operationId,
|
|
@@ -2713,7 +3984,7 @@ function traceCommand() {
|
|
|
2713
3984
|
outputOptions(cmd2)
|
|
2714
3985
|
);
|
|
2715
3986
|
});
|
|
2716
|
-
cmd.command("search").description("List authorized technical traces").option("--limit <n>", "page size, 1..200", (value) => Number.parseInt(value, 10)).option("--cursor <cursor>", "opaque pagination cursor").option("--from <time>", "started at or after this RFC3339 timestamp").option("--to <time>", "started at or before this RFC3339 timestamp").option("--status <status>", "execution status").option("--service <service>", "exact producing service").option("--tool <tool>", "exact root tool").option("--trace-id <id>", "exact Trace ID").option("--error-keyword <text>", "case-insensitive error text").option("--conversation-id <id>", "exact conversation ID").option("--interaction-id <id>", "exact interaction ID").action(async (opts, cmd2) => {
|
|
3987
|
+
cmd.command("search").description("List authorized technical traces \u2192 {entries, total, next_cursor, partial}").option("--limit <n>", "page size, 1..200", (value) => Number.parseInt(value, 10)).option("--cursor <cursor>", "opaque pagination cursor").option("--from <time>", "started at or after this RFC3339 timestamp").option("--to <time>", "started at or before this RFC3339 timestamp").option("--status <status>", "execution status").option("--service <service>", "exact producing service").option("--tool <tool>", "exact root tool").option("--trace-id <id>", "exact Trace ID").option("--error-keyword <text>", "case-insensitive error text").option("--conversation-id <id>", "exact conversation ID").option("--interaction-id <id>", "exact interaction ID").action(async (opts, cmd2) => {
|
|
2717
3988
|
printJson(
|
|
2718
3989
|
await clientFrom(cmd2).trace.search({
|
|
2719
3990
|
limit: opts.limit,
|
|
@@ -2746,9 +4017,9 @@ function traceCommand() {
|
|
|
2746
4017
|
outputOptions(cmd2)
|
|
2747
4018
|
);
|
|
2748
4019
|
});
|
|
2749
|
-
const evalSet = cmd.command("eval-set").description("Build
|
|
4020
|
+
const evalSet = cmd.command("eval-set").description("Build trace eval sets");
|
|
2750
4021
|
evalSet.command("build <queries-file>").description("Build eval cases from a queries JSON file").option("--out <file>", "write the cases JSON here (default: stdout)").action(async (queriesFile, opts, cmd2) => {
|
|
2751
|
-
const raw = parseBigIntJSON(
|
|
4022
|
+
const raw = parseBigIntJSON(readFileSync6(queriesFile, "utf8"));
|
|
2752
4023
|
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2753
4024
|
if (opts.out) {
|
|
2754
4025
|
writeFileSync(opts.out, stringifyBigIntJSON({ cases }, 2));
|
|
@@ -2757,16 +4028,6 @@ function traceCommand() {
|
|
|
2757
4028
|
printJson({ cases }, outputOptions(cmd2));
|
|
2758
4029
|
}
|
|
2759
4030
|
});
|
|
2760
|
-
evalSet.command("test <cases-file>").description("Run an eval set against an agent (--llm enables semantic_match)").requiredOption("--agent <id>", "agent id to run the queries against").option("--version <v>", "agent version", "v0").option("--llm", "enable semantic_match assertions via the local `claude` CLI").action(async (casesFile, opts, cmd2) => {
|
|
2761
|
-
const raw = parseBigIntJSON(readFileSync5(casesFile, "utf8"));
|
|
2762
|
-
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2763
|
-
const result = await clientFrom(cmd2).trace.evalSetTest(opts.agent, cases, {
|
|
2764
|
-
version: opts.version,
|
|
2765
|
-
llm: Boolean(opts.llm)
|
|
2766
|
-
});
|
|
2767
|
-
printJson(result, outputOptions(cmd2));
|
|
2768
|
-
if (result.failed > 0) process.exitCode = 1;
|
|
2769
|
-
});
|
|
2770
4031
|
const schema = cmd.command("schema").description("Validate eval-set / diagnosis-rule files");
|
|
2771
4032
|
schema.command("validate <file>").description("Validate an eval-set or diagnosis-rule file (JSON/YAML) against its schema").option("--kind <k>", "force schema kind: eval-set | rule (default: auto-detect)").action(async (file, opts, cmd2) => {
|
|
2772
4033
|
const result = validateSchemaFile(file, opts.kind);
|
|
@@ -2778,12 +4039,33 @@ function traceCommand() {
|
|
|
2778
4039
|
printJson(result, outputOptions(cmd2));
|
|
2779
4040
|
if (!result.ok) process.exitCode = 1;
|
|
2780
4041
|
});
|
|
2781
|
-
|
|
4042
|
+
groupChildren(cmd, {
|
|
4043
|
+
GROUPS: ["conversations", "interactions", "operations", "receipts", "eval-set", "schema"],
|
|
4044
|
+
READ: ["graph", "get", "search", "detail", "spans"],
|
|
4045
|
+
RUN: ["diagnose", "scan", "validate-fixture"]
|
|
4046
|
+
});
|
|
4047
|
+
guide(
|
|
4048
|
+
cmd,
|
|
4049
|
+
`FINDING A CONVERSATION
|
|
4050
|
+
conversations list gives conversation ids; get <conversation-id> pulls its spans.
|
|
4051
|
+
|
|
4052
|
+
DIAGNOSING
|
|
4053
|
+
diagnose <conversation-id> symbolic rules only, no model needed
|
|
4054
|
+
diagnose <conversation-id> --llm adds rubric judging + a synthesized summary; needs a
|
|
4055
|
+
local \`claude\` CLI on PATH, silently degrades without it
|
|
4056
|
+
scan <id,id,...> the same over several conversations, aggregated
|
|
4057
|
+
|
|
4058
|
+
MANAGED LIFECYCLE
|
|
4059
|
+
conversations / interactions / operations / receipts are the write side: an agent opens an
|
|
4060
|
+
interaction, reports operations, then completes it. Those bodies are 3.0 manifests,
|
|
4061
|
+
documented at https://openbkn-ai.github.io/bkn-foundry/ (agent-observability).`
|
|
4062
|
+
);
|
|
4063
|
+
return group(cmd, "TRACING");
|
|
2782
4064
|
}
|
|
2783
4065
|
|
|
2784
4066
|
// src/commands/vega.ts
|
|
2785
4067
|
import { Command as Command15 } from "commander";
|
|
2786
|
-
var
|
|
4068
|
+
var int10 = (value) => {
|
|
2787
4069
|
const parsed = Number(value);
|
|
2788
4070
|
if (!Number.isSafeInteger(parsed)) {
|
|
2789
4071
|
throw new InputError(`expected an integer, received "${value}"`);
|
|
@@ -2878,6 +4160,16 @@ var buildTaskSort = (raw) => {
|
|
|
2878
4160
|
}
|
|
2879
4161
|
return parsed.data;
|
|
2880
4162
|
};
|
|
4163
|
+
var buildTaskExecuteType = (raw) => {
|
|
4164
|
+
if (raw === void 0) return void 0;
|
|
4165
|
+
const parsed = BuildTaskExecuteType.safeParse(raw);
|
|
4166
|
+
if (!parsed.success) {
|
|
4167
|
+
throw new InputError(
|
|
4168
|
+
`invalid build task execute type "${raw}"; expected one of ${BuildTaskExecuteType.options.join(", ")}`
|
|
4169
|
+
);
|
|
4170
|
+
}
|
|
4171
|
+
return parsed.data;
|
|
4172
|
+
};
|
|
2881
4173
|
var discoverStrategy = (raw) => {
|
|
2882
4174
|
if (raw === void 0) return void 0;
|
|
2883
4175
|
const parsed = DiscoverStrategy.safeParse(raw);
|
|
@@ -2975,10 +4267,10 @@ var sortDirection = (raw) => {
|
|
|
2975
4267
|
};
|
|
2976
4268
|
function vegaCommand() {
|
|
2977
4269
|
const vega = new Command15("vega").description(
|
|
2978
|
-
"
|
|
4270
|
+
"Data sources: catalogs, connectors, SQL, index builds"
|
|
2979
4271
|
);
|
|
2980
4272
|
const catalog = vega.command("catalog").description("Catalog entries");
|
|
2981
|
-
catalog.command("list").description("List catalog entries").option("--limit <n>", "page size",
|
|
4273
|
+
catalog.command("list").description("List catalog entries").option("--limit <n>", "page size", int10, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int10, 0).option("--name <s>", "filter by name").option("--tag <s>", "filter by tag").option("--type <type>", "filter by catalog type: physical | logical").option("--connector-type <type>", "filter by connector type").option("--enabled <bool>", "filter by enabled state").option("--health-check-status <s>", "filter by health status").option("--sort <field>", "sort field: name | create_time | update_time").option("--direction <dir>", "sort direction: asc | desc").action(async (_opts, cmd) => {
|
|
2982
4274
|
const o = cmd.optsWithGlobals();
|
|
2983
4275
|
const data = await clientFrom(cmd).vega.catalogs({
|
|
2984
4276
|
limit: o.limit,
|
|
@@ -2997,7 +4289,7 @@ function vegaCommand() {
|
|
|
2997
4289
|
catalog.command("get <id>").description("Get a catalog by id").action(async (id, _opts, cmd) => {
|
|
2998
4290
|
printJson(await clientFrom(cmd).vega.getCatalog(id), outputOptions(cmd));
|
|
2999
4291
|
});
|
|
3000
|
-
catalog.command("resources <id>").description("List resources under a catalog").option("--category <c>", "filter by category (e.g. table)").option("--limit <n>", "page size (default 30, max 1000; -1 = all)",
|
|
4292
|
+
catalog.command("resources <id>").description("List resources under a catalog").option("--category <c>", "filter by category (e.g. table)").option("--limit <n>", "page size (default 30, max 1000; -1 = all)", int10).option("--offset <n>", "page offset", int10, 0).action(async (id, opts, cmd) => {
|
|
3001
4293
|
printJson(
|
|
3002
4294
|
await clientFrom(cmd).vega.catalogResources(id, opts.category, opts.limit, opts.offset),
|
|
3003
4295
|
outputOptions(cmd)
|
|
@@ -3098,7 +4390,7 @@ function vegaCommand() {
|
|
|
3098
4390
|
);
|
|
3099
4391
|
});
|
|
3100
4392
|
const discoverSchedule = vega.command("discover-schedule").description("Resource discovery schedules");
|
|
3101
|
-
discoverSchedule.command("list").description("List discovery schedules").option("--name <s>", "filter by name").option("--catalog-id <id>", "filter by catalog id").option("--enabled <bool>", "filter by enabled state", bool).option("--limit <n>", "page size",
|
|
4393
|
+
discoverSchedule.command("list").description("List discovery schedules").option("--name <s>", "filter by name").option("--catalog-id <id>", "filter by catalog id").option("--enabled <bool>", "filter by enabled state", bool).option("--limit <n>", "page size", int10, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int10, 0).option("--sort <field>", "name | create_time | update_time | next_run").option("--direction <dir>", "asc | desc").action(async (opts, cmd) => {
|
|
3102
4394
|
printJson(
|
|
3103
4395
|
await clientFrom(cmd).vega.discoverSchedules({
|
|
3104
4396
|
name: opts.name,
|
|
@@ -3115,7 +4407,7 @@ function vegaCommand() {
|
|
|
3115
4407
|
discoverSchedule.command("get <id>").description("Get a discovery schedule").action(async (id, _opts, cmd) => {
|
|
3116
4408
|
printJson(await clientFrom(cmd).vega.getDiscoverSchedule(id), outputOptions(cmd));
|
|
3117
4409
|
});
|
|
3118
|
-
discoverSchedule.command("create").description("Create a discovery schedule").requiredOption("--name <s>", "schedule name").requiredOption("--catalog-id <id>", "catalog id").requiredOption("--cron <expr>", "five-field cron expression").option("--start-time <ms>", "start time",
|
|
4410
|
+
discoverSchedule.command("create").description("Create a discovery schedule").requiredOption("--name <s>", "schedule name").requiredOption("--catalog-id <id>", "catalog id").requiredOption("--cron <expr>", "five-field cron expression").option("--start-time <ms>", "start time", int10).option("--end-time <ms>", "end time", int10).option("--enabled", "create enabled").option("--strategy <strategy>", `strategy: ${DiscoverStrategy.options.join(" | ")}`).action(async (opts, cmd) => {
|
|
3119
4411
|
printJson(
|
|
3120
4412
|
await clientFrom(cmd).vega.createDiscoverSchedule({
|
|
3121
4413
|
name: opts.name,
|
|
@@ -3129,7 +4421,7 @@ function vegaCommand() {
|
|
|
3129
4421
|
outputOptions(cmd)
|
|
3130
4422
|
);
|
|
3131
4423
|
});
|
|
3132
|
-
discoverSchedule.command("update <id>").description("Fully update a discovery schedule").requiredOption("--name <s>", "schedule name").requiredOption("--catalog-id <id>", "current catalog id").requiredOption("--cron <expr>", "five-field cron expression").requiredOption("--enabled <bool>", "current enabled state", bool).requiredOption("--start-time <ms>", "start time (0 = no lower bound)",
|
|
4424
|
+
discoverSchedule.command("update <id>").description("Fully update a discovery schedule").requiredOption("--name <s>", "schedule name").requiredOption("--catalog-id <id>", "current catalog id").requiredOption("--cron <expr>", "five-field cron expression").requiredOption("--enabled <bool>", "current enabled state", bool).requiredOption("--start-time <ms>", "start time (0 = no lower bound)", int10).requiredOption("--end-time <ms>", "end time (0 = no upper bound)", int10).requiredOption("--strategy <strategy>", `strategy: ${DiscoverStrategy.options.join(" | ")}`).requiredOption(
|
|
3133
4425
|
"--expected-update-time <ms>",
|
|
3134
4426
|
"optimistic-lock update time",
|
|
3135
4427
|
expectedUpdateTime
|
|
@@ -3156,10 +4448,11 @@ function vegaCommand() {
|
|
|
3156
4448
|
});
|
|
3157
4449
|
}
|
|
3158
4450
|
const discoverTask = vega.command("discover-task").description("Resource discovery tasks");
|
|
3159
|
-
discoverTask.command("list").description("List discovery tasks").option("--catalog-id <id>", "filter by catalog id").option("--schedule-id <id>", "filter by schedule id").option("--status <status>", `comma-separated: ${VegaTaskStatus.options.join(" | ")}`).option("--strategy <strategy>", `strategy: ${DiscoverStrategy.options.join(" | ")}`).option("--trigger-type <type>", "manual | scheduled").option("--limit <n>", "page size",
|
|
4451
|
+
discoverTask.command("list").description("List discovery tasks").option("--catalog-id <id>", "filter by catalog id").option("--resource-id <id>", "filter by resource id").option("--schedule-id <id>", "filter by schedule id").option("--status <status>", `comma-separated: ${VegaTaskStatus.options.join(" | ")}`).option("--strategy <strategy>", `strategy: ${DiscoverStrategy.options.join(" | ")}`).option("--trigger-type <type>", "manual | scheduled").option("--limit <n>", "page size", int10, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int10, 0).option("--sort <field>", "create_time | start_time | finish_time | last_progress_time").option("--direction <dir>", "asc | desc").action(async (opts, cmd) => {
|
|
3160
4452
|
printJson(
|
|
3161
4453
|
await clientFrom(cmd).vega.discoverTasks({
|
|
3162
4454
|
catalogId: opts.catalogId,
|
|
4455
|
+
resourceId: opts.resourceId,
|
|
3163
4456
|
scheduleId: opts.scheduleId,
|
|
3164
4457
|
status: taskStatuses(opts.status),
|
|
3165
4458
|
strategy: discoverStrategy(opts.strategy),
|
|
@@ -3187,7 +4480,7 @@ function vegaCommand() {
|
|
|
3187
4480
|
semanticTask.command("list").description("List semantic-understanding tasks").option("--scope <scope>", `scope: ${SemanticUnderstandingScope.options.join(" | ")}`).option("--catalog-id <id>", "filter by catalog id").option("--resource-id <id>", "filter by resource id").option("--status <status>", `comma-separated: ${VegaTaskStatus.options.join(" | ")}`).option(
|
|
3188
4481
|
"--apply-mode <mode>",
|
|
3189
4482
|
`apply mode: ${SemanticUnderstandingApplyMode.options.join(" | ")}`
|
|
3190
|
-
).option("--applied <bool>", "filter by applied state", bool).option("--limit <n>", "page size",
|
|
4483
|
+
).option("--applied <bool>", "filter by applied state", bool).option("--limit <n>", "page size", int10, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int10, 0).option("--sort <field>", "create_time | start_time | finish_time").option("--direction <dir>", "asc | desc").action(async (opts, cmd) => {
|
|
3191
4484
|
printJson(
|
|
3192
4485
|
await clientFrom(cmd).vega.semanticUnderstandingTasks({
|
|
3193
4486
|
scope: semanticScope(opts.scope),
|
|
@@ -3204,7 +4497,7 @@ function vegaCommand() {
|
|
|
3204
4497
|
outputOptions(cmd)
|
|
3205
4498
|
);
|
|
3206
4499
|
});
|
|
3207
|
-
semanticTask.command("create").description("Create a semantic-understanding task").requiredOption("--scope <scope>", "resource | catalog").option("--catalog-id <id>", "catalog id").option("--resource-id <id>", "resource id").option("--apply-mode <mode>", "dry_run | fill_empty | force").option("--confidence-threshold <n>", "minimum confidence (0..1)", confidenceThreshold).option("--include-sample-rows", "include resource sample rows").option("--sample-max-rows <n>", "sample row limit",
|
|
4500
|
+
semanticTask.command("create").description("Create a semantic-understanding task").requiredOption("--scope <scope>", "resource | catalog").option("--catalog-id <id>", "catalog id").option("--resource-id <id>", "resource id").option("--apply-mode <mode>", "dry_run | fill_empty | force").option("--confidence-threshold <n>", "minimum confidence (0..1)", confidenceThreshold).option("--include-sample-rows", "include resource sample rows").option("--sample-max-rows <n>", "sample row limit", int10).action(async (opts, cmd) => {
|
|
3208
4501
|
const scope = semanticScope(opts.scope);
|
|
3209
4502
|
if (!scope) throw new InputError("--scope is required");
|
|
3210
4503
|
const applyMode = semanticApplyMode(opts.applyMode);
|
|
@@ -3260,10 +4553,12 @@ function vegaCommand() {
|
|
|
3260
4553
|
connector.command("get <type>").description("Get a connector type").action(async (type, _opts, cmd) => {
|
|
3261
4554
|
printJson(await clientFrom(cmd).vega.connectorType(type), outputOptions(cmd));
|
|
3262
4555
|
});
|
|
3263
|
-
vega.command("sql").description(
|
|
4556
|
+
vega.command("sql").description(
|
|
4557
|
+
"Read-only SQL straight against a data source \u2014 no knowledge network, no Trace record"
|
|
4558
|
+
).option(
|
|
3264
4559
|
"--query <sql>",
|
|
3265
4560
|
"SQL string; reference a resource with a {{<resource-id>}} placeholder"
|
|
3266
|
-
).option("--input-dialect <dialect>", "SQL input dialect: postgres | mysql | trino | duckdb").option("--paging-mode <mode>", "paging mode: single | cursor").option("--limit <n>", "page size (cursor mode requires it)",
|
|
4561
|
+
).option("--input-dialect <dialect>", "SQL input dialect: postgres | mysql | trino | duckdb").option("--paging-mode <mode>", "paging mode: single | cursor").option("--limit <n>", "page size (cursor mode requires it)", int10).option("--offset <n>", "first-page offset", int10).option("--keep-alive-sec <s>", "cursor keep-alive in seconds (60\u20133600)", int10).option("--cursor <cursor>", "opaque cursor returned by the previous page").option("--need-total", "include the complete total count").option("--query-timeout-sec <s>", "query timeout in seconds (1\u20133600)", int10).option(
|
|
3267
4562
|
"-d, --data <json>",
|
|
3268
4563
|
"full request body as JSON (advanced; wins over individual query flags)"
|
|
3269
4564
|
).action(async (opts, cmd) => {
|
|
@@ -3307,7 +4602,7 @@ function vegaCommand() {
|
|
|
3307
4602
|
printJson(await clientFrom(cmd).vega.sql(body), outputOptions(cmd));
|
|
3308
4603
|
});
|
|
3309
4604
|
const resource = vega.command("resource").description("Vega-backend resources");
|
|
3310
|
-
resource.command("list").description("List resources").option("--catalog-id <id>", "filter by catalog id").option("--type <category>", "resource category").option("--category <category>", "alias of --type").option("--status <status>", "filter by status").option("--schema <name>", "filter by source schema").option("--limit <n>", "page size",
|
|
4605
|
+
resource.command("list").description("List resources").option("--catalog-id <id>", "filter by catalog id").option("--type <category>", "resource category").option("--category <category>", "alias of --type").option("--status <status>", "filter by status").option("--schema <name>", "filter by source schema").option("--limit <n>", "page size", int10, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int10, 0).option("--sort <field>", "sort field: name | create_time | update_time").option("--direction <dir>", "sort direction: asc | desc").action(async (opts, cmd) => {
|
|
3311
4606
|
printJson(
|
|
3312
4607
|
await clientFrom(cmd).resource.list({
|
|
3313
4608
|
catalogId: opts.catalogId,
|
|
@@ -3325,7 +4620,17 @@ function vegaCommand() {
|
|
|
3325
4620
|
resource.command("get <id>").description("Get a resource").action(async (id, _opts, cmd) => {
|
|
3326
4621
|
printJson(await clientFrom(cmd).resource.get(id), outputOptions(cmd));
|
|
3327
4622
|
});
|
|
3328
|
-
resource.command("
|
|
4623
|
+
resource.command("discover <id>").description("Trigger metadata discovery for a resource").action(async (id, _opts, cmd) => {
|
|
4624
|
+
printJson(await clientFrom(cmd).vega.discoverResource(id), outputOptions(cmd));
|
|
4625
|
+
});
|
|
4626
|
+
for (const action of ["enable", "disable"]) {
|
|
4627
|
+
resource.command(`${action} <id>`).description(`${action[0]?.toUpperCase()}${action.slice(1)} a resource`).action(async (id, _opts, cmd) => {
|
|
4628
|
+
const api = clientFrom(cmd).resource;
|
|
4629
|
+
const result = action === "enable" ? await api.enable(id) : await api.disable(id);
|
|
4630
|
+
printJson(result, outputOptions(cmd));
|
|
4631
|
+
});
|
|
4632
|
+
}
|
|
4633
|
+
resource.command("query <id>").description("Fetch data rows from a resource").option("--limit <n>", "row limit", int10, 50).option("--offset <n>", "row offset", int10, 0).action(async (id, opts, cmd) => {
|
|
3329
4634
|
printJson(
|
|
3330
4635
|
await clientFrom(cmd).resource.query(id, { limit: opts.limit, offset: opts.offset }),
|
|
3331
4636
|
outputOptions(cmd)
|
|
@@ -3337,7 +4642,10 @@ function vegaCommand() {
|
|
|
3337
4642
|
outputOptions(cmd)
|
|
3338
4643
|
);
|
|
3339
4644
|
});
|
|
3340
|
-
resource.command("document-create <resource-id>").description("Create dataset documents").requiredOption(
|
|
4645
|
+
resource.command("document-create <resource-id>").description("Create dataset documents").requiredOption(
|
|
4646
|
+
"--data <json>",
|
|
4647
|
+
"JSON array of documents \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (vega-backend)"
|
|
4648
|
+
).action(async (resourceId, opts, cmd) => {
|
|
3341
4649
|
printJson(
|
|
3342
4650
|
await clientFrom(cmd).resource.createDocuments(
|
|
3343
4651
|
resourceId,
|
|
@@ -3346,7 +4654,10 @@ function vegaCommand() {
|
|
|
3346
4654
|
outputOptions(cmd)
|
|
3347
4655
|
);
|
|
3348
4656
|
});
|
|
3349
|
-
resource.command("document-upsert <resource-id>").description("Upsert dataset documents; every document must have an id").requiredOption(
|
|
4657
|
+
resource.command("document-upsert <resource-id>").description("Upsert dataset documents; every document must have an id").requiredOption(
|
|
4658
|
+
"--data <json>",
|
|
4659
|
+
"JSON array of documents \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (vega-backend)"
|
|
4660
|
+
).action(async (resourceId, opts, cmd) => {
|
|
3350
4661
|
const documents = parseJsonArray(opts.data, "--data");
|
|
3351
4662
|
if (documents.some((document) => typeof document.id !== "string")) {
|
|
3352
4663
|
throw new InputError("every document in --data must have a string id");
|
|
@@ -3405,7 +4716,10 @@ function vegaCommand() {
|
|
|
3405
4716
|
const task = await clientFrom(cmd).vega.buildStatus(taskId);
|
|
3406
4717
|
printJson(task, outputOptions(cmd));
|
|
3407
4718
|
});
|
|
3408
|
-
dataset.command("build-list").description("List BuildTasks").option("--limit <n>", "page size",
|
|
4719
|
+
dataset.command("build-list").description("List BuildTasks").option("--limit <n>", "page size", int10, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int10, 0).option("--resource-id <id>", "filter by resource id").option("--catalog-id <id>", "filter by catalog id").option("--status <status>", `comma-separated statuses: ${BuildTaskStatus.options.join(" | ")}`).option("--mode <mode>", "filter by mode: batch | streaming").option(
|
|
4720
|
+
"--execute-type <type>",
|
|
4721
|
+
`filter by execution type: ${BuildTaskExecuteType.options.join(" | ")}`
|
|
4722
|
+
).option("--sort <field>", `sort field: ${BuildTaskSort.options.join(" | ")}`).option("--direction <dir>", `sort direction: ${SortDirection.options.join(" | ")}`).action(async (opts, cmd) => {
|
|
3409
4723
|
printJson(
|
|
3410
4724
|
await clientFrom(cmd).vega.buildTasks({
|
|
3411
4725
|
limit: opts.limit,
|
|
@@ -3414,6 +4728,7 @@ function vegaCommand() {
|
|
|
3414
4728
|
catalogId: opts.catalogId,
|
|
3415
4729
|
status: buildTaskStatuses(opts.status),
|
|
3416
4730
|
mode: opts.mode,
|
|
4731
|
+
executeType: buildTaskExecuteType(opts.executeType),
|
|
3417
4732
|
sort: buildTaskSort(opts.sort),
|
|
3418
4733
|
direction: sortDirection(opts.direction)
|
|
3419
4734
|
}),
|
|
@@ -3437,36 +4752,134 @@ function vegaCommand() {
|
|
|
3437
4752
|
outputOptions(cmd)
|
|
3438
4753
|
);
|
|
3439
4754
|
});
|
|
3440
|
-
|
|
4755
|
+
groupChildren(vega, {
|
|
4756
|
+
GROUPS: [
|
|
4757
|
+
"catalog",
|
|
4758
|
+
"resource",
|
|
4759
|
+
"connector-type",
|
|
4760
|
+
"dataset",
|
|
4761
|
+
"discover-schedule",
|
|
4762
|
+
"discover-task",
|
|
4763
|
+
"semantic-task"
|
|
4764
|
+
],
|
|
4765
|
+
RUN: ["sql"]
|
|
4766
|
+
});
|
|
4767
|
+
groupChildren(resource, {
|
|
4768
|
+
READ: ["list", "get", "document-get"],
|
|
4769
|
+
RUN: ["query", "discover"],
|
|
4770
|
+
WRITE: [
|
|
4771
|
+
"enable",
|
|
4772
|
+
"disable",
|
|
4773
|
+
"document-create",
|
|
4774
|
+
"document-upsert",
|
|
4775
|
+
"document-delete",
|
|
4776
|
+
"document-delete-filter"
|
|
4777
|
+
]
|
|
4778
|
+
});
|
|
4779
|
+
groupChildren(catalog, {
|
|
4780
|
+
READ: ["list", "get", "resources", "health", "health-check-schedule"],
|
|
4781
|
+
RUN: ["test-connection", "test-connection-config", "discover"],
|
|
4782
|
+
WRITE: ["create", "update", "enable", "disable", "delete", "set-health-check-schedule"]
|
|
4783
|
+
});
|
|
4784
|
+
guide(
|
|
4785
|
+
vega,
|
|
4786
|
+
`FINDING DATA
|
|
4787
|
+
catalog list -> catalog resources <catalog-id> -> resource get <id>. A physical catalog
|
|
4788
|
+
can be discovered and written; a logical one cannot.
|
|
4789
|
+
|
|
4790
|
+
QUERYING DIRECTLY
|
|
4791
|
+
sql --query "<sql>" runs against the source itself. Name a resource with a
|
|
4792
|
+
{{<resource-id>}} placeholder rather than the physical table it happens to have.
|
|
4793
|
+
|
|
4794
|
+
BUILDING AN INDEX
|
|
4795
|
+
dataset build <resource-id> creates a BuildTask; build-status / build-list follow it.
|
|
4796
|
+
Indexes are per resource \u2014 a knowledge network has no build of its own.`
|
|
4797
|
+
);
|
|
4798
|
+
return group(vega, "DATA & KNOWLEDGE");
|
|
4799
|
+
}
|
|
4800
|
+
|
|
4801
|
+
// src/cli-program.ts
|
|
4802
|
+
function buildProgram() {
|
|
4803
|
+
const program2 = new Command16();
|
|
4804
|
+
program2.name("openbkn").description(
|
|
4805
|
+
"openbkn \u2014 one CLI for the BKN platform: knowledge networks, the data behind them,\nthe tools and skills agents run on them, and the traces they leave."
|
|
4806
|
+
).version(package_default.version, "-V, --version", "output the version number").option("--base-url <url>", "platform base URL (env: BKN_BASE_URL)").option("--token <value>", "access token (env: BKN_TOKEN)").option("--user <id|name>", "use specific user credentials (env: BKN_USER)").option("--json", "machine-readable JSON output").option("--compact", "single-line JSON output").option("--full", "human view: show all columns (default trims to the key ones)").option("--biz-domain <s>", "business domain (alias: -bd)").option("--conversation-id <id>", "BKN Trace conversation id (env: BKN_CONVERSATION_ID)").option("--interaction-id <id>", "BKN Trace interaction id (env: BKN_INTERACTION_ID)").option(
|
|
4807
|
+
"--new-conversation",
|
|
4808
|
+
"ignore the remembered conversation for this command (see `openbkn context conversation`)"
|
|
4809
|
+
).option("-k, --insecure", "skip TLS verification (dev / self-signed only)").option("--dry-run", "print the request this command would send, and send nothing").showHelpAfterError();
|
|
4810
|
+
program2.addCommand(authCommand());
|
|
4811
|
+
program2.addCommand(configCommand());
|
|
4812
|
+
program2.addCommand(appkeyCommand());
|
|
4813
|
+
program2.addCommand(bknCommand());
|
|
4814
|
+
program2.addCommand(vegaCommand());
|
|
4815
|
+
program2.addCommand(resourceCommand());
|
|
4816
|
+
program2.addCommand(contextCommand());
|
|
4817
|
+
program2.addCommand(modelCommand());
|
|
4818
|
+
program2.addCommand(skillCommand());
|
|
4819
|
+
program2.addCommand(toolboxCommand());
|
|
4820
|
+
program2.addCommand(toolCommand());
|
|
4821
|
+
program2.addCommand(functionCommand());
|
|
4822
|
+
program2.addCommand(traceCommand());
|
|
4823
|
+
program2.addCommand(adminCommand());
|
|
4824
|
+
program2.addCommand(callCommand());
|
|
4825
|
+
program2.addCommand(describeCommand(program2));
|
|
4826
|
+
guide(
|
|
4827
|
+
program2,
|
|
4828
|
+
`FIRST STEPS
|
|
4829
|
+
openbkn auth login https://your-platform -u <user> -p <pass>
|
|
4830
|
+
openbkn bkn list # knowledge networks you can see
|
|
4831
|
+
openbkn bkn --help # every group has its own help
|
|
4832
|
+
openbkn describe --depth 1 # the whole map as one table; \`describe <command>\`
|
|
4833
|
+
# drills in, --json ships the same tree as data
|
|
4834
|
+
|
|
4835
|
+
COMMON TASKS
|
|
4836
|
+
Answer a question bkn search <kn-id> "<q>" -> context search-schema ->
|
|
4837
|
+
context query-object-instance --args '<json>'
|
|
4838
|
+
Look at the data vega catalog list -> resource find --name <t> -> resource query <id>
|
|
4839
|
+
Build from a catalog bkn create-from-catalog <catalog-id> --name "<n>" ->
|
|
4840
|
+
vega dataset build <resource-id>
|
|
4841
|
+
Edit as files bkn pull <kn-id> ./kn -> bkn validate ./kn -> bkn push ./kn
|
|
4842
|
+
Ship a capability skill register ./my-skill; toolbox create --name "<n>" ->
|
|
4843
|
+
tool upload ./api.yaml --toolbox <id> -> toolbox publish <id>
|
|
4844
|
+
Ship some code function run ./add.py -> toolbox create --name "<n>" --type function
|
|
4845
|
+
-> tool create ./add.py --toolbox <box-id> --name add ->
|
|
4846
|
+
tool enable <tool-id> --toolbox <box-id>
|
|
4847
|
+
Debug an answer trace conversations list -> trace diagnose <conversation-id> --llm
|
|
4848
|
+
|
|
4849
|
+
GOOD TO KNOW
|
|
4850
|
+
Every command group sorts its subcommands into the same four sections: GROUPS nests one
|
|
4851
|
+
level deeper, READ changes nothing, RUN acts without changing configuration (triggers a
|
|
4852
|
+
job, spends a model call, rotates a token), WRITE changes platform state \u2014 confirm those
|
|
4853
|
+
with a person first.
|
|
4854
|
+
Add --json to any command for machine-readable output (the default view trims columns,
|
|
4855
|
+
--full widens it). Most list commands answer {entries, total_count}; anything else says
|
|
4856
|
+
so in its own description. Ids come from list/search output \u2014 opaque, never guess one,
|
|
4857
|
+
and the key holding one is not always \`id\` (\`skill_id\`, \`conversation_id\`, \`ot_id\` \u2026).
|
|
4858
|
+
Multi-tenant deploys: --biz-domain picks the domain, --user switches saved logins.
|
|
4859
|
+
\`openbkn call\` reaches any endpoint a command does not cover, auth injected. Look the
|
|
4860
|
+
path up at https://openbkn-ai.github.io/bkn-foundry/ first \u2014 do not guess one.`
|
|
4861
|
+
);
|
|
4862
|
+
installGroupedHelp(program2);
|
|
4863
|
+
return program2;
|
|
3441
4864
|
}
|
|
3442
4865
|
|
|
3443
4866
|
// src/cli.ts
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
program.addCommand(authCommand());
|
|
3450
|
-
program.addCommand(callCommand());
|
|
3451
|
-
program.addCommand(configCommand());
|
|
3452
|
-
program.addCommand(appkeyCommand());
|
|
3453
|
-
program.addCommand(vegaCommand());
|
|
3454
|
-
program.addCommand(bknCommand());
|
|
3455
|
-
program.addCommand(resourceCommand());
|
|
3456
|
-
program.addCommand(contextCommand());
|
|
3457
|
-
program.addCommand(agentCommand());
|
|
3458
|
-
program.addCommand(modelCommand());
|
|
3459
|
-
program.addCommand(skillCommand());
|
|
3460
|
-
program.addCommand(toolboxCommand());
|
|
3461
|
-
program.addCommand(toolCommand());
|
|
3462
|
-
program.addCommand(traceCommand());
|
|
3463
|
-
program.addCommand(adminCommand());
|
|
3464
|
-
program.addCommand(exploreCommand());
|
|
3465
|
-
installGroupedHelp(program);
|
|
4867
|
+
process.stdout.on("error", (err) => {
|
|
4868
|
+
if (err.code === "EPIPE") process.exit(0);
|
|
4869
|
+
throw err;
|
|
4870
|
+
});
|
|
4871
|
+
var program = buildProgram();
|
|
3466
4872
|
var argv = process.argv.map((a) => a === "-bd" ? "--biz-domain" : a);
|
|
4873
|
+
if (argv.includes("--dry-run")) enableDryRun();
|
|
3467
4874
|
try {
|
|
3468
4875
|
await program.parseAsync(argv);
|
|
3469
4876
|
} catch (err) {
|
|
4877
|
+
if (err instanceof DryRunSignal) {
|
|
4878
|
+
process.stdout.write(`${JSON.stringify(err.request, null, 2)}
|
|
4879
|
+
`);
|
|
4880
|
+
await releaseLifecycleSessions();
|
|
4881
|
+
process.exit(0);
|
|
4882
|
+
}
|
|
3470
4883
|
console.error(formatError(err));
|
|
3471
4884
|
await releaseLifecycleSessions();
|
|
3472
4885
|
process.exit(toExitCode(err));
|