@openbkn/bkn-sdk 0.1.3 → 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 +18 -10
- package/README.zh.md +12 -7
- package/dist/{chunk-PC2F54XD.js → chunk-WIYRGBAB.js} +2212 -2614
- package/dist/cli.js +2428 -622
- package/dist/index.d.ts +7818 -709
- package/dist/index.js +9 -5
- package/package.json +6 -2
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
BuildTaskExecuteType,
|
|
4
|
+
BuildTaskSort,
|
|
5
|
+
BuildTaskStatus,
|
|
3
6
|
DEFAULT_BUSINESS_DOMAIN,
|
|
4
7
|
DEFAULT_LIST_LIMIT,
|
|
5
8
|
DEFAULT_QUERY_LIMIT,
|
|
9
|
+
DiscoverScheduleSort,
|
|
10
|
+
DiscoverStrategy,
|
|
11
|
+
DiscoverTaskSort,
|
|
12
|
+
DiscoverTaskTriggerType,
|
|
13
|
+
DryRunSignal,
|
|
6
14
|
HttpError,
|
|
7
15
|
InputError,
|
|
16
|
+
SemanticUnderstandingApplyMode,
|
|
17
|
+
SemanticUnderstandingScope,
|
|
18
|
+
SemanticUnderstandingTaskSort,
|
|
19
|
+
SortDirection,
|
|
20
|
+
VegaTaskStatus,
|
|
8
21
|
activePlatform,
|
|
9
22
|
attachToken,
|
|
10
23
|
changePasswordSafe,
|
|
@@ -16,6 +29,7 @@ import {
|
|
|
16
29
|
decodeJwt,
|
|
17
30
|
deletePlatform,
|
|
18
31
|
deviceLogin,
|
|
32
|
+
enableDryRun,
|
|
19
33
|
exportCreds,
|
|
20
34
|
filesUnder,
|
|
21
35
|
formatError,
|
|
@@ -25,6 +39,7 @@ import {
|
|
|
25
39
|
listPlatforms,
|
|
26
40
|
logout,
|
|
27
41
|
openBrowser,
|
|
42
|
+
parseBigIntJSON,
|
|
28
43
|
parseEmbeddingFields,
|
|
29
44
|
parsePkMap,
|
|
30
45
|
rawCall,
|
|
@@ -35,21 +50,23 @@ import {
|
|
|
35
50
|
resolveContext,
|
|
36
51
|
setActivePlatform,
|
|
37
52
|
status,
|
|
53
|
+
stringifyBigIntJSON,
|
|
38
54
|
switchUser,
|
|
39
55
|
toExitCode,
|
|
56
|
+
trimTrailingSlashes,
|
|
57
|
+
updatePlatformConfig,
|
|
40
58
|
use,
|
|
41
59
|
validateFixturePath,
|
|
42
|
-
whoami
|
|
43
|
-
|
|
44
|
-
} from "./chunk-PC2F54XD.js";
|
|
60
|
+
whoami
|
|
61
|
+
} from "./chunk-WIYRGBAB.js";
|
|
45
62
|
|
|
46
|
-
// src/cli.ts
|
|
47
|
-
import { Command as
|
|
63
|
+
// src/cli-program.ts
|
|
64
|
+
import { Command as Command16 } from "commander";
|
|
48
65
|
|
|
49
66
|
// package.json
|
|
50
67
|
var package_default = {
|
|
51
68
|
name: "@openbkn/bkn-sdk",
|
|
52
|
-
version: "0.1.
|
|
69
|
+
version: "0.1.5-rc.1",
|
|
53
70
|
description: "Unified TypeScript SDK + CLI for the BKN (Business Knowledge Network) platform.",
|
|
54
71
|
type: "module",
|
|
55
72
|
license: "Apache-2.0",
|
|
@@ -81,10 +98,14 @@ var package_default = {
|
|
|
81
98
|
dev: "tsup --watch",
|
|
82
99
|
typecheck: "tsc --noEmit",
|
|
83
100
|
"check:deps": "node scripts/check-no-self-dep.mjs",
|
|
101
|
+
"capture:returns": "node scripts/capture-returns.mjs",
|
|
84
102
|
lint: "npm run check:deps && biome check . && tsc --noEmit",
|
|
85
103
|
format: "biome format --write .",
|
|
86
104
|
test: "vitest run",
|
|
87
105
|
"test:e2e:trace-business": "npm run build && node test/e2e/bkn-trace-business-interaction.mjs",
|
|
106
|
+
"test:e2e:smoke": "npm run build && test/e2e/live-smoke.sh",
|
|
107
|
+
"test:e2e:suite": "npm run build && test/e2e/live-suite.sh",
|
|
108
|
+
"test:e2e:write": "npm run build && test/e2e/live-write.sh",
|
|
88
109
|
"test:cover": "vitest run --coverage",
|
|
89
110
|
ci: "npm run lint && npm test",
|
|
90
111
|
prepublishOnly: "npm run ci && npm run build"
|
|
@@ -102,7 +123,7 @@ var package_default = {
|
|
|
102
123
|
devDependencies: {
|
|
103
124
|
"@biomejs/biome": "^1.9.4",
|
|
104
125
|
"@types/js-yaml": "^4.0.9",
|
|
105
|
-
"@types/node": "^
|
|
126
|
+
"@types/node": "^24.0.0",
|
|
106
127
|
tsup: "^8.4.0",
|
|
107
128
|
typescript: "^5.8.0",
|
|
108
129
|
vitest: "^3.0.0"
|
|
@@ -115,14 +136,72 @@ import { Command as Command2 } from "commander";
|
|
|
115
136
|
|
|
116
137
|
// src/help/grouped-help.ts
|
|
117
138
|
var GROUP = /* @__PURE__ */ Symbol("openbkn.group");
|
|
139
|
+
var GUIDE = /* @__PURE__ */ Symbol("openbkn.guide");
|
|
118
140
|
var DEFAULT_GROUP = "COMMANDS";
|
|
119
141
|
function group(cmd, name) {
|
|
120
142
|
cmd[GROUP] = name;
|
|
121
143
|
return cmd;
|
|
122
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
|
+
}
|
|
123
189
|
function groupOf(cmd) {
|
|
124
190
|
return cmd[GROUP] ?? DEFAULT_GROUP;
|
|
125
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
|
+
}
|
|
126
205
|
function formatHelp(cmd, helper) {
|
|
127
206
|
const out = [];
|
|
128
207
|
const desc = helper.commandDescription(cmd);
|
|
@@ -138,7 +217,8 @@ function formatHelp(cmd, helper) {
|
|
|
138
217
|
if (bucket) bucket.push(c);
|
|
139
218
|
else sections.set(g, [c]);
|
|
140
219
|
}
|
|
141
|
-
|
|
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) {
|
|
142
222
|
out.push(name);
|
|
143
223
|
for (const c of cmds) {
|
|
144
224
|
out.push(` ${helper.subcommandTerm(c).padEnd(width)} ${helper.subcommandDescription(c)}`);
|
|
@@ -146,6 +226,8 @@ function formatHelp(cmd, helper) {
|
|
|
146
226
|
out.push("");
|
|
147
227
|
}
|
|
148
228
|
}
|
|
229
|
+
const extra = guideOf(cmd);
|
|
230
|
+
if (extra) out.push(extra.trim(), "");
|
|
149
231
|
const opts = helper.visibleOptions(cmd);
|
|
150
232
|
if (opts.length > 0) {
|
|
151
233
|
const width = Math.max(...opts.map((o) => helper.optionTerm(o).length));
|
|
@@ -158,11 +240,15 @@ function formatHelp(cmd, helper) {
|
|
|
158
240
|
return out.join("\n");
|
|
159
241
|
}
|
|
160
242
|
function installGroupedHelp(root) {
|
|
161
|
-
const apply = (cmd) => {
|
|
243
|
+
const apply = (cmd, path) => {
|
|
162
244
|
cmd.configureHelp({ formatHelp });
|
|
163
|
-
|
|
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()]);
|
|
164
250
|
};
|
|
165
|
-
apply(root);
|
|
251
|
+
apply(root, []);
|
|
166
252
|
}
|
|
167
253
|
|
|
168
254
|
// src/utils/org-tree.ts
|
|
@@ -181,7 +267,7 @@ function renderOrgTree(nodes, prefix = "") {
|
|
|
181
267
|
// src/utils/output.ts
|
|
182
268
|
function printJson(value, opts = {}) {
|
|
183
269
|
if (opts.json || opts.compact) {
|
|
184
|
-
const json =
|
|
270
|
+
const json = stringifyBigIntJSON(value === void 0 ? null : value, opts.compact ? 0 : 2);
|
|
185
271
|
process.stdout.write(`${json}
|
|
186
272
|
`);
|
|
187
273
|
return;
|
|
@@ -190,12 +276,12 @@ function printJson(value, opts = {}) {
|
|
|
190
276
|
process.stdout.write("(ok)\n");
|
|
191
277
|
return;
|
|
192
278
|
}
|
|
193
|
-
const
|
|
194
|
-
if (
|
|
195
|
-
const fullColumns = columnsOf(
|
|
196
|
-
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);
|
|
197
283
|
if (columns.length > 0) {
|
|
198
|
-
printTable(
|
|
284
|
+
printTable(rows2, columns);
|
|
199
285
|
const hidden = fullColumns.length - columns.length;
|
|
200
286
|
if (hidden > 0 && !opts.full) {
|
|
201
287
|
process.stdout.write(`\u2026 ${hidden} more column(s); use --full or --json for everything
|
|
@@ -208,7 +294,7 @@ function printJson(value, opts = {}) {
|
|
|
208
294
|
process.stdout.write("(no results)\n");
|
|
209
295
|
return;
|
|
210
296
|
}
|
|
211
|
-
process.stdout.write(`${
|
|
297
|
+
process.stdout.write(`${stringifyBigIntJSON(value, 2)}
|
|
212
298
|
`);
|
|
213
299
|
}
|
|
214
300
|
function isEmptyEnvelope(value) {
|
|
@@ -241,9 +327,9 @@ function toRows(value) {
|
|
|
241
327
|
}
|
|
242
328
|
return null;
|
|
243
329
|
}
|
|
244
|
-
function columnsOf(
|
|
330
|
+
function columnsOf(rows2) {
|
|
245
331
|
const seen = [];
|
|
246
|
-
for (const row of
|
|
332
|
+
for (const row of rows2) {
|
|
247
333
|
for (const k of Object.keys(row)) if (!seen.includes(k)) seen.push(k);
|
|
248
334
|
}
|
|
249
335
|
return seen;
|
|
@@ -264,16 +350,16 @@ var NOISE_COLS = /* @__PURE__ */ new Set([
|
|
|
264
350
|
]);
|
|
265
351
|
var isNoiseCol = (c) => NOISE_COLS.has(c) || /_time$/.test(c);
|
|
266
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);
|
|
267
|
-
function selectColumns(
|
|
353
|
+
function selectColumns(rows2) {
|
|
268
354
|
const isObj = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
269
|
-
const kept = columnsOf(
|
|
355
|
+
const kept = columnsOf(rows2).filter((c) => {
|
|
270
356
|
if (isNoiseCol(c)) return false;
|
|
271
|
-
const vals =
|
|
357
|
+
const vals = rows2.map((r) => r[c]);
|
|
272
358
|
if (!vals.some((v) => stringifyCell(v) !== "")) return false;
|
|
273
359
|
if (vals.every((v) => v === null || v === void 0 || isObj(v))) return false;
|
|
274
360
|
return true;
|
|
275
361
|
});
|
|
276
|
-
const isLongText = (c) =>
|
|
362
|
+
const isLongText = (c) => rows2.every((r) => {
|
|
277
363
|
const s = stringifyCell(r[c]);
|
|
278
364
|
return s === "" || s.length >= CELL_MAX - 1;
|
|
279
365
|
});
|
|
@@ -281,12 +367,12 @@ function selectColumns(rows) {
|
|
|
281
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);
|
|
282
368
|
return ordered.slice(0, MAX_COLS);
|
|
283
369
|
}
|
|
284
|
-
function printTable(
|
|
370
|
+
function printTable(rows2, columns, opts = {}) {
|
|
285
371
|
if (opts.json || opts.compact) {
|
|
286
|
-
printJson(
|
|
372
|
+
printJson(rows2, opts);
|
|
287
373
|
return;
|
|
288
374
|
}
|
|
289
|
-
const cells =
|
|
375
|
+
const cells = rows2.map((row) => columns.map((c) => stringifyCell(row[c])));
|
|
290
376
|
const widths = columns.map(
|
|
291
377
|
(col, i) => Math.max(displayWidth(col), ...cells.map((r) => displayWidth(r[i] ?? "")))
|
|
292
378
|
);
|
|
@@ -307,7 +393,7 @@ function pad(s, width) {
|
|
|
307
393
|
}
|
|
308
394
|
function stringifyCell(v) {
|
|
309
395
|
if (v === null || v === void 0) return "";
|
|
310
|
-
const raw = Array.isArray(v) && v.every((x) => x === null || typeof x !== "object") ? v.join(",") : typeof v === "object" ?
|
|
396
|
+
const raw = Array.isArray(v) && v.every((x) => x === null || typeof x !== "object") ? v.join(",") : typeof v === "object" ? stringifyBigIntJSON(v) : String(v);
|
|
311
397
|
const s = raw.replace(/\s+/g, " ").trim();
|
|
312
398
|
return s.length > CELL_MAX ? `${s.slice(0, CELL_MAX - 1)}\u2026` : s;
|
|
313
399
|
}
|
|
@@ -315,7 +401,7 @@ function stringifyCell(v) {
|
|
|
315
401
|
// src/utils/prompt.ts
|
|
316
402
|
import { createInterface } from "readline";
|
|
317
403
|
function promptLine(query, hidden = false) {
|
|
318
|
-
return new Promise((
|
|
404
|
+
return new Promise((resolve3) => {
|
|
319
405
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
320
406
|
if (hidden) {
|
|
321
407
|
const mutable = rl;
|
|
@@ -326,15 +412,33 @@ function promptLine(query, hidden = false) {
|
|
|
326
412
|
rl.question(query, (answer) => {
|
|
327
413
|
rl.close();
|
|
328
414
|
if (hidden) process.stdout.write("\n");
|
|
329
|
-
|
|
415
|
+
resolve3(answer.trim());
|
|
330
416
|
});
|
|
331
417
|
});
|
|
332
418
|
}
|
|
333
419
|
|
|
334
420
|
// src/commands/_shared.ts
|
|
335
421
|
import { readFileSync } from "fs";
|
|
422
|
+
function platformOf(o) {
|
|
423
|
+
const baseUrl = (typeof o.baseUrl === "string" ? o.baseUrl : void 0) ?? process.env.BKN_BASE_URL ?? activePlatform();
|
|
424
|
+
return baseUrl === void 0 ? void 0 : trimTrailingSlashes(baseUrl);
|
|
425
|
+
}
|
|
426
|
+
function transientIdentity(o) {
|
|
427
|
+
return Boolean(o.user || process.env.BKN_USER || o.token || process.env.BKN_TOKEN);
|
|
428
|
+
}
|
|
429
|
+
function conversationSource(o) {
|
|
430
|
+
const flag = typeof o.conversationId === "string" ? o.conversationId : void 0;
|
|
431
|
+
if (flag) return { id: flag, source: "flag" };
|
|
432
|
+
const env = process.env.BKN_CONVERSATION_ID;
|
|
433
|
+
if (env) return { id: env, source: "env" };
|
|
434
|
+
if (o.newConversation || transientIdentity(o)) return { source: "none" };
|
|
435
|
+
const baseUrl = platformOf(o);
|
|
436
|
+
const stored = baseUrl ? readPlatformConfig(baseUrl).conversationId : void 0;
|
|
437
|
+
return stored ? { id: stored, source: "stored" } : { source: "none" };
|
|
438
|
+
}
|
|
336
439
|
function traceOptionsFrom(o) {
|
|
337
|
-
const
|
|
440
|
+
const found = conversationSource(o);
|
|
441
|
+
const conversationId = found.source === "stored" ? void 0 : found.id;
|
|
338
442
|
const interactionId = (typeof o.interactionId === "string" ? o.interactionId : void 0) ?? process.env.BKN_INTERACTION_ID;
|
|
339
443
|
if (!conversationId && !interactionId) return void 0;
|
|
340
444
|
return {
|
|
@@ -345,14 +449,36 @@ function traceOptionsFrom(o) {
|
|
|
345
449
|
function clientFrom(cmd) {
|
|
346
450
|
const o = cmd.optsWithGlobals();
|
|
347
451
|
const trace = traceOptionsFrom(o);
|
|
348
|
-
|
|
452
|
+
const storeBaseUrl = platformOf(o);
|
|
453
|
+
const remembered = conversationSource(o);
|
|
454
|
+
const client = createClient({
|
|
349
455
|
baseUrl: o.baseUrl,
|
|
350
456
|
token: o.token,
|
|
351
457
|
user: o.user,
|
|
352
458
|
businessDomain: o.bizDomain,
|
|
353
459
|
insecure: o.insecure,
|
|
354
|
-
...trace ? { trace } : {}
|
|
460
|
+
...trace ? { trace } : {},
|
|
461
|
+
...remembered.source === "stored" && remembered.id ? { rememberedConversationId: remembered.id } : {},
|
|
462
|
+
// Remember a conversation this run opens, so the next command continues the
|
|
463
|
+
// same thread instead of starting a new one. Only for the active identity —
|
|
464
|
+
// `transientIdentity` explains which identities are left out.
|
|
465
|
+
// `--new-conversation` says "for this command", so it must not replace what
|
|
466
|
+
// it declined to use — otherwise one run with the flag would silently end
|
|
467
|
+
// the thread every other run was continuing.
|
|
468
|
+
...transientIdentity(o) || o.newConversation ? {} : {
|
|
469
|
+
onConversationOpened: (conversationId) => {
|
|
470
|
+
if (!storeBaseUrl) return;
|
|
471
|
+
try {
|
|
472
|
+
updatePlatformConfig(storeBaseUrl, {
|
|
473
|
+
conversationId,
|
|
474
|
+
conversationOpenedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
475
|
+
});
|
|
476
|
+
} catch {
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
355
480
|
});
|
|
481
|
+
return client;
|
|
356
482
|
}
|
|
357
483
|
function outputOptions(cmd) {
|
|
358
484
|
const o = cmd.optsWithGlobals();
|
|
@@ -366,7 +492,7 @@ function readBody(opts) {
|
|
|
366
492
|
const raw = opts.bodyFile ? readFileSync(opts.bodyFile, "utf8") : opts.body;
|
|
367
493
|
if (!raw) throw new InputError("Provide --body '<json>' or --body-file <path>.");
|
|
368
494
|
try {
|
|
369
|
-
return
|
|
495
|
+
return parseBigIntJSON(raw);
|
|
370
496
|
} catch {
|
|
371
497
|
throw new InputError("Request body is not valid JSON.");
|
|
372
498
|
}
|
|
@@ -520,16 +646,16 @@ User code: ${userCode}
|
|
|
520
646
|
}
|
|
521
647
|
const expMs = typeof me.exp === "number" ? me.exp * 1e3 : void 0;
|
|
522
648
|
const expired = expMs !== void 0 && expMs < Date.now();
|
|
523
|
-
const
|
|
649
|
+
const rows2 = [
|
|
524
650
|
["User", String(me.username ?? me.sub ?? "(unknown)")],
|
|
525
651
|
...me.name && me.name !== me.username ? [["Name", String(me.name)]] : [],
|
|
526
652
|
["ID", String(me.userId ?? me.sub ?? "-")],
|
|
527
653
|
["Platform", String(me.baseUrl ?? "-")],
|
|
528
654
|
...expMs !== void 0 ? [["Expires", `${new Date(expMs).toISOString()}${expired ? " (expired)" : ""}`]] : []
|
|
529
655
|
];
|
|
530
|
-
const pad2 = Math.max(...
|
|
656
|
+
const pad2 = Math.max(...rows2.map(([k]) => k.length));
|
|
531
657
|
process.stdout.write(
|
|
532
|
-
`${
|
|
658
|
+
`${rows2.map(([k, v]) => `${k.padEnd(pad2)} ${v}`).join("\n")}
|
|
533
659
|
\u2026 use --full or --json for all claims
|
|
534
660
|
`
|
|
535
661
|
);
|
|
@@ -557,7 +683,7 @@ User code: ${userCode}
|
|
|
557
683
|
`);
|
|
558
684
|
});
|
|
559
685
|
cmd.command("users <url>").description("List saved users for a platform (* = active)").action((url, _opts, cmd2) => {
|
|
560
|
-
const norm = url
|
|
686
|
+
const norm = trimTrailingSlashes(url);
|
|
561
687
|
const items = listPlatforms().filter((i) => i.baseUrl === norm);
|
|
562
688
|
const out = outputOptions(cmd2);
|
|
563
689
|
if (out.json || out.compact) printJson(items, out);
|
|
@@ -601,9 +727,33 @@ User code: ${userCode}
|
|
|
601
727
|
});
|
|
602
728
|
}
|
|
603
729
|
function authCommand() {
|
|
604
|
-
const cmd = new Command("auth").description("
|
|
730
|
+
const cmd = new Command("auth").description("Log in; the token is saved and reused. Start here.");
|
|
605
731
|
registerAuthLeaves(cmd);
|
|
606
|
-
|
|
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");
|
|
607
757
|
}
|
|
608
758
|
|
|
609
759
|
// src/commands/admin.ts
|
|
@@ -616,10 +766,10 @@ async function importLicenseFile(cmd, file, receipt) {
|
|
|
616
766
|
if ("stored" in res && res.stored) process.exitCode = 1;
|
|
617
767
|
}
|
|
618
768
|
function adminCommand() {
|
|
619
|
-
const admin = new Command2("admin").description("
|
|
769
|
+
const admin = new Command2("admin").description("Orgs, users, roles, license, audit log");
|
|
620
770
|
registerAuthLeaves(admin.command("auth").description("Operator authentication"));
|
|
621
771
|
const org = admin.command("org").description("Departments and org structure");
|
|
622
|
-
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) => {
|
|
623
773
|
printJson(
|
|
624
774
|
await clientFrom(cmd).admin.orgList({
|
|
625
775
|
role: opts.role,
|
|
@@ -680,7 +830,7 @@ function adminCommand() {
|
|
|
680
830
|
else console.log(renderOrgTree(tree));
|
|
681
831
|
});
|
|
682
832
|
const user = admin.command("user").description("User management");
|
|
683
|
-
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) => {
|
|
684
834
|
printJson(
|
|
685
835
|
await clientFrom(cmd).admin.userList({
|
|
686
836
|
orgId: opts.org,
|
|
@@ -766,7 +916,7 @@ function adminCommand() {
|
|
|
766
916
|
);
|
|
767
917
|
});
|
|
768
918
|
const role = admin.command("role").description("Role management");
|
|
769
|
-
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) => {
|
|
770
920
|
printJson(
|
|
771
921
|
await clientFrom(cmd).admin.roleList({ keyword: opts.keyword, limit: opts.limit }),
|
|
772
922
|
outputOptions(cmd)
|
|
@@ -868,7 +1018,10 @@ function adminCommand() {
|
|
|
868
1018
|
m.command("get <modelid>").description(`Get a ${kind} model`).action(async (id, _opts, cmd) => {
|
|
869
1019
|
printJson(await clientFrom(cmd).models[ns].get(id), outputOptions(cmd));
|
|
870
1020
|
});
|
|
871
|
-
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");
|
|
872
1025
|
if (isLlm) {
|
|
873
1026
|
add.option("--series <s>", "model series").option("--api-base <url>", "upstream API base URL").option("--icon <url>", "icon URL");
|
|
874
1027
|
} else {
|
|
@@ -877,7 +1030,10 @@ function adminCommand() {
|
|
|
877
1030
|
add.action(async (opts, cmd) => {
|
|
878
1031
|
printJson(await clientFrom(cmd).models[ns].add(modelBody(opts)), outputOptions(cmd));
|
|
879
1032
|
});
|
|
880
|
-
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");
|
|
881
1037
|
if (isLlm) {
|
|
882
1038
|
edit.option("--icon <url>", "icon URL");
|
|
883
1039
|
} else {
|
|
@@ -892,7 +1048,10 @@ function adminCommand() {
|
|
|
892
1048
|
m.command("delete <modelid...>").description(`Delete ${kind} model(s)`).action(async (ids, _opts, cmd) => {
|
|
893
1049
|
printJson(await clientFrom(cmd).models[ns].delete(ids), outputOptions(cmd));
|
|
894
1050
|
});
|
|
895
|
-
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) => {
|
|
896
1055
|
const body = opts.body || opts.bodyFile ? readBody(opts) : {};
|
|
897
1056
|
printJson(
|
|
898
1057
|
await clientFrom(cmd).models[ns].test({ model_id: id, ...body }),
|
|
@@ -941,10 +1100,12 @@ function adminCommand() {
|
|
|
941
1100
|
if (key !== "baseUrl") {
|
|
942
1101
|
throw new Error(`Unknown config key: ${key} (only baseUrl supported)`);
|
|
943
1102
|
}
|
|
944
|
-
setActivePlatform(value
|
|
1103
|
+
setActivePlatform(trimTrailingSlashes(value));
|
|
945
1104
|
printJson({ ok: true, baseUrl: value }, outputOptions(cmd));
|
|
946
1105
|
});
|
|
947
|
-
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(
|
|
948
1109
|
"-H, --header <header>",
|
|
949
1110
|
'extra header "Name: value" (repeatable)',
|
|
950
1111
|
(v, a) => {
|
|
@@ -967,132 +1128,23 @@ function adminCommand() {
|
|
|
967
1128
|
);
|
|
968
1129
|
const out = outputOptions(cmd);
|
|
969
1130
|
try {
|
|
970
|
-
printJson(
|
|
1131
|
+
printJson(parseBigIntJSON(res.body), out);
|
|
971
1132
|
} catch {
|
|
972
1133
|
process.stdout.write(res.body.endsWith("\n") ? res.body : `${res.body}
|
|
973
1134
|
`);
|
|
974
1135
|
}
|
|
975
1136
|
if (res.status >= 400) process.exitCode = 1;
|
|
976
1137
|
});
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
// src/commands/agent.ts
|
|
981
|
-
import { Command as Command3 } from "commander";
|
|
982
|
-
var int2 = (v) => Number.parseInt(v, 10);
|
|
983
|
-
function agentCommand() {
|
|
984
|
-
const cmd = new Command3("agent").description(
|
|
985
|
-
"[DEPRECATED] Decision Agent \u2014 CRUD, chat, sessions, publish (being phased out)"
|
|
986
|
-
);
|
|
987
|
-
cmd.hook("preAction", () => {
|
|
988
|
-
process.stderr.write(
|
|
989
|
-
"\u26A0\uFE0F `openbkn agent` is deprecated and may be removed in a future release.\n"
|
|
990
|
-
);
|
|
991
|
-
});
|
|
992
|
-
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) => {
|
|
993
|
-
const data = await clientFrom(cmd2).agents.list({
|
|
994
|
-
name: opts.name,
|
|
995
|
-
limit: opts.limit,
|
|
996
|
-
offset: opts.offset,
|
|
997
|
-
categoryId: opts.categoryId
|
|
998
|
-
});
|
|
999
|
-
printJson(data, outputOptions(cmd2));
|
|
1000
|
-
});
|
|
1001
|
-
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) => {
|
|
1002
|
-
const data = await clientFrom(cmd2).agents.personalList({
|
|
1003
|
-
name: opts.name,
|
|
1004
|
-
limit: opts.limit,
|
|
1005
|
-
offset: opts.offset
|
|
1006
|
-
});
|
|
1007
|
-
printJson(data, outputOptions(cmd2));
|
|
1008
|
-
});
|
|
1009
|
-
cmd.command("category-list").description("List agent categories").action(async (_opts, cmd2) => {
|
|
1010
|
-
printJson(await clientFrom(cmd2).agents.categoryList(), outputOptions(cmd2));
|
|
1011
|
-
});
|
|
1012
|
-
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) => {
|
|
1013
|
-
const data = await clientFrom(cmd2).agents.templateList({
|
|
1014
|
-
name: opts.name,
|
|
1015
|
-
limit: opts.limit,
|
|
1016
|
-
offset: opts.offset
|
|
1017
|
-
});
|
|
1018
|
-
printJson(data, outputOptions(cmd2));
|
|
1019
|
-
});
|
|
1020
|
-
cmd.command("template-get <id>").description("Get a published agent template").action(async (id, _opts, cmd2) => {
|
|
1021
|
-
printJson(await clientFrom(cmd2).agents.templateGet(id), outputOptions(cmd2));
|
|
1022
|
-
});
|
|
1023
|
-
cmd.command("get <id>").description("Get agent details").action(async (id, _opts, cmd2) => {
|
|
1024
|
-
printJson(await clientFrom(cmd2).agents.get(id), outputOptions(cmd2));
|
|
1025
|
-
});
|
|
1026
|
-
cmd.command("get-by-key <key>").description("Get an agent by key").action(async (key, _opts, cmd2) => {
|
|
1027
|
-
printJson(await clientFrom(cmd2).agents.getByKey(key), outputOptions(cmd2));
|
|
1028
|
-
});
|
|
1029
|
-
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) => {
|
|
1030
|
-
printJson(await clientFrom(cmd2).agents.create(readBody(opts)), outputOptions(cmd2));
|
|
1031
|
-
});
|
|
1032
|
-
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) => {
|
|
1033
|
-
printJson(await clientFrom(cmd2).agents.update(id, readBody(opts)), outputOptions(cmd2));
|
|
1034
|
-
});
|
|
1035
|
-
cmd.command("delete <id>").description("Delete an agent").option("-y, --yes", "skip confirmation").action(async (id, _opts, cmd2) => {
|
|
1036
|
-
printJson(await clientFrom(cmd2).agents.delete(id), outputOptions(cmd2));
|
|
1037
|
-
});
|
|
1038
|
-
cmd.command("publish <id>").description("Publish an agent").action(async (id, _opts, cmd2) => {
|
|
1039
|
-
printJson(await clientFrom(cmd2).agents.publish(id), outputOptions(cmd2));
|
|
1040
|
-
});
|
|
1041
|
-
cmd.command("unpublish <id>").description("Unpublish an agent").action(async (id, _opts, cmd2) => {
|
|
1042
|
-
printJson(await clientFrom(cmd2).agents.unpublish(id), outputOptions(cmd2));
|
|
1043
|
-
});
|
|
1044
|
-
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) => {
|
|
1045
|
-
printJson(
|
|
1046
|
-
await clientFrom(cmd2).agents.sessions(agentKey, { size: opts.limit, page: opts.page }),
|
|
1047
|
-
outputOptions(cmd2)
|
|
1048
|
-
);
|
|
1049
|
-
});
|
|
1050
|
-
cmd.command("history <agent> <conversation-id>").description("Show message history for a conversation").action(async (agentKey, conversationId, _opts, cmd2) => {
|
|
1051
|
-
printJson(await clientFrom(cmd2).agents.history(agentKey, conversationId), outputOptions(cmd2));
|
|
1052
|
-
});
|
|
1053
|
-
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) => {
|
|
1054
|
-
const client = clientFrom(cmd2);
|
|
1055
|
-
if (opts.stream) {
|
|
1056
|
-
const res = await client.agents.chat(agentId, opts.message, {
|
|
1057
|
-
version: opts.version,
|
|
1058
|
-
conversationId: opts.conversationId,
|
|
1059
|
-
stream: true,
|
|
1060
|
-
onDelta: (t) => process.stdout.write(t)
|
|
1061
|
-
});
|
|
1062
|
-
process.stdout.write("\n");
|
|
1063
|
-
if (res.conversationId) console.error(`conversation_id: ${res.conversationId}`);
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
printJson(
|
|
1067
|
-
await client.agents.chat(agentId, opts.message, {
|
|
1068
|
-
version: opts.version,
|
|
1069
|
-
conversationId: opts.conversationId
|
|
1070
|
-
}),
|
|
1071
|
-
outputOptions(cmd2)
|
|
1072
|
-
);
|
|
1073
|
-
});
|
|
1074
|
-
cmd.command("trace <conversation-id>").description("Get trace spans for a conversation (agent-scoped alias of `trace get`)").action(async (conversationId, _opts, cmd2) => {
|
|
1075
|
-
printJson(await clientFrom(cmd2).trace.spans(conversationId), outputOptions(cmd2));
|
|
1076
|
-
});
|
|
1077
|
-
const skill = cmd.command("skill").description("Manage skills attached to an agent");
|
|
1078
|
-
skill.command("list <agent-id>").description("List skill ids attached to an agent").action(async (agentId, _opts, cmd2) => {
|
|
1079
|
-
printJson(await clientFrom(cmd2).agents.skillList(agentId), outputOptions(cmd2));
|
|
1080
|
-
});
|
|
1081
|
-
skill.command("add <agent-id> <skill-ids>").description("Attach skill(s) to an agent (comma-joined ids)").action(async (agentId, ids, _opts, cmd2) => {
|
|
1082
|
-
printJson(await clientFrom(cmd2).agents.skillAdd(agentId, csv(ids) ?? []), outputOptions(cmd2));
|
|
1083
|
-
});
|
|
1084
|
-
skill.command("remove <agent-id> <skill-ids>").description("Detach skill(s) from an agent (comma-joined ids)").action(async (agentId, ids, _opts, cmd2) => {
|
|
1085
|
-
printJson(
|
|
1086
|
-
await clientFrom(cmd2).agents.skillRemove(agentId, csv(ids) ?? []),
|
|
1087
|
-
outputOptions(cmd2)
|
|
1088
|
-
);
|
|
1138
|
+
groupChildren(admin, {
|
|
1139
|
+
GROUPS: ["org", "user", "role", "llm", "small-model", "license", "audit", "auth", "config"],
|
|
1140
|
+
RUN: ["call"]
|
|
1089
1141
|
});
|
|
1090
|
-
return group(
|
|
1142
|
+
return group(admin, "ADMINISTRATION");
|
|
1091
1143
|
}
|
|
1092
1144
|
|
|
1093
1145
|
// src/commands/appkey.ts
|
|
1094
|
-
import { Command as
|
|
1095
|
-
var
|
|
1146
|
+
import { Command as Command3 } from "commander";
|
|
1147
|
+
var int2 = (v) => Number.parseInt(v, 10);
|
|
1096
1148
|
var DAY_MS = 864e5;
|
|
1097
1149
|
function printNewKey(created, out) {
|
|
1098
1150
|
if (out.json || out.compact) {
|
|
@@ -1114,13 +1166,13 @@ function printNewKey(created, out) {
|
|
|
1114
1166
|
`);
|
|
1115
1167
|
}
|
|
1116
1168
|
function appkeyCommand() {
|
|
1117
|
-
const appkey = new
|
|
1118
|
-
"
|
|
1169
|
+
const appkey = new Command3("appkey").description(
|
|
1170
|
+
"Issue long-lived `bak_` keys for scripts and services"
|
|
1119
1171
|
);
|
|
1120
|
-
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) => {
|
|
1121
1173
|
printJson(await clientFrom(cmd).appKeys.list(), outputOptions(cmd));
|
|
1122
1174
|
});
|
|
1123
|
-
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) => {
|
|
1124
1176
|
let expiresAt = opts.expiresAt;
|
|
1125
1177
|
if (opts.expireDays !== void 0) {
|
|
1126
1178
|
if (!Number.isFinite(opts.expireDays) || opts.expireDays <= 0) {
|
|
@@ -1154,11 +1206,18 @@ function appkeyCommand() {
|
|
|
1154
1206
|
await clientFrom(cmd).appKeys.adminRevoke(id);
|
|
1155
1207
|
printJson({ revoked: id }, outputOptions(cmd));
|
|
1156
1208
|
});
|
|
1157
|
-
|
|
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");
|
|
1158
1217
|
}
|
|
1159
1218
|
|
|
1160
1219
|
// src/commands/bkn.ts
|
|
1161
|
-
import { Command as
|
|
1220
|
+
import { Command as Command4 } from "commander";
|
|
1162
1221
|
|
|
1163
1222
|
// src/utils/bkn-validate.ts
|
|
1164
1223
|
import { existsSync, readFileSync as readFileSync3, readdirSync, statSync } from "fs";
|
|
@@ -1276,10 +1335,12 @@ function validateBknDirectory(dirPath) {
|
|
|
1276
1335
|
}
|
|
1277
1336
|
|
|
1278
1337
|
// src/commands/bkn.ts
|
|
1279
|
-
var
|
|
1338
|
+
var int3 = (v) => Number.parseInt(v, 10);
|
|
1280
1339
|
function bknCommand() {
|
|
1281
|
-
const bkn = new
|
|
1282
|
-
|
|
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) => {
|
|
1283
1344
|
const o = cmd.optsWithGlobals();
|
|
1284
1345
|
const data = await clientFrom(cmd).kn.list({
|
|
1285
1346
|
limit: o.limit,
|
|
@@ -1298,10 +1359,17 @@ function bknCommand() {
|
|
|
1298
1359
|
});
|
|
1299
1360
|
printJson(data, outputOptions(cmd));
|
|
1300
1361
|
});
|
|
1301
|
-
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) => {
|
|
1302
1365
|
const data = await clientFrom(cmd).kn.search(knId, query, {
|
|
1303
|
-
|
|
1304
|
-
|
|
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
|
|
1305
1373
|
});
|
|
1306
1374
|
printJson(data, outputOptions(cmd));
|
|
1307
1375
|
});
|
|
@@ -1319,16 +1387,22 @@ function bknCommand() {
|
|
|
1319
1387
|
);
|
|
1320
1388
|
});
|
|
1321
1389
|
if (crud) {
|
|
1322
|
-
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) => {
|
|
1323
1391
|
printJson(await clientFrom(cmd).kn[`${crud}Get`](knId, id), outputOptions(cmd));
|
|
1324
1392
|
});
|
|
1325
|
-
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) => {
|
|
1326
1397
|
printJson(
|
|
1327
1398
|
await clientFrom(cmd).kn[`${crud}Create`](knId, readBody(opts)),
|
|
1328
1399
|
outputOptions(cmd)
|
|
1329
1400
|
);
|
|
1330
1401
|
});
|
|
1331
|
-
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) => {
|
|
1332
1406
|
printJson(
|
|
1333
1407
|
await clientFrom(cmd).kn[`${crud}Update`](knId, id, readBody(opts)),
|
|
1334
1408
|
outputOptions(cmd)
|
|
@@ -1340,21 +1414,24 @@ function bknCommand() {
|
|
|
1340
1414
|
}
|
|
1341
1415
|
}
|
|
1342
1416
|
const actionType = bkn.commands.find((c) => c.name() === "action-type");
|
|
1343
|
-
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) => {
|
|
1344
1421
|
printJson(
|
|
1345
1422
|
await clientFrom(cmd).kn.actionTypeQuery(knId, atId, readBody(opts)),
|
|
1346
1423
|
outputOptions(cmd)
|
|
1347
1424
|
);
|
|
1348
1425
|
});
|
|
1349
|
-
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) => {
|
|
1350
1430
|
printJson(
|
|
1351
1431
|
await clientFrom(cmd).kn.actionTypeExecute(knId, atId, readBody(opts)),
|
|
1352
1432
|
outputOptions(cmd)
|
|
1353
1433
|
);
|
|
1354
1434
|
});
|
|
1355
|
-
actionType?.command("inputs <kn-id> <at-id>").description("Get an action type's input schema").action(async (knId, atId, _o, cmd) => {
|
|
1356
|
-
printJson(await clientFrom(cmd).kn.actionTypeInputs(knId, atId), outputOptions(cmd));
|
|
1357
|
-
});
|
|
1358
1435
|
actionType?.command("get <kn-id> <at-id>").description("Get an action type").action(async (knId, atId, _o, cmd) => {
|
|
1359
1436
|
printJson(await clientFrom(cmd).kn.actionTypeGet(knId, atId), outputOptions(cmd));
|
|
1360
1437
|
});
|
|
@@ -1365,7 +1442,10 @@ function bknCommand() {
|
|
|
1365
1442
|
printJson(await clientFrom(cmd).kn.get(knId, { exportMode: true }), outputOptions(cmd));
|
|
1366
1443
|
});
|
|
1367
1444
|
const objectType = bkn.commands.find((c) => c.name() === "object-type");
|
|
1368
|
-
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) => {
|
|
1369
1449
|
printJson(
|
|
1370
1450
|
await clientFrom(cmd).kn.objectTypeQuery(knId, otId, readBody(opts)),
|
|
1371
1451
|
outputOptions(cmd)
|
|
@@ -1374,17 +1454,23 @@ function bknCommand() {
|
|
|
1374
1454
|
bkn.command("create <name>").description("Create an (empty) knowledge network").option("--branch <b>", "branch", "main").action(async (name, opts, cmd) => {
|
|
1375
1455
|
printJson(await clientFrom(cmd).kn.create({ name, branch: opts.branch }), outputOptions(cmd));
|
|
1376
1456
|
});
|
|
1377
|
-
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) => {
|
|
1378
1461
|
printJson(await clientFrom(cmd).kn.update(knId, readBody(opts)), outputOptions(cmd));
|
|
1379
1462
|
});
|
|
1380
1463
|
bkn.command("delete <kn-id>").description("Delete a knowledge network").option("-y, --yes", "skip confirmation").action(async (knId, _opts, cmd) => {
|
|
1381
1464
|
printJson(await clientFrom(cmd).kn.delete(knId), outputOptions(cmd));
|
|
1382
1465
|
});
|
|
1383
|
-
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) => {
|
|
1384
1470
|
printJson(await clientFrom(cmd).kn.subgraph(knId, readBody(opts)), outputOptions(cmd));
|
|
1385
1471
|
});
|
|
1386
|
-
const actionLog = bkn.command("action-log").description("Action logs \u2014 list/get/cancel");
|
|
1387
|
-
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) => {
|
|
1388
1474
|
printJson(
|
|
1389
1475
|
await clientFrom(cmd).kn.actionLogs(knId, {
|
|
1390
1476
|
status: opts.status,
|
|
@@ -1404,25 +1490,37 @@ function bknCommand() {
|
|
|
1404
1490
|
printJson(await clientFrom(cmd).kn.actionExecution(knId, execId), outputOptions(cmd));
|
|
1405
1491
|
});
|
|
1406
1492
|
const metric = bkn.command("metric").description("Metrics \u2014 query / dry-run");
|
|
1407
|
-
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) => {
|
|
1408
1497
|
printJson(
|
|
1409
1498
|
await clientFrom(cmd).kn.metricQuery(knId, metricId, readBody(opts)),
|
|
1410
1499
|
outputOptions(cmd)
|
|
1411
1500
|
);
|
|
1412
1501
|
});
|
|
1413
|
-
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) => {
|
|
1414
1506
|
printJson(await clientFrom(cmd).kn.metricDryRun(knId, readBody(opts)), outputOptions(cmd));
|
|
1415
1507
|
});
|
|
1416
1508
|
metric.command("list <kn-id>").description("List metrics").action(async (knId, _o, cmd) => {
|
|
1417
1509
|
printJson(await clientFrom(cmd).kn.metricList(knId), outputOptions(cmd));
|
|
1418
1510
|
});
|
|
1419
|
-
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) => {
|
|
1420
1512
|
printJson(await clientFrom(cmd).kn.metricGet(knId, id), outputOptions(cmd));
|
|
1421
1513
|
});
|
|
1422
|
-
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) => {
|
|
1423
1518
|
printJson(await clientFrom(cmd).kn.metricCreate(knId, readBody(opts)), outputOptions(cmd));
|
|
1424
1519
|
});
|
|
1425
|
-
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) => {
|
|
1426
1524
|
printJson(
|
|
1427
1525
|
await clientFrom(cmd).kn.metricUpdate(knId, id, readBody(opts)),
|
|
1428
1526
|
outputOptions(cmd)
|
|
@@ -1431,10 +1529,10 @@ function bknCommand() {
|
|
|
1431
1529
|
metric.command("delete <kn-id> <metric-id>").description("Delete a metric").action(async (knId, id, _o, cmd) => {
|
|
1432
1530
|
printJson(await clientFrom(cmd).kn.metricDelete(knId, id), outputOptions(cmd));
|
|
1433
1531
|
});
|
|
1434
|
-
metric.command("
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
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) => {
|
|
1438
1536
|
printJson(await clientFrom(cmd).kn.metricValidate(knId, readBody(opts)), outputOptions(cmd));
|
|
1439
1537
|
});
|
|
1440
1538
|
const cg = bkn.command("concept-group").description("Concept groups \u2014 list/get");
|
|
@@ -1444,13 +1542,19 @@ function bknCommand() {
|
|
|
1444
1542
|
cg.command("get <kn-id> <cg-id>").description("Get a concept group").action(async (knId, cgId, _o, cmd) => {
|
|
1445
1543
|
printJson(await clientFrom(cmd).kn.conceptGroup(knId, cgId), outputOptions(cmd));
|
|
1446
1544
|
});
|
|
1447
|
-
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) => {
|
|
1448
1549
|
printJson(
|
|
1449
1550
|
await clientFrom(cmd).kn.conceptGroupCreate(knId, readBody(opts)),
|
|
1450
1551
|
outputOptions(cmd)
|
|
1451
1552
|
);
|
|
1452
1553
|
});
|
|
1453
|
-
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) => {
|
|
1454
1558
|
printJson(
|
|
1455
1559
|
await clientFrom(cmd).kn.conceptGroupUpdate(knId, cgId, readBody(opts)),
|
|
1456
1560
|
outputOptions(cmd)
|
|
@@ -1459,7 +1563,10 @@ function bknCommand() {
|
|
|
1459
1563
|
cg.command("delete <kn-id> <cg-id>").description("Delete a concept group").action(async (knId, cgId, _o, cmd) => {
|
|
1460
1564
|
printJson(await clientFrom(cmd).kn.conceptGroupDelete(knId, cgId), outputOptions(cmd));
|
|
1461
1565
|
});
|
|
1462
|
-
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) => {
|
|
1463
1570
|
printJson(
|
|
1464
1571
|
await clientFrom(cmd).kn.conceptGroupAddMembers(knId, cgId, readBody(opts)),
|
|
1465
1572
|
outputOptions(cmd)
|
|
@@ -1478,19 +1585,28 @@ function bknCommand() {
|
|
|
1478
1585
|
sched.command("get <kn-id> <schedule-id>").description("Get an action schedule").action(async (knId, sId, _o, cmd) => {
|
|
1479
1586
|
printJson(await clientFrom(cmd).kn.actionSchedule(knId, sId), outputOptions(cmd));
|
|
1480
1587
|
});
|
|
1481
|
-
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) => {
|
|
1482
1592
|
printJson(
|
|
1483
1593
|
await clientFrom(cmd).kn.actionScheduleCreate(knId, readBody(opts)),
|
|
1484
1594
|
outputOptions(cmd)
|
|
1485
1595
|
);
|
|
1486
1596
|
});
|
|
1487
|
-
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) => {
|
|
1488
1601
|
printJson(
|
|
1489
1602
|
await clientFrom(cmd).kn.actionScheduleUpdate(knId, sId, readBody(opts)),
|
|
1490
1603
|
outputOptions(cmd)
|
|
1491
1604
|
);
|
|
1492
1605
|
});
|
|
1493
|
-
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) => {
|
|
1494
1610
|
printJson(
|
|
1495
1611
|
await clientFrom(cmd).kn.actionScheduleSetStatus(knId, sId, readBody(opts)),
|
|
1496
1612
|
outputOptions(cmd)
|
|
@@ -1500,8 +1616,8 @@ function bknCommand() {
|
|
|
1500
1616
|
printJson(await clientFrom(cmd).kn.actionScheduleDelete(knId, ids), outputOptions(cmd));
|
|
1501
1617
|
});
|
|
1502
1618
|
bkn.command("push <directory>").description("Pack a BKN directory into a tar and import it as a knowledge network").option("--branch <name>", "target branch", "main").option("--build", "submit a Vega build task for each object type declaring a vector index").option(
|
|
1503
|
-
"--embedding-model <id>",
|
|
1504
|
-
"
|
|
1619
|
+
"--embedding-model <name-or-id>",
|
|
1620
|
+
"small-model name (or numeric ID, resolved to its name) for declared vector indexes (with --build)"
|
|
1505
1621
|
).action(async (dir, opts, cmd) => {
|
|
1506
1622
|
printJson(
|
|
1507
1623
|
await clientFrom(cmd).kn.push(dir, {
|
|
@@ -1518,7 +1634,10 @@ function bknCommand() {
|
|
|
1518
1634
|
outputOptions(cmd)
|
|
1519
1635
|
);
|
|
1520
1636
|
});
|
|
1521
|
-
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) => {
|
|
1522
1641
|
printJson(
|
|
1523
1642
|
await clientFrom(cmd).kn.relationTypePaths(knId, readBody(opts)),
|
|
1524
1643
|
outputOptions(cmd)
|
|
@@ -1530,7 +1649,10 @@ function bknCommand() {
|
|
|
1530
1649
|
bkn.command("create-from-catalog <catalog-id>").description("Build a knowledge network from a Vega catalog's tables").requiredOption("--name <name>", "knowledge network name").option("--tables <list>", "comma-separated table names (default: all)").option("--pk-map <map>", "explicit primary keys: '<table>:<col>[,<table>:<col>...]'").option("--build", "submit a Vega build task per resource after creation").option(
|
|
1531
1650
|
"--embedding-fields <map>",
|
|
1532
1651
|
"columns to vectorize per table (with --build): '<table>:<col>[+<col>...][,...]'"
|
|
1533
|
-
).option(
|
|
1652
|
+
).option(
|
|
1653
|
+
"--embedding-model <name-or-id>",
|
|
1654
|
+
"small-model name (or numeric ID, resolved to its name) for the vector index (with --build)"
|
|
1655
|
+
).option("--no-rollback", "keep a partially-created KN on failure").action(async (catalogId, opts, cmd) => {
|
|
1534
1656
|
printJson(
|
|
1535
1657
|
await clientFrom(cmd).kn.createFromCatalog({
|
|
1536
1658
|
catalogId,
|
|
@@ -1551,39 +1673,73 @@ function bknCommand() {
|
|
|
1551
1673
|
printJson(result, outputOptions(cmd));
|
|
1552
1674
|
if (!result.valid) process.exitCode = 1;
|
|
1553
1675
|
});
|
|
1554
|
-
bkn
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
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");
|
|
1577
1733
|
}
|
|
1578
1734
|
|
|
1579
1735
|
// src/commands/call.ts
|
|
1580
|
-
import { Command as
|
|
1736
|
+
import { Command as Command5 } from "commander";
|
|
1581
1737
|
function collect(value, prev) {
|
|
1582
1738
|
prev.push(value);
|
|
1583
1739
|
return prev;
|
|
1584
1740
|
}
|
|
1585
1741
|
function callCommand() {
|
|
1586
|
-
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(
|
|
1587
1743
|
"-F, --form <field>",
|
|
1588
1744
|
"multipart field key=value or key=@file (repeatable)",
|
|
1589
1745
|
collect,
|
|
@@ -1609,7 +1765,7 @@ function callCommand() {
|
|
|
1609
1765
|
});
|
|
1610
1766
|
const out = outputOptions(cmd2);
|
|
1611
1767
|
try {
|
|
1612
|
-
printJson(
|
|
1768
|
+
printJson(parseBigIntJSON(res.body), out);
|
|
1613
1769
|
} catch {
|
|
1614
1770
|
process.stdout.write(res.body.endsWith("\n") ? res.body : `${res.body}
|
|
1615
1771
|
`);
|
|
@@ -1620,18 +1776,30 @@ function callCommand() {
|
|
|
1620
1776
|
process.exitCode = 1;
|
|
1621
1777
|
}
|
|
1622
1778
|
});
|
|
1623
|
-
|
|
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");
|
|
1624
1792
|
}
|
|
1625
1793
|
|
|
1626
1794
|
// src/commands/config.ts
|
|
1627
|
-
import { Command as
|
|
1795
|
+
import { Command as Command6 } from "commander";
|
|
1628
1796
|
function requireActive() {
|
|
1629
1797
|
const baseUrl = activePlatform();
|
|
1630
1798
|
if (!baseUrl) throw new InputError("No active platform. Run `openbkn auth login <url>` first.");
|
|
1631
1799
|
return baseUrl;
|
|
1632
1800
|
}
|
|
1633
1801
|
function configCommand() {
|
|
1634
|
-
const config = new
|
|
1802
|
+
const config = new Command6("config").description("Remember a platform URL / business domain");
|
|
1635
1803
|
config.command("show").description("Show the active platform and business domain").action((_opts, cmd) => {
|
|
1636
1804
|
const baseUrl = activePlatform();
|
|
1637
1805
|
printJson(
|
|
@@ -1644,9 +1812,9 @@ function configCommand() {
|
|
|
1644
1812
|
});
|
|
1645
1813
|
config.command("set <key> <value>").description("Set a config value (baseUrl | businessDomain)").action((key, value, _opts, cmd) => {
|
|
1646
1814
|
if (key === "baseUrl") {
|
|
1647
|
-
setActivePlatform(value
|
|
1815
|
+
setActivePlatform(trimTrailingSlashes(value));
|
|
1648
1816
|
} else if (key === "businessDomain") {
|
|
1649
|
-
|
|
1817
|
+
updatePlatformConfig(requireActive(), { businessDomain: value });
|
|
1650
1818
|
} else {
|
|
1651
1819
|
throw new InputError(`Unknown config key: ${key} (expected baseUrl | businessDomain)`);
|
|
1652
1820
|
}
|
|
@@ -1654,18 +1822,19 @@ function configCommand() {
|
|
|
1654
1822
|
});
|
|
1655
1823
|
config.command("set-bd <value>").description("Set the default business domain for the active platform").action((value, _opts, cmd) => {
|
|
1656
1824
|
const baseUrl = requireActive();
|
|
1657
|
-
|
|
1825
|
+
updatePlatformConfig(baseUrl, { businessDomain: value });
|
|
1658
1826
|
printJson({ baseUrl, businessDomain: value }, outputOptions(cmd));
|
|
1659
1827
|
});
|
|
1660
1828
|
config.command("list-bd").description("List business domains (requires login)").action(() => {
|
|
1661
1829
|
throw new InputError("Not yet implemented \u2014 requires backend business-domains API.");
|
|
1662
1830
|
});
|
|
1663
|
-
|
|
1831
|
+
groupChildren(config, { READ: ["show", "list-bd"], WRITE: ["set", "set-bd"] });
|
|
1832
|
+
return group(config, "SIGN IN & SETTINGS");
|
|
1664
1833
|
}
|
|
1665
1834
|
|
|
1666
1835
|
// src/commands/context.ts
|
|
1667
|
-
import { Command as
|
|
1668
|
-
var
|
|
1836
|
+
import { Command as Command7 } from "commander";
|
|
1837
|
+
var int4 = (v) => Number.parseInt(v, 10);
|
|
1669
1838
|
var collectArg = (v, prev) => {
|
|
1670
1839
|
prev.push(v);
|
|
1671
1840
|
return prev;
|
|
@@ -1674,7 +1843,7 @@ function buildArgs(opts) {
|
|
|
1674
1843
|
let out = {};
|
|
1675
1844
|
if (opts.args) {
|
|
1676
1845
|
try {
|
|
1677
|
-
out =
|
|
1846
|
+
out = parseBigIntJSON(opts.args);
|
|
1678
1847
|
} catch {
|
|
1679
1848
|
throw new InputError("--args must be valid JSON");
|
|
1680
1849
|
}
|
|
@@ -1685,7 +1854,7 @@ function buildArgs(opts) {
|
|
|
1685
1854
|
const key = pair.slice(0, idx);
|
|
1686
1855
|
const raw = pair.slice(idx + 1);
|
|
1687
1856
|
try {
|
|
1688
|
-
out[key] =
|
|
1857
|
+
out[key] = parseBigIntJSON(raw);
|
|
1689
1858
|
} catch {
|
|
1690
1859
|
out[key] = raw;
|
|
1691
1860
|
}
|
|
@@ -1703,33 +1872,44 @@ function printToolList(res, out) {
|
|
|
1703
1872
|
printJson(res, out);
|
|
1704
1873
|
return;
|
|
1705
1874
|
}
|
|
1706
|
-
const
|
|
1875
|
+
const rows2 = arr.map((t) => ({
|
|
1707
1876
|
name: t.name ?? t.tool_name ?? t.key ?? "",
|
|
1708
1877
|
description: typeof t.description === "string" ? t.description : ""
|
|
1709
1878
|
}));
|
|
1710
|
-
printJson(
|
|
1879
|
+
printJson(rows2, out);
|
|
1711
1880
|
}
|
|
1712
1881
|
function contextCommand() {
|
|
1713
|
-
const cmd = new
|
|
1714
|
-
"
|
|
1882
|
+
const cmd = new Command7("context").description(
|
|
1883
|
+
"Ask a network questions (the MCP interface agents use)"
|
|
1715
1884
|
);
|
|
1716
|
-
|
|
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) => {
|
|
1717
1896
|
const data = await clientFrom(cmd2).context.searchSchema(knId, query, {
|
|
1718
1897
|
searchScope: opts.scope ? String(opts.scope).split(",") : void 0,
|
|
1719
1898
|
maxConcepts: opts.max
|
|
1720
1899
|
});
|
|
1721
1900
|
printJson(data, outputOptions(cmd2));
|
|
1722
1901
|
});
|
|
1723
|
-
cmd.command("query-object-instance <kn-id>").description(
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
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);
|
|
1730
1910
|
printJson(await clientFrom(cmd2).context.queryObjectInstance(knId, args), outputOptions(cmd2));
|
|
1731
1911
|
});
|
|
1732
|
-
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) => {
|
|
1733
1913
|
printJson(
|
|
1734
1914
|
await clientFrom(cmd2).context.findSkills(knId, otId, opts.topK),
|
|
1735
1915
|
outputOptions(cmd2)
|
|
@@ -1745,18 +1925,139 @@ function contextCommand() {
|
|
|
1745
1925
|
cmd.command("relation-types <kn-id> <ids...>").description("Full definitions for the given relation-type ids (unmatched \u2192 `missing`)").action(async (knId, ids, _opts, cmd2) => {
|
|
1746
1926
|
printJson(await clientFrom(cmd2).context.relationTypes(knId, ids), outputOptions(cmd2));
|
|
1747
1927
|
});
|
|
1928
|
+
cmd.command("conversation").description("Show the remembered conversation, or forget it with --forget").option(
|
|
1929
|
+
"--forget",
|
|
1930
|
+
"drop it, so the next command opens a fresh conversation (acts on this machine's store for the active user, whatever identity the request would use)"
|
|
1931
|
+
).action((opts, cmd2) => {
|
|
1932
|
+
const o = cmd2.optsWithGlobals();
|
|
1933
|
+
const baseUrl = platformOf(o);
|
|
1934
|
+
if (!baseUrl) throw new InputError("No platform. Run `openbkn auth login` first.");
|
|
1935
|
+
const forgot = opts.forget ? readPlatformConfig(baseUrl).conversationId : void 0;
|
|
1936
|
+
if (opts.forget) {
|
|
1937
|
+
updatePlatformConfig(baseUrl, {
|
|
1938
|
+
conversationId: void 0,
|
|
1939
|
+
conversationOpenedAt: void 0
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
const { id, source } = conversationSource(o);
|
|
1943
|
+
const stored = readPlatformConfig(baseUrl);
|
|
1944
|
+
printJson(
|
|
1945
|
+
{
|
|
1946
|
+
baseUrl,
|
|
1947
|
+
conversationId: id ?? null,
|
|
1948
|
+
source,
|
|
1949
|
+
...stored.conversationOpenedAt ? { storedOpenedAt: stored.conversationOpenedAt } : {},
|
|
1950
|
+
// What is on disk, even when something outranks it — otherwise
|
|
1951
|
+
// `--forget` looks like a no-op to whoever just ran this.
|
|
1952
|
+
...stored.conversationId && stored.conversationId !== id ? { storedConversationId: stored.conversationId } : {},
|
|
1953
|
+
...opts.forget ? { forgot: forgot ?? null } : {}
|
|
1954
|
+
},
|
|
1955
|
+
outputOptions(cmd2)
|
|
1956
|
+
);
|
|
1957
|
+
});
|
|
1748
1958
|
cmd.command("info").description("List the deploy's MCP tool catalog (global \u2014 no KN needed)").action(async (_opts, cmd2) => {
|
|
1749
1959
|
printToolList(await clientFrom(cmd2).context.info(), outputOptions(cmd2));
|
|
1750
1960
|
});
|
|
1751
|
-
|
|
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) => {
|
|
1752
2046
|
printToolList(await clientFrom(cmd2).context.tools(knId), outputOptions(cmd2));
|
|
1753
2047
|
});
|
|
1754
|
-
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(
|
|
1755
2052
|
"--arg <key=value>",
|
|
1756
2053
|
"one argument (repeatable; value parsed as JSON, else string)",
|
|
1757
2054
|
collectArg,
|
|
1758
2055
|
[]
|
|
2056
|
+
).option(
|
|
2057
|
+
"--schema",
|
|
2058
|
+
"print the named tool's argument schema from the deploy instead of calling it"
|
|
1759
2059
|
).action(async (knId, name, opts, cmd2) => {
|
|
2060
|
+
if (opts.schema) return printToolSchema(cmd2, knId, name);
|
|
1760
2061
|
printJson(
|
|
1761
2062
|
await clientFrom(cmd2).context.toolCall(knId, name, buildArgs(opts)),
|
|
1762
2063
|
outputOptions(cmd2)
|
|
@@ -1764,7 +2065,7 @@ function contextCommand() {
|
|
|
1764
2065
|
});
|
|
1765
2066
|
cmd.command("call-method <kn-id> <method>").description(
|
|
1766
2067
|
"Call any MCP method by name (e.g. tools/list, resources/read) \u2014 current or future"
|
|
1767
|
-
).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(
|
|
1768
2069
|
"--arg <key=value>",
|
|
1769
2070
|
"one param (repeatable; value parsed as JSON, else string)",
|
|
1770
2071
|
collectArg,
|
|
@@ -1787,239 +2088,1027 @@ function contextCommand() {
|
|
|
1787
2088
|
cmd.command("prompts <kn-id>").description("List MCP prompts").action(async (knId, _opts, cmd2) => {
|
|
1788
2089
|
printJson(await clientFrom(cmd2).context.prompts(knId), outputOptions(cmd2));
|
|
1789
2090
|
});
|
|
1790
|
-
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) => {
|
|
1791
2095
|
let args;
|
|
1792
2096
|
if (opts.args) {
|
|
1793
2097
|
try {
|
|
1794
|
-
args =
|
|
2098
|
+
args = parseBigIntJSON(opts.args);
|
|
1795
2099
|
} catch {
|
|
1796
2100
|
throw new InputError("--args must be valid JSON");
|
|
1797
2101
|
}
|
|
1798
2102
|
}
|
|
1799
2103
|
printJson(await clientFrom(cmd2).context.prompt(knId, name, args), outputOptions(cmd2));
|
|
1800
2104
|
});
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
}
|
|
1807
|
-
};
|
|
1808
|
-
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");
|
|
1809
2110
|
printJson(
|
|
1810
2111
|
await clientFrom(cmd2).context.queryInstanceSubgraph(knId, jsonArgs(opts.args)),
|
|
1811
2112
|
outputOptions(cmd2)
|
|
1812
2113
|
);
|
|
1813
2114
|
});
|
|
1814
|
-
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");
|
|
1815
2120
|
printJson(
|
|
1816
2121
|
await clientFrom(cmd2).context.logicProperties(knId, jsonArgs(opts.args)),
|
|
1817
2122
|
outputOptions(cmd2)
|
|
1818
2123
|
);
|
|
1819
2124
|
});
|
|
1820
|
-
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");
|
|
1821
2130
|
printJson(
|
|
1822
2131
|
await clientFrom(cmd2).context.actionInfo(knId, jsonArgs(opts.args)),
|
|
1823
2132
|
outputOptions(cmd2)
|
|
1824
2133
|
);
|
|
1825
2134
|
});
|
|
1826
|
-
|
|
1827
|
-
|
|
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
|
|
1828
2171
|
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
const cmd = new Command9("dataflow").description("Dataflow document workflows \u2014 list, runs, logs");
|
|
1834
|
-
cmd.command("list").description("List all dataflows").action(async (_opts, cmd2) => {
|
|
1835
|
-
printJson(await clientFrom(cmd2).dataflows.list(), outputOptions(cmd2));
|
|
1836
|
-
});
|
|
1837
|
-
cmd.command("runs <dagId>").description("List run records for one dataflow").option("--since <date>", "filter runs since a date").option("--limit <n>", "page size (backend default 20)", int6).option("--page <n>", "page (0-based; backend default 0)", int6).action(async (dagId, opts, cmd2) => {
|
|
1838
|
-
printJson(
|
|
1839
|
-
await clientFrom(cmd2).dataflows.runs(dagId, {
|
|
1840
|
-
since: opts.since,
|
|
1841
|
-
page: opts.page,
|
|
1842
|
-
limit: opts.limit
|
|
1843
|
-
}),
|
|
1844
|
-
outputOptions(cmd2)
|
|
1845
|
-
);
|
|
1846
|
-
});
|
|
1847
|
-
cmd.command("logs <dagId> <instanceId>").description("Show logs for one run").option("--page <n>", "page", int6, 0).option("--limit <n>", "page size", int6, DEFAULT_LIST_LIMIT).action(async (dagId, instanceId, opts, cmd2) => {
|
|
1848
|
-
printJson(
|
|
1849
|
-
await clientFrom(cmd2).dataflows.logs(dagId, instanceId, {
|
|
1850
|
-
page: opts.page,
|
|
1851
|
-
limit: opts.limit
|
|
1852
|
-
}),
|
|
1853
|
-
outputOptions(cmd2)
|
|
1854
|
-
);
|
|
1855
|
-
});
|
|
1856
|
-
cmd.command("run <dagId>").description("Trigger a dataflow run from a remote file URL").requiredOption("--url <url>", "remote file URL").requiredOption("--name <name>", "file name").action(async (dagId, opts, cmd2) => {
|
|
1857
|
-
printJson(
|
|
1858
|
-
await clientFrom(cmd2).dataflows.run(dagId, opts.url, opts.name),
|
|
1859
|
-
outputOptions(cmd2)
|
|
1860
|
-
);
|
|
1861
|
-
});
|
|
1862
|
-
cmd.command("create").description("Create a dataflow (DAG) from a full document body (--body / --body-file)").option("--body <json>", "dataflow document JSON").option("--body-file <path>", "read the dataflow document JSON from a file").action(async (opts, cmd2) => {
|
|
1863
|
-
printJson(await clientFrom(cmd2).dataflows.create(readBody(opts)), outputOptions(cmd2));
|
|
1864
|
-
});
|
|
1865
|
-
const parseSet = (pairs) => {
|
|
1866
|
-
const out = {};
|
|
1867
|
-
for (const item of pairs ?? []) {
|
|
1868
|
-
const i = item.indexOf("=");
|
|
1869
|
-
if (i > 0) out[item.slice(0, i)] = item.slice(i + 1);
|
|
1870
|
-
}
|
|
1871
|
-
return out;
|
|
1872
|
-
};
|
|
1873
|
-
cmd.command("templates").description("List available dataset/bkn/dataflow templates").action(async (_opts, cmd2) => {
|
|
1874
|
-
printJson(clientFrom(cmd2).dataflows.templates(), outputOptions(cmd2));
|
|
1875
|
-
});
|
|
1876
|
-
cmd.command("create-dataset").description("Create a dataset from a template (--template <name> --set k=v ...)").requiredOption("--template <name>", "template name").option(
|
|
1877
|
-
"--set <kv...>",
|
|
1878
|
-
"set a template argument (key=value); repeatable",
|
|
1879
|
-
(v, acc) => {
|
|
1880
|
-
acc.push(v);
|
|
1881
|
-
return acc;
|
|
1882
|
-
},
|
|
1883
|
-
[]
|
|
1884
|
-
).action(async (opts, cmd2) => {
|
|
1885
|
-
printJson(
|
|
1886
|
-
await clientFrom(cmd2).dataflows.createDataset(opts.template, parseSet(opts.set)),
|
|
1887
|
-
outputOptions(cmd2)
|
|
1888
|
-
);
|
|
1889
|
-
});
|
|
1890
|
-
cmd.command("create-bkn").description("Create a knowledge network from a template (--template <name> --set k=v ...)").requiredOption("--template <name>", "template name").option(
|
|
1891
|
-
"--set <kv...>",
|
|
1892
|
-
"set a template argument (key=value); repeatable",
|
|
1893
|
-
(v, acc) => {
|
|
1894
|
-
acc.push(v);
|
|
1895
|
-
return acc;
|
|
1896
|
-
},
|
|
1897
|
-
[]
|
|
1898
|
-
).action(async (opts, cmd2) => {
|
|
1899
|
-
printJson(
|
|
1900
|
-
await clientFrom(cmd2).dataflows.createBkn(opts.template, parseSet(opts.set)),
|
|
1901
|
-
outputOptions(cmd2)
|
|
1902
|
-
);
|
|
1903
|
-
});
|
|
1904
|
-
return group(cmd, "AI DATA PLATFORM");
|
|
1905
|
-
}
|
|
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.
|
|
1906
2176
|
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
}),
|
|
1916
|
-
"POST /api/bkn/instances": (c, _q, b) => c.kn.objectTypeQuery(str(b.knId), str(b.objectTypeId), b.body ?? {}),
|
|
1917
|
-
"POST /api/bkn/subgraph": (c, _q, b) => c.kn.subgraph(str(b.knId), b.body ?? b),
|
|
1918
|
-
"GET /api/vega/catalogs": (c) => c.vega.catalogs(),
|
|
1919
|
-
"GET /api/vega/catalog": (c, q) => c.vega.getCatalog(req(q, "catalogId")),
|
|
1920
|
-
"GET /api/vega/catalog-resources": (c, q) => c.vega.catalogResources(req(q, "catalogId"), q.get("category") ?? void 0),
|
|
1921
|
-
"GET /api/vega/connector-types": (c) => c.vega.connectorTypes(),
|
|
1922
|
-
"POST /api/vega/query": (c, _q, b) => c.resource.query(str(b.resourceId), b.options ?? {})
|
|
1923
|
-
};
|
|
1924
|
-
function str(v) {
|
|
1925
|
-
return typeof v === "string" ? v : String(v ?? "");
|
|
1926
|
-
}
|
|
1927
|
-
function req(q, key) {
|
|
1928
|
-
const v = q.get(key);
|
|
1929
|
-
if (!v) throw new Error(`missing query param: ${key}`);
|
|
1930
|
-
return v;
|
|
1931
|
-
}
|
|
1932
|
-
function readBody2(reqMsg) {
|
|
1933
|
-
return new Promise((resolve2, reject) => {
|
|
1934
|
-
let data = "";
|
|
1935
|
-
reqMsg.on("data", (chunk) => {
|
|
1936
|
-
data += chunk;
|
|
1937
|
-
});
|
|
1938
|
-
reqMsg.on("end", () => {
|
|
1939
|
-
if (!data.trim()) return resolve2({});
|
|
1940
|
-
try {
|
|
1941
|
-
resolve2(JSON.parse(data));
|
|
1942
|
-
} catch {
|
|
1943
|
-
reject(new Error("invalid JSON body"));
|
|
1944
|
-
}
|
|
1945
|
-
});
|
|
1946
|
-
reqMsg.on("error", reject);
|
|
1947
|
-
});
|
|
1948
|
-
}
|
|
1949
|
-
var INDEX = `<!doctype html><meta charset="utf-8"><title>openbkn explore</title>
|
|
1950
|
-
<h1>openbkn explore</h1>
|
|
1951
|
-
<p>Read-only JSON endpoints for bkn + vega:</p>
|
|
1952
|
-
<ul>${Object.keys(ROUTES).map((r) => `<li><code>${r}</code></li>`).join("")}</ul>`;
|
|
1953
|
-
function exploreCommand() {
|
|
1954
|
-
const cmd = new Command10("explore").description(
|
|
1955
|
-
"Start a local web server with read-only bkn + vega JSON endpoints"
|
|
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.`
|
|
1956
2185
|
);
|
|
1957
|
-
|
|
1958
|
-
const client = clientFrom(command);
|
|
1959
|
-
const server = createServer((reqMsg, res) => {
|
|
1960
|
-
void handle(client, reqMsg, res);
|
|
1961
|
-
});
|
|
1962
|
-
server.listen(opts.port, opts.host, () => {
|
|
1963
|
-
console.error(`openbkn explore running at http://${opts.host}:${opts.port}/`);
|
|
1964
|
-
console.error("bkn + vega read endpoints only. Press Ctrl+C to stop.");
|
|
1965
|
-
});
|
|
1966
|
-
});
|
|
1967
|
-
return group(cmd, "FOUNDATION");
|
|
2186
|
+
return group(cmd, "DATA & KNOWLEDGE");
|
|
1968
2187
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
2188
|
+
|
|
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"]
|
|
1976
2625
|
}
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
2626
|
+
};
|
|
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
|
+
}
|
|
1982
2680
|
}
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
|
|
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
|
+
}
|
|
1991
2688
|
}
|
|
2689
|
+
return { baseUrl: client.ctx.baseUrl, checkedAt: now, services, mcpTools };
|
|
1992
2690
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
import { Command as Command11 } from "commander";
|
|
1996
|
-
var int8 = (v) => Number.parseInt(v, 10);
|
|
1997
|
-
async function resolveLlmModelName(client, model) {
|
|
1998
|
-
if (!/^\d+$/.test(model)) return model;
|
|
1999
|
-
const detail = await client.models.llm.get(model);
|
|
2000
|
-
if (!detail?.model_name) throw new InputError(`No LLM found with id ${model}.`);
|
|
2001
|
-
return detail.model_name;
|
|
2691
|
+
function firstLine(message) {
|
|
2692
|
+
return (message.split("\n")[0] ?? message).slice(0, 160);
|
|
2002
2693
|
}
|
|
2003
|
-
function
|
|
2004
|
-
|
|
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"}` };
|
|
2705
|
+
}
|
|
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"
|
|
2873
|
+
);
|
|
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
|
+
};
|
|
2885
|
+
}
|
|
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("");
|
|
2908
|
+
}
|
|
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());
|
|
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) {
|
|
2949
|
+
try {
|
|
2950
|
+
return readFileSync4(file === "-" ? 0 : file, "utf8");
|
|
2951
|
+
} catch (err) {
|
|
2952
|
+
throw new InputError(
|
|
2953
|
+
`Cannot read ${file === "-" ? "stdin" : file}: ${err instanceof Error ? err.message : err}`
|
|
2954
|
+
);
|
|
2955
|
+
}
|
|
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
|
+
}
|
|
3073
|
+
|
|
3074
|
+
// src/commands/model.ts
|
|
3075
|
+
import { Command as Command10 } from "commander";
|
|
3076
|
+
var int6 = (v) => Number.parseInt(v, 10);
|
|
3077
|
+
async function resolveLlmModelName(client, model) {
|
|
3078
|
+
if (!/^\d+$/.test(model)) return model;
|
|
3079
|
+
const detail = await client.models.llm.get(model);
|
|
3080
|
+
if (!detail?.model_name) throw new InputError(`No LLM found with id ${model}.`);
|
|
3081
|
+
return detail.model_name;
|
|
3082
|
+
}
|
|
3083
|
+
function addManagementCommands(parent, kind) {
|
|
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) => {
|
|
2005
3088
|
printJson(await clientFrom(cmd).models[kind].add(readBody(opts)), outputOptions(cmd));
|
|
2006
3089
|
});
|
|
2007
|
-
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) => {
|
|
2008
3094
|
printJson(await clientFrom(cmd).models[kind].edit(readBody(opts)), outputOptions(cmd));
|
|
2009
3095
|
});
|
|
2010
3096
|
parent.command("delete <model-ids>").description("Delete model(s) (comma-joined ids)").action(async (ids, _o, cmd) => {
|
|
2011
3097
|
printJson(await clientFrom(cmd).models[kind].delete(csv(ids) ?? []), outputOptions(cmd));
|
|
2012
3098
|
});
|
|
2013
|
-
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) => {
|
|
2014
3103
|
printJson(await clientFrom(cmd).models[kind].test(readBody(opts)), outputOptions(cmd));
|
|
2015
3104
|
});
|
|
2016
3105
|
}
|
|
2017
3106
|
function modelCommand() {
|
|
2018
|
-
const model = new
|
|
2019
|
-
"
|
|
3107
|
+
const model = new Command10("model").description(
|
|
3108
|
+
"Large and small models: chat, embeddings, rerank, defaults"
|
|
2020
3109
|
);
|
|
2021
3110
|
const llm = model.command("llm").description("Large language models");
|
|
2022
|
-
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) => {
|
|
2023
3112
|
printJson(
|
|
2024
3113
|
await clientFrom(cmd).models.llm.list({
|
|
2025
3114
|
name: opts.name,
|
|
@@ -2052,7 +3141,7 @@ function modelCommand() {
|
|
|
2052
3141
|
});
|
|
2053
3142
|
addManagementCommands(llm, "llm");
|
|
2054
3143
|
const small = model.command("small").description("Small models (embedding / reranker)");
|
|
2055
|
-
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) => {
|
|
2056
3145
|
printJson(
|
|
2057
3146
|
await clientFrom(cmd).models.small.list({
|
|
2058
3147
|
name: opts.name,
|
|
@@ -2066,13 +3155,13 @@ function modelCommand() {
|
|
|
2066
3155
|
small.command("get <modelId>").description("Get a small model").action(async (id, _opts, cmd) => {
|
|
2067
3156
|
printJson(await clientFrom(cmd).models.small.get(id), outputOptions(cmd));
|
|
2068
3157
|
});
|
|
2069
|
-
small.command("embeddings <
|
|
3158
|
+
small.command("embeddings <model>").description("Compute embeddings (<model> = model name or numeric id)").requiredOption("-i, --input <text>", "comma-separated input texts").action(async (id, opts, cmd) => {
|
|
2070
3159
|
printJson(
|
|
2071
3160
|
await clientFrom(cmd).models.small.embeddings(id, csv(opts.input) ?? []),
|
|
2072
3161
|
outputOptions(cmd)
|
|
2073
3162
|
);
|
|
2074
3163
|
});
|
|
2075
|
-
small.command("rerank <
|
|
3164
|
+
small.command("rerank <model>").description("Rerank documents against a query (<model> = model name or numeric id)").requiredOption("-q, --query <text>", "query").requiredOption("-d, --documents <list>", "comma-separated documents").action(async (id, opts, cmd) => {
|
|
2076
3165
|
printJson(
|
|
2077
3166
|
await clientFrom(cmd).models.small.rerank(id, opts.query, csv(opts.documents) ?? []),
|
|
2078
3167
|
outputOptions(cmd)
|
|
@@ -2103,42 +3192,38 @@ Examples:
|
|
|
2103
3192
|
$ openbkn model small get-default --type embedding # current default
|
|
2104
3193
|
$ openbkn model small set-default <id> # default embedding/reranker`
|
|
2105
3194
|
);
|
|
2106
|
-
|
|
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");
|
|
2107
3203
|
}
|
|
2108
3204
|
|
|
2109
3205
|
// src/commands/resource.ts
|
|
2110
|
-
import { Command as
|
|
2111
|
-
var
|
|
2112
|
-
var parsePairs = (raw) => {
|
|
2113
|
-
if (!raw) return void 0;
|
|
2114
|
-
return raw.split(",").map((part) => {
|
|
2115
|
-
const idx = part.indexOf("=");
|
|
2116
|
-
if (idx < 1) throw new Error("--extension must be key=value[,key=value]");
|
|
2117
|
-
return { key: part.slice(0, idx).trim(), value: part.slice(idx + 1).trim() };
|
|
2118
|
-
}).filter((p) => p.key.length > 0);
|
|
2119
|
-
};
|
|
3206
|
+
import { Command as Command11 } from "commander";
|
|
3207
|
+
var int7 = (v) => Number.parseInt(v, 10);
|
|
2120
3208
|
function resourceCommand() {
|
|
2121
|
-
const cmd = new
|
|
2122
|
-
cmd.command("list").description("List resources under a catalog").option("--catalog-id <id>", "filter by catalog id").option("--
|
|
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) => {
|
|
2123
3211
|
const data = await clientFrom(cmd2).resource.list({
|
|
2124
|
-
|
|
3212
|
+
catalogId: opts.catalogId,
|
|
2125
3213
|
category: opts.category ?? opts.type,
|
|
2126
3214
|
status: opts.status,
|
|
2127
|
-
|
|
3215
|
+
schema: opts.schema,
|
|
2128
3216
|
limit: opts.limit,
|
|
2129
3217
|
offset: opts.offset,
|
|
2130
|
-
includeExtensions: opts.includeExtensions,
|
|
2131
|
-
includeExtensionKeys: opts.includeExtensionKeys,
|
|
2132
|
-
extensionPairs: parsePairs(opts.extension),
|
|
2133
3218
|
sort: opts.sort,
|
|
2134
3219
|
direction: opts.direction
|
|
2135
3220
|
});
|
|
2136
3221
|
printJson(data, outputOptions(cmd2));
|
|
2137
3222
|
});
|
|
2138
|
-
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) => {
|
|
2139
3224
|
const data = await clientFrom(cmd2).resource.find(opts.name, {
|
|
2140
3225
|
exact: opts.exact,
|
|
2141
|
-
|
|
3226
|
+
catalogId: opts.catalogId,
|
|
2142
3227
|
limit: opts.limit
|
|
2143
3228
|
});
|
|
2144
3229
|
printJson(data, outputOptions(cmd2));
|
|
@@ -2146,7 +3231,14 @@ function resourceCommand() {
|
|
|
2146
3231
|
cmd.command("get <id>").description("Get resource details").action(async (id, _opts, cmd2) => {
|
|
2147
3232
|
printJson(await clientFrom(cmd2).resource.get(id), outputOptions(cmd2));
|
|
2148
3233
|
});
|
|
2149
|
-
|
|
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) => {
|
|
2150
3242
|
const data = await clientFrom(cmd2).resource.query(id, {
|
|
2151
3243
|
limit: opts.limit,
|
|
2152
3244
|
offset: opts.offset,
|
|
@@ -2160,12 +3252,17 @@ function resourceCommand() {
|
|
|
2160
3252
|
cmd.command("delete <id>").description("Delete a resource").option("-y, --yes", "skip confirmation").action(async (id, _opts, cmd2) => {
|
|
2161
3253
|
printJson(await clientFrom(cmd2).resource.delete(id), outputOptions(cmd2));
|
|
2162
3254
|
});
|
|
2163
|
-
|
|
3255
|
+
groupChildren(cmd, {
|
|
3256
|
+
READ: ["list", "find", "get"],
|
|
3257
|
+
RUN: ["query"],
|
|
3258
|
+
WRITE: ["enable", "disable", "delete"]
|
|
3259
|
+
});
|
|
3260
|
+
return group(cmd, "DATA & KNOWLEDGE");
|
|
2164
3261
|
}
|
|
2165
3262
|
|
|
2166
3263
|
// src/commands/skill.ts
|
|
2167
|
-
import { Command as
|
|
2168
|
-
var
|
|
3264
|
+
import { Command as Command12 } from "commander";
|
|
3265
|
+
var int8 = (v) => Number.parseInt(v, 10);
|
|
2169
3266
|
var positiveInt = (flag) => (v) => {
|
|
2170
3267
|
if (!/^\d+$/.test(v)) {
|
|
2171
3268
|
throw new InputError(`${flag} must be a positive integer (got '${v}')`);
|
|
@@ -2190,9 +3287,15 @@ function checkSource(source) {
|
|
|
2190
3287
|
}
|
|
2191
3288
|
var draftOption = (c) => c.option("--draft", "read the draft (management) version instead of the published one");
|
|
2192
3289
|
function skillCommand() {
|
|
2193
|
-
const cmd = new
|
|
2194
|
-
|
|
2195
|
-
|
|
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) => {
|
|
2196
3299
|
printJson(
|
|
2197
3300
|
await clientFrom(cmd2).skills.list({
|
|
2198
3301
|
name: opts.name,
|
|
@@ -2208,19 +3311,19 @@ function skillCommand() {
|
|
|
2208
3311
|
cmd.command("get <skill-id>").description("Get a skill by id").action(async (id, _opts, cmd2) => {
|
|
2209
3312
|
printJson(await clientFrom(cmd2).skills.get(id), outputOptions(cmd2));
|
|
2210
3313
|
});
|
|
2211
|
-
listOpts(
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
)
|
|
2222
|
-
|
|
2223
|
-
);
|
|
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
|
+
});
|
|
2224
3327
|
cmd.command("market-get <skill-id>").description("Get a market skill by id").action(async (id, _opts, cmd2) => {
|
|
2225
3328
|
printJson(await clientFrom(cmd2).skills.marketGet(id), outputOptions(cmd2));
|
|
2226
3329
|
});
|
|
@@ -2329,7 +3432,7 @@ ${files.length} files, ${bytes} B
|
|
|
2329
3432
|
);
|
|
2330
3433
|
});
|
|
2331
3434
|
cmd.command("register <directory>").description("Zip a local skill directory and register it").option("--source <s>", `source tag: ${SKILL_SOURCES.join(" | ")}`, "custom").option("--extend-info <json>", "extra metadata as JSON").action(async (dir, opts, cmd2) => {
|
|
2332
|
-
const extendInfo = opts.extendInfo ?
|
|
3435
|
+
const extendInfo = opts.extendInfo ? parseBigIntJSON(opts.extendInfo) : void 0;
|
|
2333
3436
|
printJson(
|
|
2334
3437
|
await clientFrom(cmd2).skills.register(dir, {
|
|
2335
3438
|
source: checkSource(opts.source),
|
|
@@ -2347,7 +3450,10 @@ ${files.length} files, ${bytes} B
|
|
|
2347
3450
|
cmd.command("install <skill-id> [directory]").description("Download a skill archive and extract it locally").action(async (skillId, dir, _o, cmd2) => {
|
|
2348
3451
|
printJson(await clientFrom(cmd2).skills.install(skillId, dir), outputOptions(cmd2));
|
|
2349
3452
|
});
|
|
2350
|
-
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) => {
|
|
2351
3457
|
printJson(
|
|
2352
3458
|
await clientFrom(cmd2).skills.updateMetadata(skillId, readBody(opts)),
|
|
2353
3459
|
outputOptions(cmd2)
|
|
@@ -2365,15 +3471,53 @@ ${files.length} files, ${bytes} B
|
|
|
2365
3471
|
outputOptions(cmd2)
|
|
2366
3472
|
);
|
|
2367
3473
|
});
|
|
2368
|
-
|
|
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");
|
|
2369
3512
|
}
|
|
2370
3513
|
|
|
2371
3514
|
// src/commands/toolbox.ts
|
|
2372
|
-
import { Command as
|
|
2373
|
-
|
|
3515
|
+
import { Command as Command13 } from "commander";
|
|
3516
|
+
import yaml from "js-yaml";
|
|
3517
|
+
var int9 = (v) => Number.parseInt(v, 10);
|
|
2374
3518
|
function toolboxCommand() {
|
|
2375
|
-
const cmd = new
|
|
2376
|
-
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) => {
|
|
2377
3521
|
printJson(
|
|
2378
3522
|
await clientFrom(cmd2).toolboxes.list({
|
|
2379
3523
|
keyword: opts.keyword,
|
|
@@ -2383,12 +3527,21 @@ function toolboxCommand() {
|
|
|
2383
3527
|
outputOptions(cmd2)
|
|
2384
3528
|
);
|
|
2385
3529
|
});
|
|
2386
|
-
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
|
+
}
|
|
2387
3539
|
printJson(
|
|
2388
3540
|
await clientFrom(cmd2).toolboxes.create({
|
|
2389
3541
|
name: opts.name,
|
|
2390
3542
|
serviceUrl: opts.serviceUrl,
|
|
2391
|
-
description: opts.description
|
|
3543
|
+
description: opts.description,
|
|
3544
|
+
metadataType: opts.type
|
|
2392
3545
|
}),
|
|
2393
3546
|
outputOptions(cmd2)
|
|
2394
3547
|
);
|
|
@@ -2411,11 +3564,36 @@ function toolboxCommand() {
|
|
|
2411
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) => {
|
|
2412
3565
|
printJson(await clientFrom(cmd2).toolboxes.import(file, opts.type), outputOptions(cmd2));
|
|
2413
3566
|
});
|
|
2414
|
-
|
|
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");
|
|
2415
3591
|
}
|
|
2416
3592
|
function toolCommand() {
|
|
2417
|
-
const cmd = new
|
|
2418
|
-
|
|
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) => {
|
|
2419
3597
|
printJson(
|
|
2420
3598
|
await clientFrom(cmd2).toolboxes.tools(opts.toolbox, {
|
|
2421
3599
|
page: opts.page,
|
|
@@ -2437,55 +3615,120 @@ function toolCommand() {
|
|
|
2437
3615
|
outputOptions(cmd2)
|
|
2438
3616
|
);
|
|
2439
3617
|
});
|
|
2440
|
-
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);
|
|
2441
3622
|
const parseJson = (s, label) => {
|
|
2442
3623
|
if (!s) return void 0;
|
|
2443
3624
|
try {
|
|
2444
|
-
return
|
|
3625
|
+
return parseBigIntJSON(s);
|
|
2445
3626
|
} catch {
|
|
2446
3627
|
throw new InputError(`--${label} must be valid JSON`);
|
|
2447
3628
|
}
|
|
2448
3629
|
};
|
|
2449
3630
|
const buildEnvelope = (opts) => ({
|
|
2450
|
-
body: opts.body ?
|
|
3631
|
+
body: opts.body ? parseBigIntJSON(opts.body) : void 0,
|
|
2451
3632
|
header: parseJson(opts.header, "header"),
|
|
2452
3633
|
query: parseJson(opts.query, "query"),
|
|
2453
3634
|
path: parseJson(opts.path, "path"),
|
|
2454
3635
|
timeout: opts.timeout ? Number(opts.timeout) : void 0
|
|
2455
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
|
+
);
|
|
2456
3645
|
invokeOpts(
|
|
2457
|
-
cmd.command("
|
|
3646
|
+
cmd.command("debug <tool-id>").description("Invoke a tool that is not enabled yet")
|
|
2458
3647
|
).action(async (toolId, opts, cmd2) => {
|
|
2459
3648
|
printJson(
|
|
2460
|
-
await clientFrom(cmd2).toolboxes.
|
|
3649
|
+
await clientFrom(cmd2).toolboxes.debug(opts.toolbox, toolId, buildEnvelope(opts)),
|
|
2461
3650
|
outputOptions(cmd2)
|
|
2462
3651
|
);
|
|
2463
3652
|
});
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
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
|
+
}
|
|
2467
3695
|
printJson(
|
|
2468
|
-
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
|
+
}),
|
|
3701
|
+
outputOptions(cmd2)
|
|
3702
|
+
);
|
|
3703
|
+
});
|
|
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),
|
|
2469
3707
|
outputOptions(cmd2)
|
|
2470
3708
|
);
|
|
2471
3709
|
});
|
|
2472
|
-
cmd.command("upload <file>").description("
|
|
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) => {
|
|
2473
3711
|
printJson(
|
|
2474
3712
|
await clientFrom(cmd2).toolboxes.upload(opts.toolbox, file, opts.metadataType),
|
|
2475
3713
|
outputOptions(cmd2)
|
|
2476
3714
|
);
|
|
2477
3715
|
});
|
|
2478
|
-
|
|
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");
|
|
2479
3722
|
}
|
|
2480
3723
|
|
|
2481
3724
|
// src/commands/trace.ts
|
|
2482
|
-
import { readFileSync as
|
|
2483
|
-
import { Command as
|
|
3725
|
+
import { readFileSync as readFileSync6, writeFileSync } from "fs";
|
|
3726
|
+
import { Command as Command14 } from "commander";
|
|
2484
3727
|
|
|
2485
3728
|
// src/bkn-trace/schema-validate.ts
|
|
2486
|
-
import { readFileSync as
|
|
3729
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
2487
3730
|
import { extname } from "path";
|
|
2488
|
-
import
|
|
3731
|
+
import yaml2 from "js-yaml";
|
|
2489
3732
|
import { z } from "zod";
|
|
2490
3733
|
var Assertion = z.object({
|
|
2491
3734
|
type: z.enum([
|
|
@@ -2520,10 +3763,10 @@ var DiagnosisRule = z.object({
|
|
|
2520
3763
|
params: z.record(z.string(), z.unknown()).optional()
|
|
2521
3764
|
});
|
|
2522
3765
|
function parseFile(file) {
|
|
2523
|
-
const text =
|
|
3766
|
+
const text = readFileSync5(file, "utf8");
|
|
2524
3767
|
const ext = extname(file).toLowerCase();
|
|
2525
|
-
if (ext === ".yaml" || ext === ".yml") return
|
|
2526
|
-
return
|
|
3768
|
+
if (ext === ".yaml" || ext === ".yml") return yaml2.load(text);
|
|
3769
|
+
return parseBigIntJSON(text);
|
|
2527
3770
|
}
|
|
2528
3771
|
function inferKind(data) {
|
|
2529
3772
|
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
@@ -2557,9 +3800,44 @@ function validateSchemaFile(file, kind) {
|
|
|
2557
3800
|
}
|
|
2558
3801
|
|
|
2559
3802
|
// src/commands/trace.ts
|
|
3803
|
+
function renderPayload(payload) {
|
|
3804
|
+
if (!payload) return "-";
|
|
3805
|
+
if (payload.mode === "inline") return stringifyBigIntJSON(payload.inline);
|
|
3806
|
+
if (payload.mode === "referenced") return `[referenced] ${payload.ref ?? "-"}`;
|
|
3807
|
+
return `[omitted] ${payload.omitted_reason ?? "unknown"}`;
|
|
3808
|
+
}
|
|
3809
|
+
function renderTechnicalTraceDetail(detail) {
|
|
3810
|
+
const lines = [
|
|
3811
|
+
`Trace: ${detail.summary.trace_id}`,
|
|
3812
|
+
`Status: ${detail.summary.status}`,
|
|
3813
|
+
`Request: ${detail.summary.request_id || "-"}`,
|
|
3814
|
+
`Question: ${detail.summary.question_preview || "-"}`,
|
|
3815
|
+
`Result: ${detail.summary.result_preview || "-"}`,
|
|
3816
|
+
`Service: ${detail.summary.root_service || "-"}`,
|
|
3817
|
+
`Spans: ${detail.graph?.data.nodes.length ?? 0}`
|
|
3818
|
+
];
|
|
3819
|
+
if (detail.partial) {
|
|
3820
|
+
lines.push(`Partial: ${(detail.partial_reasons ?? []).join(", ") || "yes"}`);
|
|
3821
|
+
}
|
|
3822
|
+
for (const operation of detail.operations) {
|
|
3823
|
+
lines.push(
|
|
3824
|
+
"",
|
|
3825
|
+
`${operation.fact.tool_name} \xB7 ${operation.fact.operation_id} \xB7 attempt ${operation.fact.attempt} \xB7 ${operation.state}`,
|
|
3826
|
+
`Source: ${operation.fact.protocol}/${operation.fact.source_module}`,
|
|
3827
|
+
`Input: ${renderPayload(operation.fact.input)}`
|
|
3828
|
+
);
|
|
3829
|
+
if (operation.fact.output) lines.push(`Output: ${renderPayload(operation.fact.output)}`);
|
|
3830
|
+
if (operation.fact.error) lines.push(`Error: ${renderPayload(operation.fact.error)}`);
|
|
3831
|
+
if (operation.partial_reasons?.length) {
|
|
3832
|
+
lines.push(`Partial: ${operation.partial_reasons.join(", ")}`);
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
return `${lines.join("\n")}
|
|
3836
|
+
`;
|
|
3837
|
+
}
|
|
2560
3838
|
function traceCommand() {
|
|
2561
|
-
const cmd = new
|
|
2562
|
-
"
|
|
3839
|
+
const cmd = new Command14("trace").description(
|
|
3840
|
+
"Inspect what an agent actually did, and diagnose bad answers"
|
|
2563
3841
|
);
|
|
2564
3842
|
cmd.command("graph <trace-id>").description("Fetch normalized trace graph by trace id").action(async (traceId, _opts, cmd2) => {
|
|
2565
3843
|
printJson(await clientFrom(cmd2).trace.graph(traceId), outputOptions(cmd2));
|
|
@@ -2633,8 +3911,17 @@ function traceCommand() {
|
|
|
2633
3911
|
outputOptions(cmd2)
|
|
2634
3912
|
);
|
|
2635
3913
|
});
|
|
3914
|
+
interactions.command("operations <interaction-id>").description("List the exact Operation call facts for one interaction").action(async (interactionId, _opts, cmd2) => {
|
|
3915
|
+
printJson(
|
|
3916
|
+
await clientFrom(cmd2).trace.lifecycle.listInteractionOperations(interactionId),
|
|
3917
|
+
outputOptions(cmd2)
|
|
3918
|
+
);
|
|
3919
|
+
});
|
|
2636
3920
|
for (const action of ["complete", "fail", "cancel", "handoff"]) {
|
|
2637
|
-
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) => {
|
|
2638
3925
|
const input = readBody(opts);
|
|
2639
3926
|
const lifecycle = clientFrom(cmd2).trace.lifecycle;
|
|
2640
3927
|
const terminal = {
|
|
@@ -2653,7 +3940,20 @@ function traceCommand() {
|
|
|
2653
3940
|
outputOptions(cmd2)
|
|
2654
3941
|
);
|
|
2655
3942
|
});
|
|
2656
|
-
operations.command("
|
|
3943
|
+
operations.command("attempt <operation-id> <attempt>").description("Get one exact Operation attempt call fact").action(async (operationId, attempt, _opts, cmd2) => {
|
|
3944
|
+
if (!/^[1-9]\d*$/.test(attempt)) {
|
|
3945
|
+
throw new InputError("attempt must be a positive integer");
|
|
3946
|
+
}
|
|
3947
|
+
const ordinal = Number.parseInt(attempt, 10);
|
|
3948
|
+
printJson(
|
|
3949
|
+
await clientFrom(cmd2).trace.lifecycle.getOperationAttempt(operationId, ordinal),
|
|
3950
|
+
outputOptions(cmd2)
|
|
3951
|
+
);
|
|
3952
|
+
});
|
|
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) => {
|
|
2657
3957
|
printJson(
|
|
2658
3958
|
await clientFrom(cmd2).trace.lifecycle.retryOperationAttempt(
|
|
2659
3959
|
operationId,
|
|
@@ -2666,14 +3966,41 @@ function traceCommand() {
|
|
|
2666
3966
|
receipts.command("get <receipt-id>").description("Get an authorized operation receipt").action(async (receiptId, _opts, cmd2) => {
|
|
2667
3967
|
printJson(await clientFrom(cmd2).trace.lifecycle.getReceipt(receiptId), outputOptions(cmd2));
|
|
2668
3968
|
});
|
|
2669
|
-
cmd.command("get <conversation-id>").description("Fetch
|
|
3969
|
+
cmd.command("get <conversation-id>").description("Fetch normalized spans for a conversation").option("--max-spans <n>", "max spans", (v) => Number.parseInt(v, 10)).action(async (conversationId, opts, cmd2) => {
|
|
3970
|
+
printJson(
|
|
3971
|
+
await clientFrom(cmd2).trace.spans(conversationId, { maxSpans: opts.maxSpans }),
|
|
3972
|
+
outputOptions(cmd2)
|
|
3973
|
+
);
|
|
3974
|
+
});
|
|
3975
|
+
cmd.command("detail <trace-id>").description("Get one typed technical trace with Span and Operation facts").action(async (traceId, _opts, cmd2) => {
|
|
3976
|
+
const detail = await clientFrom(cmd2).trace.get(traceId);
|
|
3977
|
+
const output = outputOptions(cmd2);
|
|
3978
|
+
if (output.json || output.compact) printJson(detail, output);
|
|
3979
|
+
else process.stdout.write(renderTechnicalTraceDetail(detail));
|
|
3980
|
+
});
|
|
3981
|
+
cmd.command("spans <conversation-id>").description("Fetch normalized spans for a conversation").option("--max-spans <n>", "max spans", (v) => Number.parseInt(v, 10)).action(async (conversationId, opts, cmd2) => {
|
|
2670
3982
|
printJson(
|
|
2671
3983
|
await clientFrom(cmd2).trace.spans(conversationId, { maxSpans: opts.maxSpans }),
|
|
2672
3984
|
outputOptions(cmd2)
|
|
2673
3985
|
);
|
|
2674
3986
|
});
|
|
2675
|
-
cmd.command("search").description("
|
|
2676
|
-
printJson(
|
|
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) => {
|
|
3988
|
+
printJson(
|
|
3989
|
+
await clientFrom(cmd2).trace.search({
|
|
3990
|
+
limit: opts.limit,
|
|
3991
|
+
cursor: opts.cursor,
|
|
3992
|
+
from: opts.from,
|
|
3993
|
+
to: opts.to,
|
|
3994
|
+
status: opts.status,
|
|
3995
|
+
service: opts.service,
|
|
3996
|
+
tool: opts.tool,
|
|
3997
|
+
traceId: opts.traceId,
|
|
3998
|
+
errorKeyword: opts.errorKeyword,
|
|
3999
|
+
conversationId: opts.conversationId,
|
|
4000
|
+
interactionId: opts.interactionId
|
|
4001
|
+
}),
|
|
4002
|
+
outputOptions(cmd2)
|
|
4003
|
+
);
|
|
2677
4004
|
});
|
|
2678
4005
|
cmd.command("diagnose <conversation-id>").description("Diagnose a conversation's trace (symbolic rules; --llm adds rubric judging)").option("--llm", "also run LLM-judged rubric rules via the local `claude` CLI").action(async (conversationId, opts, cmd2) => {
|
|
2679
4006
|
const report = await clientFrom(cmd2).trace.diagnose(conversationId, {
|
|
@@ -2690,27 +4017,17 @@ function traceCommand() {
|
|
|
2690
4017
|
outputOptions(cmd2)
|
|
2691
4018
|
);
|
|
2692
4019
|
});
|
|
2693
|
-
const evalSet = cmd.command("eval-set").description("Build
|
|
4020
|
+
const evalSet = cmd.command("eval-set").description("Build trace eval sets");
|
|
2694
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) => {
|
|
2695
|
-
const raw =
|
|
4022
|
+
const raw = parseBigIntJSON(readFileSync6(queriesFile, "utf8"));
|
|
2696
4023
|
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2697
4024
|
if (opts.out) {
|
|
2698
|
-
writeFileSync(opts.out,
|
|
4025
|
+
writeFileSync(opts.out, stringifyBigIntJSON({ cases }, 2));
|
|
2699
4026
|
printJson({ out: opts.out, cases: cases.length }, outputOptions(cmd2));
|
|
2700
4027
|
} else {
|
|
2701
4028
|
printJson({ cases }, outputOptions(cmd2));
|
|
2702
4029
|
}
|
|
2703
4030
|
});
|
|
2704
|
-
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) => {
|
|
2705
|
-
const raw = JSON.parse(readFileSync5(casesFile, "utf8"));
|
|
2706
|
-
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2707
|
-
const result = await clientFrom(cmd2).trace.evalSetTest(opts.agent, cases, {
|
|
2708
|
-
version: opts.version,
|
|
2709
|
-
llm: Boolean(opts.llm)
|
|
2710
|
-
});
|
|
2711
|
-
printJson(result, outputOptions(cmd2));
|
|
2712
|
-
if (result.failed > 0) process.exitCode = 1;
|
|
2713
|
-
});
|
|
2714
4031
|
const schema = cmd.command("schema").description("Validate eval-set / diagnosis-rule files");
|
|
2715
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) => {
|
|
2716
4033
|
const result = validateSchemaFile(file, opts.kind);
|
|
@@ -2722,12 +4039,53 @@ function traceCommand() {
|
|
|
2722
4039
|
printJson(result, outputOptions(cmd2));
|
|
2723
4040
|
if (!result.ok) process.exitCode = 1;
|
|
2724
4041
|
});
|
|
2725
|
-
|
|
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");
|
|
2726
4064
|
}
|
|
2727
4065
|
|
|
2728
4066
|
// src/commands/vega.ts
|
|
2729
|
-
import { Command as
|
|
2730
|
-
var
|
|
4067
|
+
import { Command as Command15 } from "commander";
|
|
4068
|
+
var int10 = (value) => {
|
|
4069
|
+
const parsed = Number(value);
|
|
4070
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
4071
|
+
throw new InputError(`expected an integer, received "${value}"`);
|
|
4072
|
+
}
|
|
4073
|
+
return parsed;
|
|
4074
|
+
};
|
|
4075
|
+
var expectedUpdateTime = (value) => {
|
|
4076
|
+
const parsed = Number(value);
|
|
4077
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
4078
|
+
throw new InputError("--expected-update-time must be a positive integer timestamp");
|
|
4079
|
+
}
|
|
4080
|
+
return parsed;
|
|
4081
|
+
};
|
|
4082
|
+
var confidenceThreshold = (value) => {
|
|
4083
|
+
const parsed = Number(value);
|
|
4084
|
+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
|
|
4085
|
+
throw new InputError("--confidence-threshold must be a number between 0 and 1");
|
|
4086
|
+
}
|
|
4087
|
+
return parsed;
|
|
4088
|
+
};
|
|
2731
4089
|
var bool = (value) => {
|
|
2732
4090
|
if (value === "true") return true;
|
|
2733
4091
|
if (value === "false") return false;
|
|
@@ -2736,7 +4094,7 @@ var bool = (value) => {
|
|
|
2736
4094
|
var parseJsonObject = (value, flag) => {
|
|
2737
4095
|
let parsed;
|
|
2738
4096
|
try {
|
|
2739
|
-
parsed =
|
|
4097
|
+
parsed = parseBigIntJSON(value);
|
|
2740
4098
|
} catch {
|
|
2741
4099
|
throw new InputError(`${flag} must be valid JSON`);
|
|
2742
4100
|
}
|
|
@@ -2745,10 +4103,15 @@ var parseJsonObject = (value, flag) => {
|
|
|
2745
4103
|
}
|
|
2746
4104
|
return parsed;
|
|
2747
4105
|
};
|
|
2748
|
-
var
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
4106
|
+
var parseJsonArray = (value, flag) => {
|
|
4107
|
+
let parsed;
|
|
4108
|
+
try {
|
|
4109
|
+
parsed = parseBigIntJSON(value);
|
|
4110
|
+
} catch {
|
|
4111
|
+
throw new InputError(`${flag} must be valid JSON`);
|
|
4112
|
+
}
|
|
4113
|
+
if (!Array.isArray(parsed) || parsed.some((item) => typeof item !== "object" || item === null || Array.isArray(item))) {
|
|
4114
|
+
throw new InputError(`${flag} must be a JSON array of objects`);
|
|
2752
4115
|
}
|
|
2753
4116
|
return parsed;
|
|
2754
4117
|
};
|
|
@@ -2771,20 +4134,143 @@ var healthCheckSchedule = (mode, cronExpr) => {
|
|
|
2771
4134
|
}
|
|
2772
4135
|
throw new InputError("health-check mode must be inherit, enabled, or disabled");
|
|
2773
4136
|
};
|
|
2774
|
-
var
|
|
2775
|
-
if (
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
4137
|
+
var buildTaskStatuses = (raw) => {
|
|
4138
|
+
if (raw === void 0) return void 0;
|
|
4139
|
+
const statuses = csv(raw);
|
|
4140
|
+
if (!statuses?.length) {
|
|
4141
|
+
throw new InputError("--status must include at least one build status");
|
|
4142
|
+
}
|
|
4143
|
+
return statuses.map((status2) => {
|
|
4144
|
+
const parsed = BuildTaskStatus.safeParse(status2);
|
|
4145
|
+
if (!parsed.success) {
|
|
4146
|
+
throw new InputError(
|
|
4147
|
+
`invalid build status "${status2}"; expected one of ${BuildTaskStatus.options.join(", ")}`
|
|
4148
|
+
);
|
|
4149
|
+
}
|
|
4150
|
+
return parsed.data;
|
|
4151
|
+
});
|
|
4152
|
+
};
|
|
4153
|
+
var buildTaskSort = (raw) => {
|
|
4154
|
+
if (raw === void 0) return void 0;
|
|
4155
|
+
const parsed = BuildTaskSort.safeParse(raw);
|
|
4156
|
+
if (!parsed.success) {
|
|
4157
|
+
throw new InputError(
|
|
4158
|
+
`invalid build task sort "${raw}"; expected one of ${BuildTaskSort.options.join(", ")}`
|
|
4159
|
+
);
|
|
4160
|
+
}
|
|
4161
|
+
return parsed.data;
|
|
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
|
+
};
|
|
4173
|
+
var discoverStrategy = (raw) => {
|
|
4174
|
+
if (raw === void 0) return void 0;
|
|
4175
|
+
const parsed = DiscoverStrategy.safeParse(raw);
|
|
4176
|
+
if (!parsed.success) {
|
|
4177
|
+
throw new InputError(
|
|
4178
|
+
`invalid discover strategy "${raw}"; expected one of ${DiscoverStrategy.options.join(", ")}`
|
|
4179
|
+
);
|
|
4180
|
+
}
|
|
4181
|
+
return parsed.data;
|
|
4182
|
+
};
|
|
4183
|
+
var requiredDiscoverStrategy = (raw) => discoverStrategy(raw);
|
|
4184
|
+
var taskStatuses = (raw) => {
|
|
4185
|
+
if (raw === void 0) return void 0;
|
|
4186
|
+
const values = csv(raw);
|
|
4187
|
+
if (!values?.length) throw new InputError("--status must include at least one task status");
|
|
4188
|
+
return values.map((value) => {
|
|
4189
|
+
const parsed = VegaTaskStatus.safeParse(value);
|
|
4190
|
+
if (!parsed.success) {
|
|
4191
|
+
throw new InputError(
|
|
4192
|
+
`invalid task status "${value}"; expected one of ${VegaTaskStatus.options.join(", ")}`
|
|
4193
|
+
);
|
|
4194
|
+
}
|
|
4195
|
+
return parsed.data;
|
|
4196
|
+
});
|
|
4197
|
+
};
|
|
4198
|
+
var semanticScope = (raw) => {
|
|
4199
|
+
if (raw === void 0) return void 0;
|
|
4200
|
+
const parsed = SemanticUnderstandingScope.safeParse(raw);
|
|
4201
|
+
if (!parsed.success) {
|
|
4202
|
+
throw new InputError(
|
|
4203
|
+
`invalid semantic task scope "${raw}"; expected one of ${SemanticUnderstandingScope.options.join(", ")}`
|
|
4204
|
+
);
|
|
4205
|
+
}
|
|
4206
|
+
return parsed.data;
|
|
4207
|
+
};
|
|
4208
|
+
var semanticApplyMode = (raw) => {
|
|
4209
|
+
if (raw === void 0) return void 0;
|
|
4210
|
+
const parsed = SemanticUnderstandingApplyMode.safeParse(raw);
|
|
4211
|
+
if (!parsed.success) {
|
|
4212
|
+
throw new InputError(
|
|
4213
|
+
`invalid semantic apply mode "${raw}"; expected one of ${SemanticUnderstandingApplyMode.options.join(", ")}`
|
|
4214
|
+
);
|
|
4215
|
+
}
|
|
4216
|
+
return parsed.data;
|
|
4217
|
+
};
|
|
4218
|
+
var discoverScheduleSort = (raw) => {
|
|
4219
|
+
if (raw === void 0) return void 0;
|
|
4220
|
+
const parsed = DiscoverScheduleSort.safeParse(raw);
|
|
4221
|
+
if (!parsed.success) {
|
|
4222
|
+
throw new InputError(
|
|
4223
|
+
`invalid discover schedule sort "${raw}"; expected one of ${DiscoverScheduleSort.options.join(", ")}`
|
|
4224
|
+
);
|
|
4225
|
+
}
|
|
4226
|
+
return parsed.data;
|
|
4227
|
+
};
|
|
4228
|
+
var discoverTaskSort = (raw) => {
|
|
4229
|
+
if (raw === void 0) return void 0;
|
|
4230
|
+
const parsed = DiscoverTaskSort.safeParse(raw);
|
|
4231
|
+
if (!parsed.success) {
|
|
4232
|
+
throw new InputError(
|
|
4233
|
+
`invalid discover task sort "${raw}"; expected one of ${DiscoverTaskSort.options.join(", ")}`
|
|
4234
|
+
);
|
|
4235
|
+
}
|
|
4236
|
+
return parsed.data;
|
|
4237
|
+
};
|
|
4238
|
+
var discoverTaskTriggerType = (raw) => {
|
|
4239
|
+
if (raw === void 0) return void 0;
|
|
4240
|
+
const parsed = DiscoverTaskTriggerType.safeParse(raw);
|
|
4241
|
+
if (!parsed.success) {
|
|
4242
|
+
throw new InputError(
|
|
4243
|
+
`invalid discover task trigger type "${raw}"; expected one of ${DiscoverTaskTriggerType.options.join(", ")}`
|
|
4244
|
+
);
|
|
4245
|
+
}
|
|
4246
|
+
return parsed.data;
|
|
4247
|
+
};
|
|
4248
|
+
var semanticTaskSort = (raw) => {
|
|
4249
|
+
if (raw === void 0) return void 0;
|
|
4250
|
+
const parsed = SemanticUnderstandingTaskSort.safeParse(raw);
|
|
4251
|
+
if (!parsed.success) {
|
|
4252
|
+
throw new InputError(
|
|
4253
|
+
`invalid semantic task sort "${raw}"; expected one of ${SemanticUnderstandingTaskSort.options.join(", ")}`
|
|
4254
|
+
);
|
|
4255
|
+
}
|
|
4256
|
+
return parsed.data;
|
|
4257
|
+
};
|
|
4258
|
+
var sortDirection = (raw) => {
|
|
4259
|
+
if (raw === void 0) return void 0;
|
|
4260
|
+
const parsed = SortDirection.safeParse(raw);
|
|
4261
|
+
if (!parsed.success) {
|
|
4262
|
+
throw new InputError(
|
|
4263
|
+
`invalid sort direction "${raw}"; expected one of ${SortDirection.options.join(", ")}`
|
|
4264
|
+
);
|
|
4265
|
+
}
|
|
4266
|
+
return parsed.data;
|
|
2781
4267
|
};
|
|
2782
4268
|
function vegaCommand() {
|
|
2783
|
-
const vega = new
|
|
2784
|
-
"
|
|
4269
|
+
const vega = new Command15("vega").description(
|
|
4270
|
+
"Data sources: catalogs, connectors, SQL, index builds"
|
|
2785
4271
|
);
|
|
2786
4272
|
const catalog = vega.command("catalog").description("Catalog entries");
|
|
2787
|
-
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) => {
|
|
2788
4274
|
const o = cmd.optsWithGlobals();
|
|
2789
4275
|
const data = await clientFrom(cmd).vega.catalogs({
|
|
2790
4276
|
limit: o.limit,
|
|
@@ -2792,11 +4278,9 @@ function vegaCommand() {
|
|
|
2792
4278
|
name: o.name,
|
|
2793
4279
|
tag: o.tag,
|
|
2794
4280
|
type: o.type,
|
|
4281
|
+
connectorType: o.connectorType,
|
|
2795
4282
|
enabled: o.enabled === void 0 ? void 0 : o.enabled === "true",
|
|
2796
4283
|
healthCheckStatus: o.healthCheckStatus,
|
|
2797
|
-
includeExtensions: o.includeExtensions,
|
|
2798
|
-
includeExtensionKeys: o.includeExtensionKeys,
|
|
2799
|
-
extensionPairs: parsePairs2(o.extension),
|
|
2800
4284
|
sort: o.sort,
|
|
2801
4285
|
direction: o.direction
|
|
2802
4286
|
});
|
|
@@ -2805,7 +4289,7 @@ function vegaCommand() {
|
|
|
2805
4289
|
catalog.command("get <id>").description("Get a catalog by id").action(async (id, _opts, cmd) => {
|
|
2806
4290
|
printJson(await clientFrom(cmd).vega.getCatalog(id), outputOptions(cmd));
|
|
2807
4291
|
});
|
|
2808
|
-
catalog.command("resources <id>").description("List resources under a catalog").option("--category <c>", "filter by category (e.g. table)").option("--limit <n>", "page size (
|
|
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) => {
|
|
2809
4293
|
printJson(
|
|
2810
4294
|
await clientFrom(cmd).vega.catalogResources(id, opts.category, opts.limit, opts.offset),
|
|
2811
4295
|
outputOptions(cmd)
|
|
@@ -2814,9 +4298,8 @@ function vegaCommand() {
|
|
|
2814
4298
|
catalog.command("health <id>").description("Health-status for a catalog").action(async (id, _opts, cmd) => {
|
|
2815
4299
|
printJson(await clientFrom(cmd).vega.catalogHealth(id), outputOptions(cmd));
|
|
2816
4300
|
});
|
|
2817
|
-
catalog.command("create").description("Create a catalog (data source)").requiredOption("--name <s>", "catalog name").requiredOption("--connector-type <s>", "connector type (e.g. mysql)").requiredOption("--connector-config <json>", "connector config JSON").option("--id <id>", "explicit catalog id").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--enabled", "create enabled (default: disabled)").option("--internal", "create an internal catalog").option("--
|
|
4301
|
+
catalog.command("create").description("Create a catalog (data source)").requiredOption("--name <s>", "catalog name").requiredOption("--connector-type <s>", "connector type (e.g. mysql)").requiredOption("--connector-config <json>", "connector config JSON").option("--id <id>", "explicit catalog id").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--enabled", "create enabled (default: disabled)").option("--internal", "create an internal catalog").option("--allow-unhealthy", "save the catalog when its connection test fails").option("--health-check-mode <mode>", "health schedule: inherit | enabled | disabled").option("--health-check-cron <expr>", "cron expression for enabled health checks").action(async (opts, cmd) => {
|
|
2818
4302
|
const connectorConfig = parseJsonObject(opts.connectorConfig, "--connector-config");
|
|
2819
|
-
const extensions = opts.extensions ? parseStringRecord(opts.extensions, "--extensions") : void 0;
|
|
2820
4303
|
printJson(
|
|
2821
4304
|
await clientFrom(cmd).vega.createCatalog(
|
|
2822
4305
|
{
|
|
@@ -2828,7 +4311,6 @@ function vegaCommand() {
|
|
|
2828
4311
|
description: opts.description,
|
|
2829
4312
|
enabled: opts.enabled ? true : void 0,
|
|
2830
4313
|
internal: opts.internal ? true : void 0,
|
|
2831
|
-
extensions,
|
|
2832
4314
|
healthCheckSchedule: healthCheckSchedule(opts.healthCheckMode, opts.healthCheckCron)
|
|
2833
4315
|
},
|
|
2834
4316
|
{ allowUnhealthy: opts.allowUnhealthy ? true : void 0 }
|
|
@@ -2836,9 +4318,12 @@ function vegaCommand() {
|
|
|
2836
4318
|
outputOptions(cmd)
|
|
2837
4319
|
);
|
|
2838
4320
|
});
|
|
2839
|
-
catalog.command("update <id>").description("Fully update a catalog").requiredOption("--name <s>", "catalog name").requiredOption("--connector-type <s>", "connector type").requiredOption("--enabled <bool>", "current enabled state", bool).option("--connector-config <json>", "connector config JSON").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").
|
|
4321
|
+
catalog.command("update <id>").description("Fully update a catalog").requiredOption("--name <s>", "catalog name").requiredOption("--connector-type <s>", "connector type").requiredOption("--enabled <bool>", "current enabled state", bool).option("--connector-config <json>", "connector config JSON").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").requiredOption(
|
|
4322
|
+
"--expected-update-time <ms>",
|
|
4323
|
+
"optimistic-lock update time",
|
|
4324
|
+
expectedUpdateTime
|
|
4325
|
+
).option("--allow-unhealthy", "save the update when its connection test fails").action(async (id, opts, cmd) => {
|
|
2840
4326
|
const connectorConfig = opts.connectorConfig ? parseJsonObject(opts.connectorConfig, "--connector-config") : void 0;
|
|
2841
|
-
const extensions = opts.extensions ? parseStringRecord(opts.extensions, "--extensions") : void 0;
|
|
2842
4327
|
printJson(
|
|
2843
4328
|
await clientFrom(cmd).vega.updateCatalog(
|
|
2844
4329
|
id,
|
|
@@ -2849,7 +4334,7 @@ function vegaCommand() {
|
|
|
2849
4334
|
tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
|
|
2850
4335
|
description: opts.description,
|
|
2851
4336
|
enabled: opts.enabled,
|
|
2852
|
-
|
|
4337
|
+
expectedUpdateTime: opts.expectedUpdateTime
|
|
2853
4338
|
},
|
|
2854
4339
|
{ allowUnhealthy: opts.allowUnhealthy ? true : void 0 }
|
|
2855
4340
|
),
|
|
@@ -2862,8 +4347,9 @@ function vegaCommand() {
|
|
|
2862
4347
|
catalog.command("disable <id>").description("Disable a catalog").action(async (id, _opts, cmd) => {
|
|
2863
4348
|
printJson(await clientFrom(cmd).vega.disableCatalog(id), outputOptions(cmd));
|
|
2864
4349
|
});
|
|
2865
|
-
catalog.command("delete <id>").description("Delete a catalog").action(async (id,
|
|
2866
|
-
|
|
4350
|
+
catalog.command("delete <id>").description("Delete a catalog").option("--dry-run", "preview deletion impact without changing data").action(async (id, opts, cmd) => {
|
|
4351
|
+
const result = opts.dryRun ? await clientFrom(cmd).vega.deleteCatalog(id, { dryRun: true }) : await clientFrom(cmd).vega.deleteCatalog(id);
|
|
4352
|
+
printJson(result, outputOptions(cmd));
|
|
2867
4353
|
});
|
|
2868
4354
|
catalog.command("test-connection <id>").description("Test a catalog connection").action(async (id, _opts, cmd) => {
|
|
2869
4355
|
printJson(await clientFrom(cmd).vega.testCatalogConnection(id), outputOptions(cmd));
|
|
@@ -2880,17 +4366,183 @@ function vegaCommand() {
|
|
|
2880
4366
|
catalog.command("health-check-schedule <id>").description("Get a catalog health-check schedule").action(async (id, _opts, cmd) => {
|
|
2881
4367
|
printJson(await clientFrom(cmd).vega.catalogHealthCheckSchedule(id), outputOptions(cmd));
|
|
2882
4368
|
});
|
|
2883
|
-
catalog.command("set-health-check-schedule <id>").description("Update a catalog health-check schedule").requiredOption("--mode <mode>", "health schedule: inherit | enabled | disabled").option("--cron <expr>", "cron expression for enabled health checks").
|
|
4369
|
+
catalog.command("set-health-check-schedule <id>").description("Update a catalog health-check schedule").requiredOption("--mode <mode>", "health schedule: inherit | enabled | disabled").option("--cron <expr>", "cron expression for enabled health checks").requiredOption(
|
|
4370
|
+
"--expected-update-time <ms>",
|
|
4371
|
+
"optimistic-lock update time",
|
|
4372
|
+
expectedUpdateTime
|
|
4373
|
+
).action(async (id, opts, cmd) => {
|
|
2884
4374
|
const schedule = healthCheckSchedule(opts.mode, opts.cron);
|
|
2885
4375
|
if (!schedule) throw new InputError("--mode is required");
|
|
2886
4376
|
printJson(
|
|
2887
|
-
await clientFrom(cmd).vega.updateCatalogHealthCheckSchedule(id,
|
|
4377
|
+
await clientFrom(cmd).vega.updateCatalogHealthCheckSchedule(id, {
|
|
4378
|
+
...schedule,
|
|
4379
|
+
expectedUpdateTime: opts.expectedUpdateTime
|
|
4380
|
+
}),
|
|
4381
|
+
outputOptions(cmd)
|
|
4382
|
+
);
|
|
4383
|
+
});
|
|
4384
|
+
catalog.command("discover <id>").description("Trigger catalog resource discovery").option("--strategy <strategy>", `strategy: ${DiscoverStrategy.options.join(" | ")}`).action(async (id, opts, cmd) => {
|
|
4385
|
+
printJson(
|
|
4386
|
+
await clientFrom(cmd).vega.discoverCatalog(id, {
|
|
4387
|
+
strategy: discoverStrategy(opts.strategy)
|
|
4388
|
+
}),
|
|
4389
|
+
outputOptions(cmd)
|
|
4390
|
+
);
|
|
4391
|
+
});
|
|
4392
|
+
const discoverSchedule = vega.command("discover-schedule").description("Resource discovery schedules");
|
|
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) => {
|
|
4394
|
+
printJson(
|
|
4395
|
+
await clientFrom(cmd).vega.discoverSchedules({
|
|
4396
|
+
name: opts.name,
|
|
4397
|
+
catalogId: opts.catalogId,
|
|
4398
|
+
enabled: opts.enabled,
|
|
4399
|
+
limit: opts.limit,
|
|
4400
|
+
offset: opts.offset,
|
|
4401
|
+
sort: discoverScheduleSort(opts.sort),
|
|
4402
|
+
direction: sortDirection(opts.direction)
|
|
4403
|
+
}),
|
|
4404
|
+
outputOptions(cmd)
|
|
4405
|
+
);
|
|
4406
|
+
});
|
|
4407
|
+
discoverSchedule.command("get <id>").description("Get a discovery schedule").action(async (id, _opts, cmd) => {
|
|
4408
|
+
printJson(await clientFrom(cmd).vega.getDiscoverSchedule(id), outputOptions(cmd));
|
|
4409
|
+
});
|
|
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) => {
|
|
4411
|
+
printJson(
|
|
4412
|
+
await clientFrom(cmd).vega.createDiscoverSchedule({
|
|
4413
|
+
name: opts.name,
|
|
4414
|
+
catalogId: opts.catalogId,
|
|
4415
|
+
cronExpr: opts.cron,
|
|
4416
|
+
startTime: opts.startTime,
|
|
4417
|
+
endTime: opts.endTime,
|
|
4418
|
+
enabled: opts.enabled ? true : void 0,
|
|
4419
|
+
strategy: discoverStrategy(opts.strategy)
|
|
4420
|
+
}),
|
|
4421
|
+
outputOptions(cmd)
|
|
4422
|
+
);
|
|
4423
|
+
});
|
|
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(
|
|
4425
|
+
"--expected-update-time <ms>",
|
|
4426
|
+
"optimistic-lock update time",
|
|
4427
|
+
expectedUpdateTime
|
|
4428
|
+
).action(async (id, opts, cmd) => {
|
|
4429
|
+
printJson(
|
|
4430
|
+
await clientFrom(cmd).vega.updateDiscoverSchedule(id, {
|
|
4431
|
+
name: opts.name,
|
|
4432
|
+
catalogId: opts.catalogId,
|
|
4433
|
+
cronExpr: opts.cron,
|
|
4434
|
+
enabled: opts.enabled,
|
|
4435
|
+
startTime: opts.startTime,
|
|
4436
|
+
endTime: opts.endTime,
|
|
4437
|
+
strategy: requiredDiscoverStrategy(opts.strategy),
|
|
4438
|
+
expectedUpdateTime: opts.expectedUpdateTime
|
|
4439
|
+
}),
|
|
4440
|
+
outputOptions(cmd)
|
|
4441
|
+
);
|
|
4442
|
+
});
|
|
4443
|
+
for (const action of ["enable", "disable", "delete"]) {
|
|
4444
|
+
discoverSchedule.command(`${action} <id>`).description(`${action[0]?.toUpperCase()}${action.slice(1)} a discovery schedule`).action(async (id, _opts, cmd) => {
|
|
4445
|
+
const api = clientFrom(cmd).vega;
|
|
4446
|
+
const result = action === "enable" ? await api.enableDiscoverSchedule(id) : action === "disable" ? await api.disableDiscoverSchedule(id) : await api.deleteDiscoverSchedule(id);
|
|
4447
|
+
printJson(result, outputOptions(cmd));
|
|
4448
|
+
});
|
|
4449
|
+
}
|
|
4450
|
+
const discoverTask = vega.command("discover-task").description("Resource discovery tasks");
|
|
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) => {
|
|
4452
|
+
printJson(
|
|
4453
|
+
await clientFrom(cmd).vega.discoverTasks({
|
|
4454
|
+
catalogId: opts.catalogId,
|
|
4455
|
+
resourceId: opts.resourceId,
|
|
4456
|
+
scheduleId: opts.scheduleId,
|
|
4457
|
+
status: taskStatuses(opts.status),
|
|
4458
|
+
strategy: discoverStrategy(opts.strategy),
|
|
4459
|
+
triggerType: discoverTaskTriggerType(opts.triggerType),
|
|
4460
|
+
limit: opts.limit,
|
|
4461
|
+
offset: opts.offset,
|
|
4462
|
+
sort: discoverTaskSort(opts.sort),
|
|
4463
|
+
direction: sortDirection(opts.direction)
|
|
4464
|
+
}),
|
|
4465
|
+
outputOptions(cmd)
|
|
4466
|
+
);
|
|
4467
|
+
});
|
|
4468
|
+
discoverTask.command("get <id>").description("Get a discovery task").action(async (id, _opts, cmd) => {
|
|
4469
|
+
printJson(await clientFrom(cmd).vega.getDiscoverTask(id), outputOptions(cmd));
|
|
4470
|
+
});
|
|
4471
|
+
discoverTask.command("delete <ids...>").description("Delete completed discovery tasks").option("--ignore-missing", "ignore missing task ids").action(async (ids, opts, cmd) => {
|
|
4472
|
+
printJson(
|
|
4473
|
+
await clientFrom(cmd).vega.deleteDiscoverTasks(ids, {
|
|
4474
|
+
ignoreMissing: opts.ignoreMissing
|
|
4475
|
+
}),
|
|
4476
|
+
outputOptions(cmd)
|
|
4477
|
+
);
|
|
4478
|
+
});
|
|
4479
|
+
const semanticTask = vega.command("semantic-task").description("Semantic-understanding tasks");
|
|
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(
|
|
4481
|
+
"--apply-mode <mode>",
|
|
4482
|
+
`apply mode: ${SemanticUnderstandingApplyMode.options.join(" | ")}`
|
|
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) => {
|
|
4484
|
+
printJson(
|
|
4485
|
+
await clientFrom(cmd).vega.semanticUnderstandingTasks({
|
|
4486
|
+
scope: semanticScope(opts.scope),
|
|
4487
|
+
catalogId: opts.catalogId,
|
|
4488
|
+
resourceId: opts.resourceId,
|
|
4489
|
+
status: taskStatuses(opts.status),
|
|
4490
|
+
applyMode: semanticApplyMode(opts.applyMode),
|
|
4491
|
+
applied: opts.applied,
|
|
4492
|
+
limit: opts.limit,
|
|
4493
|
+
offset: opts.offset,
|
|
4494
|
+
sort: semanticTaskSort(opts.sort),
|
|
4495
|
+
direction: sortDirection(opts.direction)
|
|
4496
|
+
}),
|
|
4497
|
+
outputOptions(cmd)
|
|
4498
|
+
);
|
|
4499
|
+
});
|
|
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) => {
|
|
4501
|
+
const scope = semanticScope(opts.scope);
|
|
4502
|
+
if (!scope) throw new InputError("--scope is required");
|
|
4503
|
+
const applyMode = semanticApplyMode(opts.applyMode);
|
|
4504
|
+
if (scope === "catalog" && !opts.catalogId) {
|
|
4505
|
+
throw new InputError("--catalog-id is required for catalog scope");
|
|
4506
|
+
}
|
|
4507
|
+
if (scope === "resource" && !opts.resourceId) {
|
|
4508
|
+
throw new InputError("--resource-id is required for resource scope");
|
|
4509
|
+
}
|
|
4510
|
+
if (scope === "catalog" && (opts.includeSampleRows || opts.sampleMaxRows !== void 0)) {
|
|
4511
|
+
throw new InputError("sample row options are only valid for resource scope");
|
|
4512
|
+
}
|
|
4513
|
+
if (scope === "resource" && opts.includeSampleRows && opts.sampleMaxRows === void 0) {
|
|
4514
|
+
throw new InputError("--sample-max-rows is required with --include-sample-rows");
|
|
4515
|
+
}
|
|
4516
|
+
if (scope === "resource" && !opts.includeSampleRows && opts.sampleMaxRows !== void 0) {
|
|
4517
|
+
throw new InputError("--sample-max-rows requires --include-sample-rows");
|
|
4518
|
+
}
|
|
4519
|
+
if (opts.sampleMaxRows !== void 0 && (opts.sampleMaxRows < 1 || opts.sampleMaxRows > 20)) {
|
|
4520
|
+
throw new InputError("--sample-max-rows must be between 1 and 20");
|
|
4521
|
+
}
|
|
4522
|
+
const common = {
|
|
4523
|
+
applyMode,
|
|
4524
|
+
confidenceThreshold: opts.confidenceThreshold
|
|
4525
|
+
};
|
|
4526
|
+
const request = scope === "catalog" ? { scope: "catalog", catalogId: opts.catalogId, ...common } : {
|
|
4527
|
+
scope: "resource",
|
|
4528
|
+
resourceId: opts.resourceId,
|
|
4529
|
+
includeSampleRows: opts.includeSampleRows ? true : void 0,
|
|
4530
|
+
samplePolicy: opts.sampleMaxRows === void 0 ? void 0 : { masked: false, maxRows: opts.sampleMaxRows },
|
|
4531
|
+
...common
|
|
4532
|
+
};
|
|
4533
|
+
printJson(
|
|
4534
|
+
await clientFrom(cmd).vega.createSemanticUnderstandingTask(request),
|
|
2888
4535
|
outputOptions(cmd)
|
|
2889
4536
|
);
|
|
2890
4537
|
});
|
|
2891
|
-
|
|
4538
|
+
semanticTask.command("get <id>").description("Get a semantic-understanding task").action(async (id, _opts, cmd) => {
|
|
4539
|
+
printJson(await clientFrom(cmd).vega.getSemanticUnderstandingTask(id), outputOptions(cmd));
|
|
4540
|
+
});
|
|
4541
|
+
semanticTask.command("delete <ids...>").description("Delete completed semantic-understanding tasks").option("--ignore-missing", "ignore missing task ids").action(async (ids, opts, cmd) => {
|
|
2892
4542
|
printJson(
|
|
2893
|
-
await clientFrom(cmd).vega.
|
|
4543
|
+
await clientFrom(cmd).vega.deleteSemanticUnderstandingTasks(ids, {
|
|
4544
|
+
ignoreMissing: opts.ignoreMissing
|
|
4545
|
+
}),
|
|
2894
4546
|
outputOptions(cmd)
|
|
2895
4547
|
);
|
|
2896
4548
|
});
|
|
@@ -2901,17 +4553,19 @@ function vegaCommand() {
|
|
|
2901
4553
|
connector.command("get <type>").description("Get a connector type").action(async (type, _opts, cmd) => {
|
|
2902
4554
|
printJson(await clientFrom(cmd).vega.connectorType(type), outputOptions(cmd));
|
|
2903
4555
|
});
|
|
2904
|
-
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(
|
|
2905
4559
|
"--query <sql>",
|
|
2906
4560
|
"SQL string; reference a resource with a {{<resource-id>}} placeholder"
|
|
2907
|
-
).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(
|
|
2908
4562
|
"-d, --data <json>",
|
|
2909
4563
|
"full request body as JSON (advanced; wins over individual query flags)"
|
|
2910
4564
|
).action(async (opts, cmd) => {
|
|
2911
4565
|
let body;
|
|
2912
4566
|
if (opts.data) {
|
|
2913
4567
|
try {
|
|
2914
|
-
body =
|
|
4568
|
+
body = parseBigIntJSON(opts.data);
|
|
2915
4569
|
} catch {
|
|
2916
4570
|
throw new InputError("--data must be valid JSON");
|
|
2917
4571
|
}
|
|
@@ -2948,18 +4602,15 @@ function vegaCommand() {
|
|
|
2948
4602
|
printJson(await clientFrom(cmd).vega.sql(body), outputOptions(cmd));
|
|
2949
4603
|
});
|
|
2950
4604
|
const resource = vega.command("resource").description("Vega-backend resources");
|
|
2951
|
-
resource.command("list").description("List resources").option("--
|
|
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) => {
|
|
2952
4606
|
printJson(
|
|
2953
4607
|
await clientFrom(cmd).resource.list({
|
|
2954
|
-
|
|
4608
|
+
catalogId: opts.catalogId,
|
|
2955
4609
|
category: opts.type ?? opts.category,
|
|
2956
4610
|
status: opts.status,
|
|
2957
|
-
|
|
4611
|
+
schema: opts.schema,
|
|
2958
4612
|
limit: opts.limit,
|
|
2959
4613
|
offset: opts.offset,
|
|
2960
|
-
includeExtensions: opts.includeExtensions,
|
|
2961
|
-
includeExtensionKeys: opts.includeExtensionKeys,
|
|
2962
|
-
extensionPairs: parsePairs2(opts.extension),
|
|
2963
4614
|
sort: opts.sort,
|
|
2964
4615
|
direction: opts.direction
|
|
2965
4616
|
}),
|
|
@@ -2969,17 +4620,75 @@ function vegaCommand() {
|
|
|
2969
4620
|
resource.command("get <id>").description("Get a resource").action(async (id, _opts, cmd) => {
|
|
2970
4621
|
printJson(await clientFrom(cmd).resource.get(id), outputOptions(cmd));
|
|
2971
4622
|
});
|
|
2972
|
-
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) => {
|
|
2973
4634
|
printJson(
|
|
2974
4635
|
await clientFrom(cmd).resource.query(id, { limit: opts.limit, offset: opts.offset }),
|
|
2975
4636
|
outputOptions(cmd)
|
|
2976
4637
|
);
|
|
2977
4638
|
});
|
|
4639
|
+
resource.command("document-get <resource-id> <document-id>").description("Get one dataset document").action(async (resourceId, documentId, _opts, cmd) => {
|
|
4640
|
+
printJson(
|
|
4641
|
+
await clientFrom(cmd).resource.getDocument(resourceId, documentId),
|
|
4642
|
+
outputOptions(cmd)
|
|
4643
|
+
);
|
|
4644
|
+
});
|
|
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) => {
|
|
4649
|
+
printJson(
|
|
4650
|
+
await clientFrom(cmd).resource.createDocuments(
|
|
4651
|
+
resourceId,
|
|
4652
|
+
parseJsonArray(opts.data, "--data")
|
|
4653
|
+
),
|
|
4654
|
+
outputOptions(cmd)
|
|
4655
|
+
);
|
|
4656
|
+
});
|
|
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) => {
|
|
4661
|
+
const documents = parseJsonArray(opts.data, "--data");
|
|
4662
|
+
if (documents.some((document) => typeof document.id !== "string")) {
|
|
4663
|
+
throw new InputError("every document in --data must have a string id");
|
|
4664
|
+
}
|
|
4665
|
+
printJson(
|
|
4666
|
+
await clientFrom(cmd).resource.upsertDocuments(resourceId, documents),
|
|
4667
|
+
outputOptions(cmd)
|
|
4668
|
+
);
|
|
4669
|
+
});
|
|
4670
|
+
resource.command("document-delete <resource-id> <document-ids...>").description("Delete dataset documents by id").action(async (resourceId, documentIds, _opts, cmd) => {
|
|
4671
|
+
printJson(
|
|
4672
|
+
await clientFrom(cmd).resource.deleteDocuments(resourceId, documentIds),
|
|
4673
|
+
outputOptions(cmd)
|
|
4674
|
+
);
|
|
4675
|
+
});
|
|
4676
|
+
resource.command("document-delete-filter <resource-id>").description("Delete dataset documents by a non-empty filter").requiredOption("--filter <json>", "filter_condition JSON object").action(async (resourceId, opts, cmd) => {
|
|
4677
|
+
const filter = parseJsonObject(opts.filter, "--filter");
|
|
4678
|
+
if (!Object.keys(filter).length) throw new InputError("--filter must not be empty");
|
|
4679
|
+
printJson(
|
|
4680
|
+
await clientFrom(cmd).resource.deleteDocumentsByFilter(resourceId, filter),
|
|
4681
|
+
outputOptions(cmd)
|
|
4682
|
+
);
|
|
4683
|
+
});
|
|
2978
4684
|
const dataset = vega.command("dataset").description("Dataset index build tasks");
|
|
2979
4685
|
dataset.command("build <resource-id>").description("Build a resource's index (creates a BuildTask)").requiredOption("--mode <mode>", "build mode: batch | streaming").option("--embedding-fields <list>", "comma-separated fields to vectorize").option(
|
|
2980
4686
|
"--build-key-fields <list>",
|
|
2981
4687
|
"comma-separated key fields (batch: time; streaming: row id)"
|
|
2982
|
-
).option(
|
|
4688
|
+
).option(
|
|
4689
|
+
"--embedding-model <name-or-id>",
|
|
4690
|
+
"default small-model name (a numeric ID is resolved to its name)"
|
|
4691
|
+
).option("--fulltext-fields <list>", "comma-separated fields for fulltext index").option("--fulltext-analyzer <name>", "fulltext analyzer").option("--execute-type <type>", "batch execution type: incremental | full").option("--wait", "poll until the build reaches a terminal state").option("--timeout <s>", "wait timeout in seconds", (v) => Number.parseInt(v, 10), 300).action(async (resourceId, _opts, cmd) => {
|
|
2983
4692
|
const o = cmd.optsWithGlobals();
|
|
2984
4693
|
const embeddingFields = csv(o.embeddingFields);
|
|
2985
4694
|
const buildKeyFields = csv(o.buildKeyFields);
|
|
@@ -3007,28 +4716,26 @@ function vegaCommand() {
|
|
|
3007
4716
|
const task = await clientFrom(cmd).vega.buildStatus(taskId);
|
|
3008
4717
|
printJson(task, outputOptions(cmd));
|
|
3009
4718
|
});
|
|
3010
|
-
dataset.command("build-list").description("List BuildTasks").option("--limit <n>", "page size",
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
);
|
|
3015
|
-
}
|
|
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) => {
|
|
3016
4723
|
printJson(
|
|
3017
4724
|
await clientFrom(cmd).vega.buildTasks({
|
|
3018
4725
|
limit: opts.limit,
|
|
3019
4726
|
offset: opts.offset,
|
|
3020
4727
|
resourceId: opts.resourceId,
|
|
3021
4728
|
catalogId: opts.catalogId,
|
|
3022
|
-
status: opts.status,
|
|
3023
|
-
active: opts.active,
|
|
4729
|
+
status: buildTaskStatuses(opts.status),
|
|
3024
4730
|
mode: opts.mode,
|
|
3025
|
-
|
|
3026
|
-
|
|
4731
|
+
executeType: buildTaskExecuteType(opts.executeType),
|
|
4732
|
+
sort: buildTaskSort(opts.sort),
|
|
4733
|
+
direction: sortDirection(opts.direction)
|
|
3027
4734
|
}),
|
|
3028
4735
|
outputOptions(cmd)
|
|
3029
4736
|
);
|
|
3030
4737
|
});
|
|
3031
|
-
dataset.command("build-start <task-id>").description("Start a BuildTask").option("--reset", "restart a full task from the beginning (
|
|
4738
|
+
dataset.command("build-start <task-id>").description("Start a BuildTask").option("--reset", "restart a full task from the beginning (rejected for incremental tasks)").action(async (taskId, opts, cmd) => {
|
|
3032
4739
|
printJson(
|
|
3033
4740
|
await clientFrom(cmd).vega.startBuildTask(taskId, { reset: opts.reset }),
|
|
3034
4741
|
outputOptions(cmd)
|
|
@@ -3037,43 +4744,142 @@ function vegaCommand() {
|
|
|
3037
4744
|
dataset.command("build-stop <task-id>").description("Stop a BuildTask").action(async (taskId, _opts, cmd) => {
|
|
3038
4745
|
printJson(await clientFrom(cmd).vega.stopBuildTask(taskId), outputOptions(cmd));
|
|
3039
4746
|
});
|
|
3040
|
-
dataset.command("build-delete <ids...>").description("Delete one or more BuildTasks").option("--ignore-missing", "ignore missing task ids").
|
|
4747
|
+
dataset.command("build-delete <ids...>").description("Delete one or more BuildTasks").option("--ignore-missing", "ignore missing task ids").action(async (ids, opts, cmd) => {
|
|
3041
4748
|
printJson(
|
|
3042
4749
|
await clientFrom(cmd).vega.deleteBuildTasks(ids, {
|
|
3043
|
-
ignoreMissing: opts.ignoreMissing
|
|
3044
|
-
deleteActiveIndex: opts.deleteActiveIndex
|
|
4750
|
+
ignoreMissing: opts.ignoreMissing
|
|
3045
4751
|
}),
|
|
3046
4752
|
outputOptions(cmd)
|
|
3047
4753
|
);
|
|
3048
4754
|
});
|
|
3049
|
-
|
|
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;
|
|
3050
4864
|
}
|
|
3051
4865
|
|
|
3052
4866
|
// src/cli.ts
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
program
|
|
3058
|
-
program.addCommand(appkeyCommand());
|
|
3059
|
-
program.addCommand(vegaCommand());
|
|
3060
|
-
program.addCommand(bknCommand());
|
|
3061
|
-
program.addCommand(resourceCommand());
|
|
3062
|
-
program.addCommand(dataflowCommand());
|
|
3063
|
-
program.addCommand(contextCommand());
|
|
3064
|
-
program.addCommand(agentCommand());
|
|
3065
|
-
program.addCommand(modelCommand());
|
|
3066
|
-
program.addCommand(skillCommand());
|
|
3067
|
-
program.addCommand(toolboxCommand());
|
|
3068
|
-
program.addCommand(toolCommand());
|
|
3069
|
-
program.addCommand(traceCommand());
|
|
3070
|
-
program.addCommand(adminCommand());
|
|
3071
|
-
program.addCommand(exploreCommand());
|
|
3072
|
-
installGroupedHelp(program);
|
|
4867
|
+
process.stdout.on("error", (err) => {
|
|
4868
|
+
if (err.code === "EPIPE") process.exit(0);
|
|
4869
|
+
throw err;
|
|
4870
|
+
});
|
|
4871
|
+
var program = buildProgram();
|
|
3073
4872
|
var argv = process.argv.map((a) => a === "-bd" ? "--biz-domain" : a);
|
|
4873
|
+
if (argv.includes("--dry-run")) enableDryRun();
|
|
3074
4874
|
try {
|
|
3075
4875
|
await program.parseAsync(argv);
|
|
3076
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
|
+
}
|
|
3077
4883
|
console.error(formatError(err));
|
|
3078
4884
|
await releaseLifecycleSessions();
|
|
3079
4885
|
process.exit(toExitCode(err));
|