@openbkn/bkn-sdk 0.1.1-alpha.9 → 0.1.2
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/LICENSE +1 -0
- package/NOTICE +21 -0
- package/README.md +33 -26
- package/README.zh.md +11 -12
- package/dist/{chunk-BFE4SU3V.js → chunk-LH3ONZGQ.js} +2345 -220
- package/dist/cli.js +617 -208
- package/dist/index.d.ts +974 -81
- package/dist/index.js +3 -1
- package/package.json +6 -4
- package/dist/chunk-BFE4SU3V.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
HttpError,
|
|
7
7
|
InputError,
|
|
8
8
|
activePlatform,
|
|
9
|
-
attachNoAuth,
|
|
10
9
|
attachToken,
|
|
10
|
+
changePasswordSafe,
|
|
11
11
|
createClient,
|
|
12
12
|
credentialDeviceLogin,
|
|
13
13
|
currentToken,
|
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
deletePlatform,
|
|
17
17
|
deviceLogin,
|
|
18
18
|
exportCreds,
|
|
19
|
-
fetchAuthStatus,
|
|
20
19
|
formatError,
|
|
21
20
|
getUserSafe,
|
|
22
21
|
isHeadless,
|
|
@@ -28,24 +27,24 @@ import {
|
|
|
28
27
|
rawCall,
|
|
29
28
|
readPlatformConfig,
|
|
30
29
|
renderReportMarkdown,
|
|
31
|
-
request,
|
|
32
30
|
resolveContext,
|
|
33
31
|
setActivePlatform,
|
|
34
32
|
status,
|
|
35
33
|
switchUser,
|
|
36
34
|
toExitCode,
|
|
37
35
|
use,
|
|
36
|
+
validateFixturePath,
|
|
38
37
|
whoami,
|
|
39
38
|
writePlatformConfig
|
|
40
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-LH3ONZGQ.js";
|
|
41
40
|
|
|
42
41
|
// src/cli.ts
|
|
43
|
-
import { Command as
|
|
42
|
+
import { Command as Command17 } from "commander";
|
|
44
43
|
|
|
45
44
|
// package.json
|
|
46
45
|
var package_default = {
|
|
47
46
|
name: "@openbkn/bkn-sdk",
|
|
48
|
-
version: "0.1.
|
|
47
|
+
version: "0.1.2",
|
|
49
48
|
description: "Unified TypeScript SDK + CLI for the BKN (Business Knowledge Network) platform.",
|
|
50
49
|
type: "module",
|
|
51
50
|
license: "Apache-2.0",
|
|
@@ -63,7 +62,7 @@ var package_default = {
|
|
|
63
62
|
import: "./dist/index.js"
|
|
64
63
|
}
|
|
65
64
|
},
|
|
66
|
-
files: ["dist", "README.md", "README.zh.md", "LICENSE"],
|
|
65
|
+
files: ["dist", "!dist/**/*.map", "README.md", "README.zh.md", "LICENSE", "NOTICE"],
|
|
67
66
|
publishConfig: {
|
|
68
67
|
access: "public"
|
|
69
68
|
},
|
|
@@ -76,21 +75,23 @@ var package_default = {
|
|
|
76
75
|
build: "tsup",
|
|
77
76
|
dev: "tsup --watch",
|
|
78
77
|
typecheck: "tsc --noEmit",
|
|
79
|
-
|
|
78
|
+
"check:deps": "node scripts/check-no-self-dep.mjs",
|
|
79
|
+
lint: "npm run check:deps && biome check . && tsc --noEmit",
|
|
80
80
|
format: "biome format --write .",
|
|
81
81
|
test: "vitest run",
|
|
82
|
+
"test:e2e:trace-business": "npm run build && node test/e2e/bkn-trace-business-interaction.mjs",
|
|
82
83
|
"test:cover": "vitest run --coverage",
|
|
83
84
|
ci: "npm run lint && npm test",
|
|
84
85
|
prepublishOnly: "npm run ci && npm run build"
|
|
85
86
|
},
|
|
86
87
|
dependencies: {
|
|
87
88
|
"@clack/prompts": "^0.9.1",
|
|
88
|
-
"@openbkn/bkn-sdk": "^0.1.1-alpha.3",
|
|
89
89
|
chalk: "^5.4.1",
|
|
90
90
|
commander: "^13.1.0",
|
|
91
91
|
"csv-parse": "^6.2.1",
|
|
92
92
|
"js-yaml": "^4.2.0",
|
|
93
93
|
jszip: "^3.10.1",
|
|
94
|
+
undici: "^8.7.0",
|
|
94
95
|
zod: "^3.24.1"
|
|
95
96
|
},
|
|
96
97
|
devDependencies: {
|
|
@@ -104,6 +105,7 @@ var package_default = {
|
|
|
104
105
|
};
|
|
105
106
|
|
|
106
107
|
// src/commands/admin.ts
|
|
108
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
107
109
|
import { Command as Command2 } from "commander";
|
|
108
110
|
|
|
109
111
|
// src/help/grouped-help.ts
|
|
@@ -174,10 +176,15 @@ function renderOrgTree(nodes, prefix = "") {
|
|
|
174
176
|
// src/utils/output.ts
|
|
175
177
|
function printJson(value, opts = {}) {
|
|
176
178
|
if (opts.json || opts.compact) {
|
|
177
|
-
|
|
179
|
+
const json = JSON.stringify(value === void 0 ? null : value, null, opts.compact ? 0 : 2);
|
|
180
|
+
process.stdout.write(`${json}
|
|
178
181
|
`);
|
|
179
182
|
return;
|
|
180
183
|
}
|
|
184
|
+
if (value === void 0) {
|
|
185
|
+
process.stdout.write("(ok)\n");
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
181
188
|
const rows = toRows(value);
|
|
182
189
|
if (rows) {
|
|
183
190
|
const fullColumns = columnsOf(rows).filter((c) => rows.some((r) => stringifyCell(r[c]) !== ""));
|
|
@@ -215,7 +222,8 @@ var ROW_ENVELOPES = [
|
|
|
215
222
|
"users",
|
|
216
223
|
"roles",
|
|
217
224
|
"departments",
|
|
218
|
-
"members"
|
|
225
|
+
"members",
|
|
226
|
+
"keys"
|
|
219
227
|
];
|
|
220
228
|
function toRows(value) {
|
|
221
229
|
const isRowArray = (v) => Array.isArray(v) && v.length > 0 && v.every((x) => x !== null && typeof x === "object" && !Array.isArray(x));
|
|
@@ -300,16 +308,46 @@ function stringifyCell(v) {
|
|
|
300
308
|
return s.length > CELL_MAX ? `${s.slice(0, CELL_MAX - 1)}\u2026` : s;
|
|
301
309
|
}
|
|
302
310
|
|
|
311
|
+
// src/utils/prompt.ts
|
|
312
|
+
import { createInterface } from "readline";
|
|
313
|
+
function promptLine(query, hidden = false) {
|
|
314
|
+
return new Promise((resolve2) => {
|
|
315
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
316
|
+
if (hidden) {
|
|
317
|
+
const mutable = rl;
|
|
318
|
+
mutable._writeToOutput = (s) => {
|
|
319
|
+
if (s.startsWith(query)) process.stdout.write(query);
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
rl.question(query, (answer) => {
|
|
323
|
+
rl.close();
|
|
324
|
+
if (hidden) process.stdout.write("\n");
|
|
325
|
+
resolve2(answer.trim());
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
303
330
|
// src/commands/_shared.ts
|
|
304
331
|
import { readFileSync } from "fs";
|
|
332
|
+
function traceOptionsFrom(o) {
|
|
333
|
+
const conversationId = (typeof o.conversationId === "string" ? o.conversationId : void 0) ?? process.env.BKN_CONVERSATION_ID;
|
|
334
|
+
const interactionId = (typeof o.interactionId === "string" ? o.interactionId : void 0) ?? process.env.BKN_INTERACTION_ID;
|
|
335
|
+
if (!conversationId && !interactionId) return void 0;
|
|
336
|
+
return {
|
|
337
|
+
...conversationId ? { conversationId } : {},
|
|
338
|
+
...interactionId ? { interactionId } : {}
|
|
339
|
+
};
|
|
340
|
+
}
|
|
305
341
|
function clientFrom(cmd) {
|
|
306
342
|
const o = cmd.optsWithGlobals();
|
|
343
|
+
const trace = traceOptionsFrom(o);
|
|
307
344
|
return createClient({
|
|
308
345
|
baseUrl: o.baseUrl,
|
|
309
346
|
token: o.token,
|
|
310
347
|
user: o.user,
|
|
311
348
|
businessDomain: o.bizDomain,
|
|
312
|
-
insecure: o.insecure
|
|
349
|
+
insecure: o.insecure,
|
|
350
|
+
...trace ? { trace } : {}
|
|
313
351
|
});
|
|
314
352
|
}
|
|
315
353
|
function outputOptions(cmd) {
|
|
@@ -331,27 +369,7 @@ function readBody(opts) {
|
|
|
331
369
|
}
|
|
332
370
|
|
|
333
371
|
// src/commands/auth.ts
|
|
334
|
-
import { createInterface } from "readline";
|
|
335
372
|
import { Command } from "commander";
|
|
336
|
-
|
|
337
|
-
// src/api/eacp-crypto.ts
|
|
338
|
-
import {
|
|
339
|
-
constants,
|
|
340
|
-
createPrivateKey,
|
|
341
|
-
createPublicKey,
|
|
342
|
-
publicEncrypt
|
|
343
|
-
} from "crypto";
|
|
344
|
-
|
|
345
|
-
// src/api/admin.ts
|
|
346
|
-
async function changePasswordSafe(ctx, account, oldPassword, newPassword) {
|
|
347
|
-
await request(ctx, "/api/safe/v1/auth/change-password", {
|
|
348
|
-
method: "POST",
|
|
349
|
-
body: { account, old_password: oldPassword, new_password: newPassword }
|
|
350
|
-
});
|
|
351
|
-
return { ok: true };
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// src/commands/auth.ts
|
|
355
373
|
async function resolveAccount(baseUrl, accessToken, insecure, idToken) {
|
|
356
374
|
const sub = decodeJwt(idToken ?? accessToken)?.sub;
|
|
357
375
|
if (!sub) return void 0;
|
|
@@ -365,22 +383,6 @@ async function resolveAccount(baseUrl, accessToken, insecure, idToken) {
|
|
|
365
383
|
return void 0;
|
|
366
384
|
}
|
|
367
385
|
}
|
|
368
|
-
function promptLine(query, hidden = false) {
|
|
369
|
-
return new Promise((resolve2) => {
|
|
370
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
371
|
-
if (hidden) {
|
|
372
|
-
const mutable = rl;
|
|
373
|
-
mutable._writeToOutput = (s) => {
|
|
374
|
-
if (s.startsWith(query)) process.stdout.write(query);
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
rl.question(query, (answer) => {
|
|
378
|
-
rl.close();
|
|
379
|
-
if (hidden) process.stdout.write("\n");
|
|
380
|
-
resolve2(answer.trim());
|
|
381
|
-
});
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
386
|
function renderSessions(items) {
|
|
385
387
|
const byPlatform = /* @__PURE__ */ new Map();
|
|
386
388
|
for (const it of items) {
|
|
@@ -396,25 +398,17 @@ function renderSessions(items) {
|
|
|
396
398
|
return lines.join("\n") || "(no saved sessions)";
|
|
397
399
|
}
|
|
398
400
|
function registerAuthLeaves(cmd) {
|
|
399
|
-
cmd.command("login <url>").description("Log in to a platform (attach a token, or browser/password OAuth)").option("-u, --username <name>", "username for password signin").option("-p, --password <pwd>", "password for password signin").option("--token <token>", "provide a token directly (CI / headless)").option("--client-id <id>", "
|
|
400
|
-
"--port <n>",
|
|
401
|
-
"loopback redirect port for the auth_code flow",
|
|
402
|
-
(v) => Number.parseInt(v, 10)
|
|
403
|
-
).option("--device", "headless device-code login (RFC 8628) \u2014 no callback server, no password").option("--audience <aud>", "device-code token audience", "bkn-safe").option(
|
|
401
|
+
cmd.command("login <url>").description("Log in to a platform (attach a token, or browser/password OAuth)").option("-u, --username <name>", "username for password signin").option("-p, --password <pwd>", "password for password signin").option("--token <token>", "provide a token directly (CI / headless)").option("--client-id <id>", "OAuth2 client id to authenticate as").option("--device", "headless device-code login (RFC 8628) \u2014 no callback server, no password").option("--audience <aud>", "device-code token audience", "bkn-safe").option(
|
|
404
402
|
"--timeout <s>",
|
|
405
403
|
"device-login wait before timing out",
|
|
406
404
|
(v) => Number.parseInt(v, 10),
|
|
407
405
|
120
|
|
408
|
-
).option("--no-browser", "
|
|
406
|
+
).option("--no-browser", "print the URL instead of opening a browser").action(async (url, opts, cmd2) => {
|
|
409
407
|
const g = cmd2.optsWithGlobals();
|
|
410
|
-
if (g.insecure) process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
411
408
|
const out = outputOptions(cmd2);
|
|
412
409
|
const report = (r) => {
|
|
413
410
|
if (out.json || out.compact) {
|
|
414
411
|
printJson({ loggedIn: true, ...r }, out);
|
|
415
|
-
} else if (r.noAuth) {
|
|
416
|
-
process.stdout.write(`Registered ${r.baseUrl ?? url} (no authentication)
|
|
417
|
-
`);
|
|
418
412
|
} else {
|
|
419
413
|
process.stdout.write(`Logged in to ${r.baseUrl ?? url} as ${r.username ?? r.userId}
|
|
420
414
|
`);
|
|
@@ -425,19 +419,6 @@ function registerAuthLeaves(cmd) {
|
|
|
425
419
|
report(attachToken(url, token, { insecure: g.insecure }));
|
|
426
420
|
return;
|
|
427
421
|
}
|
|
428
|
-
if (opts.auth === false) {
|
|
429
|
-
report(attachNoAuth(url, { insecure: g.insecure }));
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
const authStatus = await fetchAuthStatus(url);
|
|
433
|
-
if (authStatus && !authStatus.enabled) {
|
|
434
|
-
process.stderr.write(
|
|
435
|
-
`Platform auth is disabled (stack: ${authStatus.stack ?? "none"}) \u2014 registering without auth.
|
|
436
|
-
`
|
|
437
|
-
);
|
|
438
|
-
report(attachNoAuth(url, { insecure: g.insecure }));
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
422
|
let tokens;
|
|
442
423
|
let account;
|
|
443
424
|
try {
|
|
@@ -448,7 +429,8 @@ function registerAuthLeaves(cmd) {
|
|
|
448
429
|
tokens = await credentialDeviceLogin(url, username, password, {
|
|
449
430
|
clientId: opts.clientId,
|
|
450
431
|
audience: opts.audience,
|
|
451
|
-
timeoutMs: opts.timeout * 1e3
|
|
432
|
+
timeoutMs: opts.timeout * 1e3,
|
|
433
|
+
insecure: g.insecure
|
|
452
434
|
});
|
|
453
435
|
} else {
|
|
454
436
|
const headless = isHeadless();
|
|
@@ -457,6 +439,7 @@ function registerAuthLeaves(cmd) {
|
|
|
457
439
|
clientId: opts.clientId,
|
|
458
440
|
audience: opts.audience,
|
|
459
441
|
timeoutMs: opts.timeout * 1e3,
|
|
442
|
+
insecure: g.insecure,
|
|
460
443
|
onPrompt: ({ userCode, verificationUri, verificationUriComplete }) => {
|
|
461
444
|
const target = verificationUriComplete ?? verificationUri;
|
|
462
445
|
process.stderr.write(
|
|
@@ -475,9 +458,9 @@ User code: ${userCode}
|
|
|
475
458
|
}
|
|
476
459
|
} catch (e) {
|
|
477
460
|
if (e instanceof Error && /Device auth failed \(404\)/.test(e.message)) {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
461
|
+
throw new InputError(
|
|
462
|
+
`No auth endpoint on ${url} \u2014 the platform has no bkn-safe auth stack. Deploy bkn-safe, or log in elsewhere and pass the token with \`--token\`.`
|
|
463
|
+
);
|
|
481
464
|
}
|
|
482
465
|
throw e;
|
|
483
466
|
}
|
|
@@ -493,29 +476,29 @@ User code: ${userCode}
|
|
|
493
476
|
attachToken(url, tokens.accessToken, {
|
|
494
477
|
refreshToken: tokens.refreshToken,
|
|
495
478
|
idToken: tokens.idToken,
|
|
496
|
-
|
|
497
|
-
|
|
479
|
+
username: account,
|
|
480
|
+
insecure: g.insecure
|
|
498
481
|
})
|
|
499
482
|
);
|
|
500
483
|
});
|
|
501
|
-
cmd.command("status").description("Show base URL and whether a token is configured").action(
|
|
484
|
+
cmd.command("status").description("Show base URL and whether a token is configured").action(
|
|
485
|
+
(_opts, cmd2) => printJson(status({ user: cmd2.optsWithGlobals().user }), outputOptions(cmd2))
|
|
486
|
+
);
|
|
502
487
|
cmd.command("token").description("Print the current access token, refreshing it if expired (keep secret)").option("--no-refresh", "print the stored token as-is, without refreshing").action(async (opts, cmd2) => {
|
|
503
488
|
const g = cmd2.optsWithGlobals();
|
|
504
|
-
|
|
505
|
-
const token = opts.refresh === false ? currentToken() : await currentTokenFresh();
|
|
489
|
+
const token = opts.refresh === false ? currentToken({ user: g.user }) : await currentTokenFresh({ insecure: g.insecure, user: g.user });
|
|
506
490
|
process.stdout.write(`${token}
|
|
507
491
|
`);
|
|
508
492
|
});
|
|
509
493
|
cmd.command("whoami [url]").description("Show current user identity (from the token)").option("--no-lookup", "skip the backend identity fallback (eacp/user/get)").action(async (_url, opts, cmd2) => {
|
|
510
494
|
const g = cmd2.optsWithGlobals();
|
|
511
|
-
|
|
512
|
-
const me = whoami();
|
|
495
|
+
const me = whoami({ user: g.user });
|
|
513
496
|
if (opts.lookup !== false && me.baseUrl && me.sub) {
|
|
514
497
|
try {
|
|
515
498
|
const u = await getUserSafe(
|
|
516
499
|
{
|
|
517
500
|
baseUrl: me.baseUrl,
|
|
518
|
-
token: currentToken(),
|
|
501
|
+
token: currentToken({ user: g.user }),
|
|
519
502
|
businessDomain: DEFAULT_BUSINESS_DOMAIN,
|
|
520
503
|
insecure: Boolean(g.insecure)
|
|
521
504
|
},
|
|
@@ -580,9 +563,8 @@ User code: ${userCode}
|
|
|
580
563
|
cmd.command("export").description("Export the active session's tokens (for a headless host)").action((_opts, cmd2) => {
|
|
581
564
|
printJson(exportCreds(), outputOptions(cmd2));
|
|
582
565
|
});
|
|
583
|
-
cmd.command("change-password [url]").description("Change your account password (bkn-safe self-service; no browser)").option("-a, --account <name>", "account / login name (the login column, e.g. admin)").option("--old-password <pwd>", "current password").option("--new-password <pwd>", "new password").
|
|
566
|
+
cmd.command("change-password [url]").description("Change your account password (bkn-safe self-service; no browser)").option("-a, --account <name>", "account / login name (the login column, e.g. admin)").option("--old-password <pwd>", "current password").option("--new-password <pwd>", "new password").action(async (url, opts, cmd2) => {
|
|
584
567
|
const g = cmd2.optsWithGlobals();
|
|
585
|
-
if (g.insecure) process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
586
568
|
const ctx = resolveContext({
|
|
587
569
|
baseUrl: url ?? g.baseUrl,
|
|
588
570
|
token: g.token,
|
|
@@ -623,10 +605,14 @@ function authCommand() {
|
|
|
623
605
|
// src/commands/admin.ts
|
|
624
606
|
var int = (v) => Number.parseInt(v, 10);
|
|
625
607
|
var DEFAULT_RESET_PASSWORD = "openbkn";
|
|
608
|
+
async function importLicenseFile(cmd, file, receipt) {
|
|
609
|
+
const text = readFileSync2(file, "utf8");
|
|
610
|
+
const res = await clientFrom(cmd).admin.licenseImport(text, { receipt });
|
|
611
|
+
printJson(res, outputOptions(cmd));
|
|
612
|
+
if ("stored" in res && res.stored) process.exitCode = 1;
|
|
613
|
+
}
|
|
626
614
|
function adminCommand() {
|
|
627
|
-
const admin = new Command2("admin").description(
|
|
628
|
-
"Operator CLI (kweaver-admin): org, user, role, models, audit"
|
|
629
|
-
);
|
|
615
|
+
const admin = new Command2("admin").description("Operator CLI: org, user, role, models, audit");
|
|
630
616
|
registerAuthLeaves(admin.command("auth").description("Operator authentication"));
|
|
631
617
|
const org = admin.command("org").description("Departments and org structure");
|
|
632
618
|
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) => {
|
|
@@ -755,15 +741,19 @@ function adminCommand() {
|
|
|
755
741
|
user.command("delete <id>").description("Delete a user").action(async (id, _opts, cmd) => {
|
|
756
742
|
printJson(await clientFrom(cmd).admin.userDelete(id), outputOptions(cmd));
|
|
757
743
|
});
|
|
758
|
-
user.command("reset-password [id]").description("Reset a user's password (defaults to the platform initial password)").option("--id <userId>", "explicit user UUID (alt to the positional id)").option("--user <account>", "resolve the user by account / login name").option("--password <s>", "the new password (default: platform initial 'openbkn')").option("--new-password <s>", "the new password (alias of --password)").option("-y, --yes", "skip confirmation").action(async (id, opts, cmd) => {
|
|
744
|
+
user.command("reset-password [id]").description("Reset a user's password (defaults to the platform initial password)").option("--id <userId>", "explicit user UUID (alt to the positional id)").option("--user <account>", "resolve the user by account / login name").option("--password <s>", "the new password (default: platform initial 'openbkn')").option("--new-password <s>", "the new password (alias of --password)").option("--prompt-password", "type the new password interactively (input hidden)").option("-y, --yes", "skip confirmation").action(async (id, opts, cmd) => {
|
|
759
745
|
const userId = id ?? opts.id ?? opts.user;
|
|
760
746
|
if (!userId) throw new Error("Provide a user id (positional or --id).");
|
|
761
|
-
|
|
747
|
+
let explicit = opts.password ?? opts.newPassword;
|
|
748
|
+
if (!explicit && opts.promptPassword) {
|
|
749
|
+
explicit = await promptLine("New password: ", true);
|
|
750
|
+
if (!explicit) throw new InputError("No password entered.");
|
|
751
|
+
}
|
|
752
|
+
const pwd = explicit ?? DEFAULT_RESET_PASSWORD;
|
|
762
753
|
const r = await clientFrom(cmd).admin.userResetPassword(userId, pwd);
|
|
763
754
|
const out = outputOptions(cmd);
|
|
764
755
|
if (out.json || out.compact) printJson(r, out);
|
|
765
|
-
else if (
|
|
766
|
-
process.stdout.write(`Password reset for ${userId}.
|
|
756
|
+
else if (explicit) process.stdout.write(`Password reset for ${userId}.
|
|
767
757
|
`);
|
|
768
758
|
else
|
|
769
759
|
process.stdout.write(
|
|
@@ -906,6 +896,27 @@ function adminCommand() {
|
|
|
906
896
|
);
|
|
907
897
|
});
|
|
908
898
|
}
|
|
899
|
+
const license = admin.command("license").description("Cluster license management");
|
|
900
|
+
license.command("show").description("Current license detail (state/edition/expiry/features)").action(async (_opts, cmd) => {
|
|
901
|
+
printJson(await clientFrom(cmd).admin.licenseGet(), outputOptions(cmd));
|
|
902
|
+
});
|
|
903
|
+
license.command("import <file>").description("Import a .lic license file (online deployments auto-activate)").action(async (file, _opts, cmd) => {
|
|
904
|
+
await importLicenseFile(cmd, file, false);
|
|
905
|
+
});
|
|
906
|
+
license.command("receipt <file>").description("Import an offline activation receipt (.lic from the license portal)").action(async (file, _opts, cmd) => {
|
|
907
|
+
await importLicenseFile(cmd, file, true);
|
|
908
|
+
});
|
|
909
|
+
license.command("activate").description("Report the installed license to the issuer (online deployments)").action(async (_opts, cmd) => {
|
|
910
|
+
printJson(await clientFrom(cmd).admin.licenseActivate(), outputOptions(cmd));
|
|
911
|
+
});
|
|
912
|
+
license.command("remove").description("Remove the installed license (back to unactivated)").action(async (_opts, cmd) => {
|
|
913
|
+
printJson(await clientFrom(cmd).admin.licenseRemove(), outputOptions(cmd));
|
|
914
|
+
});
|
|
915
|
+
license.command("fingerprint").description(
|
|
916
|
+
"This cluster's machine code (paste into the license portal for offline activation)"
|
|
917
|
+
).action(async (_opts, cmd) => {
|
|
918
|
+
printJson(await clientFrom(cmd).admin.licenseFingerprint(), outputOptions(cmd));
|
|
919
|
+
});
|
|
909
920
|
admin.command("audit").description("Audit log queries").command("list").description("List login audit events").option("--user <name>", "filter by user").option("--start <time>", "start time").option("--end <time>", "end time").option("--page <n>", "page", int, 1).option("--size <n>", "page size", int, 30).action(async (opts, cmd) => {
|
|
910
921
|
printJson(
|
|
911
922
|
await clientFrom(cmd).admin.auditList({
|
|
@@ -966,7 +977,14 @@ function adminCommand() {
|
|
|
966
977
|
import { Command as Command3 } from "commander";
|
|
967
978
|
var int2 = (v) => Number.parseInt(v, 10);
|
|
968
979
|
function agentCommand() {
|
|
969
|
-
const cmd = new Command3("agent").description(
|
|
980
|
+
const cmd = new Command3("agent").description(
|
|
981
|
+
"[DEPRECATED] Decision Agent \u2014 CRUD, chat, sessions, publish (being phased out)"
|
|
982
|
+
);
|
|
983
|
+
cmd.hook("preAction", () => {
|
|
984
|
+
process.stderr.write(
|
|
985
|
+
"\u26A0\uFE0F `openbkn agent` is deprecated and may be removed in a future release.\n"
|
|
986
|
+
);
|
|
987
|
+
});
|
|
970
988
|
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) => {
|
|
971
989
|
const data = await clientFrom(cmd2).agents.list({
|
|
972
990
|
name: opts.name,
|
|
@@ -1068,11 +1086,78 @@ function agentCommand() {
|
|
|
1068
1086
|
return group(cmd, "DECISION AGENT");
|
|
1069
1087
|
}
|
|
1070
1088
|
|
|
1071
|
-
// src/commands/
|
|
1089
|
+
// src/commands/appkey.ts
|
|
1072
1090
|
import { Command as Command4 } from "commander";
|
|
1091
|
+
var int3 = (v) => Number.parseInt(v, 10);
|
|
1092
|
+
var DAY_MS = 864e5;
|
|
1093
|
+
function printNewKey(created, out) {
|
|
1094
|
+
if (out.json || out.compact) {
|
|
1095
|
+
printJson(created, out);
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
process.stderr.write(
|
|
1099
|
+
"\u26A0\uFE0F Copy this key now \u2014 the plaintext is shown only once and cannot be retrieved again.\n\n"
|
|
1100
|
+
);
|
|
1101
|
+
const fields = [
|
|
1102
|
+
["key", created.key],
|
|
1103
|
+
["name", created.name],
|
|
1104
|
+
["id", `${created.id} (use this to revoke/regenerate)`],
|
|
1105
|
+
["key_id", created.key_id],
|
|
1106
|
+
["expires_at", created.expires_at ?? "never"]
|
|
1107
|
+
];
|
|
1108
|
+
const w = Math.max(...fields.map(([k]) => k.length));
|
|
1109
|
+
for (const [k, v] of fields) process.stdout.write(` ${k.padEnd(w)} ${v}
|
|
1110
|
+
`);
|
|
1111
|
+
}
|
|
1112
|
+
function appkeyCommand() {
|
|
1113
|
+
const appkey = new Command4("appkey").description(
|
|
1114
|
+
"AppKeys \u2014 user-issued long-lived credentials (bak_) for the Context Loader"
|
|
1115
|
+
);
|
|
1116
|
+
appkey.command("list").description("List your own AppKeys (no secrets)").action(async (_opts, cmd) => {
|
|
1117
|
+
printJson(await clientFrom(cmd).appKeys.list(), outputOptions(cmd));
|
|
1118
|
+
});
|
|
1119
|
+
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)", int3).option("--never-expire", "never expire (wins over --expires-at/--expire-days)").action(async (opts, cmd) => {
|
|
1120
|
+
let expiresAt = opts.expiresAt;
|
|
1121
|
+
if (opts.expireDays !== void 0) {
|
|
1122
|
+
if (!Number.isFinite(opts.expireDays) || opts.expireDays <= 0) {
|
|
1123
|
+
throw new InputError("--expire-days must be a positive integer.");
|
|
1124
|
+
}
|
|
1125
|
+
if (expiresAt) {
|
|
1126
|
+
throw new InputError("Use either --expires-at or --expire-days, not both.");
|
|
1127
|
+
}
|
|
1128
|
+
expiresAt = new Date(Date.now() + opts.expireDays * DAY_MS).toISOString();
|
|
1129
|
+
}
|
|
1130
|
+
const created = await clientFrom(cmd).appKeys.create({
|
|
1131
|
+
name: opts.name,
|
|
1132
|
+
expiresAt,
|
|
1133
|
+
neverExpire: Boolean(opts.neverExpire)
|
|
1134
|
+
});
|
|
1135
|
+
printNewKey(created, outputOptions(cmd));
|
|
1136
|
+
});
|
|
1137
|
+
appkey.command("regenerate <id>").alias("rotate").description("Rotate a key in place \u2014 mints a new plaintext; the old bak_ dies immediately").action(async (id, _opts, cmd) => {
|
|
1138
|
+
const created = await clientFrom(cmd).appKeys.regenerate(id);
|
|
1139
|
+
printNewKey(created, outputOptions(cmd));
|
|
1140
|
+
});
|
|
1141
|
+
appkey.command("revoke <id>").alias("delete").alias("rm").description("Revoke one of your AppKeys (immediate; use the `id`, not `key_id`)").action(async (id, _opts, cmd) => {
|
|
1142
|
+
await clientFrom(cmd).appKeys.revoke(id);
|
|
1143
|
+
printJson({ revoked: id }, outputOptions(cmd));
|
|
1144
|
+
});
|
|
1145
|
+
const admin = appkey.command("admin").description("Admin governance over all AppKeys");
|
|
1146
|
+
admin.command("list").description("List all AppKeys, or one owner's (adds owner_user_id)").option("--owner-id <id>", "filter to a single owner").action(async (opts, cmd) => {
|
|
1147
|
+
printJson(await clientFrom(cmd).appKeys.adminList(opts.ownerId), outputOptions(cmd));
|
|
1148
|
+
});
|
|
1149
|
+
admin.command("revoke <id>").alias("delete").alias("rm").description("Revoke any AppKey by id").action(async (id, _opts, cmd) => {
|
|
1150
|
+
await clientFrom(cmd).appKeys.adminRevoke(id);
|
|
1151
|
+
printJson({ revoked: id }, outputOptions(cmd));
|
|
1152
|
+
});
|
|
1153
|
+
return group(appkey, "AUTHENTICATION & CONFIG");
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
// src/commands/bkn.ts
|
|
1157
|
+
import { Command as Command5 } from "commander";
|
|
1073
1158
|
|
|
1074
1159
|
// src/utils/bkn-validate.ts
|
|
1075
|
-
import { existsSync, readFileSync as
|
|
1160
|
+
import { existsSync, readFileSync as readFileSync3, readdirSync, statSync } from "fs";
|
|
1076
1161
|
import { join, resolve } from "path";
|
|
1077
1162
|
var BKN_OBJECT_NAME_MAX_LENGTH = 40;
|
|
1078
1163
|
function parseFrontmatter(text) {
|
|
@@ -1125,7 +1210,7 @@ function validateBknDirectory(dirPath) {
|
|
|
1125
1210
|
if (!existsSync(networkPath)) {
|
|
1126
1211
|
errors.push("Missing network.bkn at the BKN root.");
|
|
1127
1212
|
} else {
|
|
1128
|
-
const fm = parseFrontmatter(
|
|
1213
|
+
const fm = parseFrontmatter(readFileSync3(networkPath, "utf8"));
|
|
1129
1214
|
if (!fm) errors.push("network.bkn has no frontmatter block.");
|
|
1130
1215
|
else {
|
|
1131
1216
|
if (fm.type !== "knowledge_network")
|
|
@@ -1137,7 +1222,7 @@ function validateBknDirectory(dirPath) {
|
|
|
1137
1222
|
const otIds = /* @__PURE__ */ new Set();
|
|
1138
1223
|
const otFiles = bknFiles(join(dir, "object_types"));
|
|
1139
1224
|
for (const file of otFiles) {
|
|
1140
|
-
const fm = parseFrontmatter(
|
|
1225
|
+
const fm = parseFrontmatter(readFileSync3(file, "utf8"));
|
|
1141
1226
|
const rel = file.slice(dir.length + 1);
|
|
1142
1227
|
if (!fm || fm.type !== "object_type") {
|
|
1143
1228
|
errors.push(`${rel}: not a valid object_type (missing/wrong frontmatter type).`);
|
|
@@ -1157,7 +1242,7 @@ function validateBknDirectory(dirPath) {
|
|
|
1157
1242
|
}
|
|
1158
1243
|
const rtFiles = bknFiles(join(dir, "relation_types"));
|
|
1159
1244
|
for (const file of rtFiles) {
|
|
1160
|
-
const text =
|
|
1245
|
+
const text = readFileSync3(file, "utf8");
|
|
1161
1246
|
const fm = parseFrontmatter(text);
|
|
1162
1247
|
const rel = file.slice(dir.length + 1);
|
|
1163
1248
|
if (!fm || fm.type !== "relation_type") {
|
|
@@ -1187,10 +1272,10 @@ function validateBknDirectory(dirPath) {
|
|
|
1187
1272
|
}
|
|
1188
1273
|
|
|
1189
1274
|
// src/commands/bkn.ts
|
|
1190
|
-
var
|
|
1275
|
+
var int4 = (v) => Number.parseInt(v, 10);
|
|
1191
1276
|
function bknCommand() {
|
|
1192
|
-
const bkn = new
|
|
1193
|
-
bkn.command("list").description("List knowledge networks").option("--limit <n>", "page size",
|
|
1277
|
+
const bkn = new Command5("bkn").description("Knowledge networks \u2014 list, query, schema, instances");
|
|
1278
|
+
bkn.command("list").description("List knowledge networks").option("--limit <n>", "page size", int4, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int4, 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) => {
|
|
1194
1279
|
const o = cmd.optsWithGlobals();
|
|
1195
1280
|
const data = await clientFrom(cmd).kn.list({
|
|
1196
1281
|
limit: o.limit,
|
|
@@ -1209,7 +1294,7 @@ function bknCommand() {
|
|
|
1209
1294
|
});
|
|
1210
1295
|
printJson(data, outputOptions(cmd));
|
|
1211
1296
|
});
|
|
1212
|
-
bkn.command("search <kn-id> <query>").description("Semantic search within a knowledge network").option("--max-concepts <n>", "max concepts to return",
|
|
1297
|
+
bkn.command("search <kn-id> <query>").description("Semantic search within a knowledge network").option("--max-concepts <n>", "max concepts to return", int4, 10).option("--mode <mode>", "retrieval mode", "keyword_vector_retrieval").action(async (knId, query, opts, cmd) => {
|
|
1213
1298
|
const data = await clientFrom(cmd).kn.search(knId, query, {
|
|
1214
1299
|
maxConcepts: opts.maxConcepts,
|
|
1215
1300
|
mode: opts.mode
|
|
@@ -1282,9 +1367,6 @@ function bknCommand() {
|
|
|
1282
1367
|
outputOptions(cmd)
|
|
1283
1368
|
);
|
|
1284
1369
|
});
|
|
1285
|
-
objectType?.command("properties <kn-id> <ot-id>").description("Get an object type's calculated properties").action(async (knId, otId, _opts, cmd) => {
|
|
1286
|
-
printJson(await clientFrom(cmd).kn.objectTypeProperties(knId, otId), outputOptions(cmd));
|
|
1287
|
-
});
|
|
1288
1370
|
bkn.command("create <name>").description("Create an (empty) knowledge network").option("--branch <b>", "branch", "main").action(async (name, opts, cmd) => {
|
|
1289
1371
|
printJson(await clientFrom(cmd).kn.create({ name, branch: opts.branch }), outputOptions(cmd));
|
|
1290
1372
|
});
|
|
@@ -1298,7 +1380,7 @@ function bknCommand() {
|
|
|
1298
1380
|
printJson(await clientFrom(cmd).kn.subgraph(knId, readBody(opts)), outputOptions(cmd));
|
|
1299
1381
|
});
|
|
1300
1382
|
const actionLog = bkn.command("action-log").description("Action logs \u2014 list/get/cancel");
|
|
1301
|
-
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",
|
|
1383
|
+
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", int4, DEFAULT_LIST_LIMIT).action(async (knId, opts, cmd) => {
|
|
1302
1384
|
printJson(
|
|
1303
1385
|
await clientFrom(cmd).kn.actionLogs(knId, {
|
|
1304
1386
|
status: opts.status,
|
|
@@ -1413,19 +1495,6 @@ function bknCommand() {
|
|
|
1413
1495
|
sched.command("delete <kn-id> <schedule-ids>").description("Delete action schedule(s) (comma-joined ids)").action(async (knId, ids, _o, cmd) => {
|
|
1414
1496
|
printJson(await clientFrom(cmd).kn.actionScheduleDelete(knId, ids), outputOptions(cmd));
|
|
1415
1497
|
});
|
|
1416
|
-
const job = bkn.command("job").description("Build jobs \u2014 list/get/tasks");
|
|
1417
|
-
job.command("list <kn-id>").description("List jobs").action(async (knId, _o, cmd) => {
|
|
1418
|
-
printJson(await clientFrom(cmd).kn.jobs(knId), outputOptions(cmd));
|
|
1419
|
-
});
|
|
1420
|
-
job.command("get <kn-id> <job-id>").description("Get a job").action(async (knId, jobId, _o, cmd) => {
|
|
1421
|
-
printJson(await clientFrom(cmd).kn.job(knId, jobId), outputOptions(cmd));
|
|
1422
|
-
});
|
|
1423
|
-
job.command("tasks <kn-id> <job-id>").description("List a job's tasks").action(async (knId, jobId, _o, cmd) => {
|
|
1424
|
-
printJson(await clientFrom(cmd).kn.jobTasks(knId, jobId), outputOptions(cmd));
|
|
1425
|
-
});
|
|
1426
|
-
job.command("delete <kn-id> <job-ids>").description("Delete job(s) (comma-joined ids)").action(async (knId, ids, _o, cmd) => {
|
|
1427
|
-
printJson(await clientFrom(cmd).kn.jobDelete(knId, ids), outputOptions(cmd));
|
|
1428
|
-
});
|
|
1429
1498
|
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(
|
|
1430
1499
|
"--embedding-model <id>",
|
|
1431
1500
|
"embedding model id for declared vector indexes (with --build)"
|
|
@@ -1478,7 +1547,7 @@ function bknCommand() {
|
|
|
1478
1547
|
printJson(result, outputOptions(cmd));
|
|
1479
1548
|
if (!result.valid) process.exitCode = 1;
|
|
1480
1549
|
});
|
|
1481
|
-
bkn.command("create-from-csv <catalog-id>").description("Import CSV files into a Vega catalog, then build a KN from them").requiredOption("--files <glob>", "CSV paths (comma-separated or glob)").requiredOption("--name <name>", "knowledge network name").option("--table-prefix <s>", "prefix for derived table names", "").option("--batch-size <n>", "rows per insert batch",
|
|
1550
|
+
bkn.command("create-from-csv <catalog-id>").description("Import CSV files into a Vega catalog, then build a KN from them").requiredOption("--files <glob>", "CSV paths (comma-separated or glob)").requiredOption("--name <name>", "knowledge network name").option("--table-prefix <s>", "prefix for derived table names", "").option("--batch-size <n>", "rows per insert batch", int4, 500).option("--tables <list>", "subset of imported tables to include in the KN").option("--pk-map <map>", "explicit primary keys: '<table>:<col>[,...]'").option("--build", "submit a Vega build task per resource after creation").option(
|
|
1482
1551
|
"--embedding-fields <map>",
|
|
1483
1552
|
"columns to vectorize per table (with --build): '<table>:<col>[+<col>...][,...]'"
|
|
1484
1553
|
).option("--embedding-model <id>", "embedding model id for the vector index (with --build)").option("--no-rollback", "keep a partially-created KN on failure").action(async (catalogId, opts, cmd) => {
|
|
@@ -1504,25 +1573,27 @@ function bknCommand() {
|
|
|
1504
1573
|
}
|
|
1505
1574
|
|
|
1506
1575
|
// src/commands/call.ts
|
|
1507
|
-
import { Command as
|
|
1576
|
+
import { Command as Command6 } from "commander";
|
|
1508
1577
|
function collect(value, prev) {
|
|
1509
1578
|
prev.push(value);
|
|
1510
1579
|
return prev;
|
|
1511
1580
|
}
|
|
1512
1581
|
function callCommand() {
|
|
1513
|
-
const cmd = new
|
|
1582
|
+
const cmd = new Command6("call").alias("curl").description("Call an API with curl-style flags and auto-injected auth headers").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(
|
|
1514
1583
|
"-F, --form <field>",
|
|
1515
1584
|
"multipart field key=value or key=@file (repeatable)",
|
|
1516
1585
|
collect,
|
|
1517
1586
|
[]
|
|
1518
1587
|
).option("-v, --verbose", "print request line to stderr").action(async (url, opts, cmd2) => {
|
|
1519
1588
|
const g = cmd2.optsWithGlobals();
|
|
1589
|
+
const trace = traceOptionsFrom(g);
|
|
1520
1590
|
const ctx = resolveContext({
|
|
1521
1591
|
baseUrl: g.baseUrl,
|
|
1522
1592
|
token: g.token,
|
|
1523
1593
|
user: g.user,
|
|
1524
1594
|
businessDomain: g.bizDomain,
|
|
1525
|
-
insecure: g.insecure
|
|
1595
|
+
insecure: g.insecure,
|
|
1596
|
+
...trace ? { trace } : {}
|
|
1526
1597
|
});
|
|
1527
1598
|
const res = await rawCall(ctx, url, {
|
|
1528
1599
|
method: opts.request,
|
|
@@ -1545,14 +1616,14 @@ function callCommand() {
|
|
|
1545
1616
|
}
|
|
1546
1617
|
|
|
1547
1618
|
// src/commands/config.ts
|
|
1548
|
-
import { Command as
|
|
1619
|
+
import { Command as Command7 } from "commander";
|
|
1549
1620
|
function requireActive() {
|
|
1550
1621
|
const baseUrl = activePlatform();
|
|
1551
1622
|
if (!baseUrl) throw new InputError("No active platform. Run `openbkn auth login <url>` first.");
|
|
1552
1623
|
return baseUrl;
|
|
1553
1624
|
}
|
|
1554
1625
|
function configCommand() {
|
|
1555
|
-
const config = new
|
|
1626
|
+
const config = new Command7("config").description("Per-platform CLI configuration");
|
|
1556
1627
|
config.command("show").description("Show the active platform and business domain").action((_opts, cmd) => {
|
|
1557
1628
|
const baseUrl = activePlatform();
|
|
1558
1629
|
printJson(
|
|
@@ -1585,13 +1656,56 @@ function configCommand() {
|
|
|
1585
1656
|
}
|
|
1586
1657
|
|
|
1587
1658
|
// src/commands/context.ts
|
|
1588
|
-
import { Command as
|
|
1589
|
-
var
|
|
1659
|
+
import { Command as Command8 } from "commander";
|
|
1660
|
+
var int5 = (v) => Number.parseInt(v, 10);
|
|
1661
|
+
var collectArg = (v, prev) => {
|
|
1662
|
+
prev.push(v);
|
|
1663
|
+
return prev;
|
|
1664
|
+
};
|
|
1665
|
+
function buildArgs(opts) {
|
|
1666
|
+
let out = {};
|
|
1667
|
+
if (opts.args) {
|
|
1668
|
+
try {
|
|
1669
|
+
out = JSON.parse(opts.args);
|
|
1670
|
+
} catch {
|
|
1671
|
+
throw new InputError("--args must be valid JSON");
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
for (const pair of opts.arg ?? []) {
|
|
1675
|
+
const idx = pair.indexOf("=");
|
|
1676
|
+
if (idx <= 0) throw new InputError(`--arg must be key=value (got: ${pair})`);
|
|
1677
|
+
const key = pair.slice(0, idx);
|
|
1678
|
+
const raw = pair.slice(idx + 1);
|
|
1679
|
+
try {
|
|
1680
|
+
out[key] = JSON.parse(raw);
|
|
1681
|
+
} catch {
|
|
1682
|
+
out[key] = raw;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
return out;
|
|
1686
|
+
}
|
|
1687
|
+
function printToolList(res, out) {
|
|
1688
|
+
if (out.json || out.compact) {
|
|
1689
|
+
printJson(res, out);
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
const r = res ?? {};
|
|
1693
|
+
const arr = [res, r.tools, r.result?.tools, r.data].find(Array.isArray);
|
|
1694
|
+
if (!arr) {
|
|
1695
|
+
printJson(res, out);
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
const rows = arr.map((t) => ({
|
|
1699
|
+
name: t.name ?? t.tool_name ?? t.key ?? "",
|
|
1700
|
+
description: typeof t.description === "string" ? t.description : ""
|
|
1701
|
+
}));
|
|
1702
|
+
printJson(rows, out);
|
|
1703
|
+
}
|
|
1590
1704
|
function contextCommand() {
|
|
1591
|
-
const cmd = new
|
|
1705
|
+
const cmd = new Command8("context").description(
|
|
1592
1706
|
"Context loader (MCP) \u2014 schema discovery, instance query, skill recall"
|
|
1593
1707
|
);
|
|
1594
|
-
cmd.command("search-schema <kn-id> <query>").description("Search object/relation/action/metric schemas").option("--scope <list>", "comma-separated scopes (object,relation,action,metric)").option("--max <n>", "max concepts",
|
|
1708
|
+
cmd.command("search-schema <kn-id> <query>").description("Search object/relation/action/metric schemas").option("--scope <list>", "comma-separated scopes (object,relation,action,metric)").option("--max <n>", "max concepts", int5).action(async (knId, query, opts, cmd2) => {
|
|
1595
1709
|
const data = await clientFrom(cmd2).context.searchSchema(knId, query, {
|
|
1596
1710
|
searchScope: opts.scope ? String(opts.scope).split(",") : void 0,
|
|
1597
1711
|
maxConcepts: opts.max
|
|
@@ -1607,23 +1721,51 @@ function contextCommand() {
|
|
|
1607
1721
|
}
|
|
1608
1722
|
printJson(await clientFrom(cmd2).context.queryObjectInstance(knId, args), outputOptions(cmd2));
|
|
1609
1723
|
});
|
|
1610
|
-
cmd.command("find-skills <kn-id> <object-type-id>").description("Recall skills for an object type").option("--top-k <n>", "max skills (1-20)",
|
|
1724
|
+
cmd.command("find-skills <kn-id> <object-type-id>").description("Recall skills for an object type").option("--top-k <n>", "max skills (1-20)", int5).action(async (knId, otId, opts, cmd2) => {
|
|
1611
1725
|
printJson(
|
|
1612
1726
|
await clientFrom(cmd2).context.findSkills(knId, otId, opts.topK),
|
|
1613
1727
|
outputOptions(cmd2)
|
|
1614
1728
|
);
|
|
1615
1729
|
});
|
|
1616
|
-
cmd.command("
|
|
1617
|
-
|
|
1730
|
+
cmd.command("kn-detail <kn-id>").description("Get a KN's schema at a detail level (progressive: summary skeleton \u2192 drill down)").option("--detail-level <level>", "summary (default) | full", "summary").action(async (knId, opts, cmd2) => {
|
|
1731
|
+
const level = opts.detailLevel === "full" ? "full" : "summary";
|
|
1732
|
+
printJson(await clientFrom(cmd2).context.knDetail(knId, level), outputOptions(cmd2));
|
|
1618
1733
|
});
|
|
1619
|
-
cmd.command("
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1734
|
+
cmd.command("object-types <kn-id> <ids...>").description("Full definitions for the given object-type ids (unmatched \u2192 `missing`)").action(async (knId, ids, _opts, cmd2) => {
|
|
1735
|
+
printJson(await clientFrom(cmd2).context.objectTypes(knId, ids), outputOptions(cmd2));
|
|
1736
|
+
});
|
|
1737
|
+
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) => {
|
|
1738
|
+
printJson(await clientFrom(cmd2).context.relationTypes(knId, ids), outputOptions(cmd2));
|
|
1739
|
+
});
|
|
1740
|
+
cmd.command("info").description("List the deploy's MCP tool catalog (global \u2014 no KN needed)").action(async (_opts, cmd2) => {
|
|
1741
|
+
printToolList(await clientFrom(cmd2).context.info(), outputOptions(cmd2));
|
|
1742
|
+
});
|
|
1743
|
+
cmd.command("tools <kn-id>").description("List MCP tools advertised for a KN session").action(async (knId, _opts, cmd2) => {
|
|
1744
|
+
printToolList(await clientFrom(cmd2).context.tools(knId), outputOptions(cmd2));
|
|
1745
|
+
});
|
|
1746
|
+
cmd.command("tool-call <kn-id> <name>").description("Call any MCP tool by name \u2014 current or future (use `tools` to discover)").option("--args <json>", "tool arguments as JSON").option(
|
|
1747
|
+
"--arg <key=value>",
|
|
1748
|
+
"one argument (repeatable; value parsed as JSON, else string)",
|
|
1749
|
+
collectArg,
|
|
1750
|
+
[]
|
|
1751
|
+
).action(async (knId, name, opts, cmd2) => {
|
|
1752
|
+
printJson(
|
|
1753
|
+
await clientFrom(cmd2).context.toolCall(knId, name, buildArgs(opts)),
|
|
1754
|
+
outputOptions(cmd2)
|
|
1755
|
+
);
|
|
1756
|
+
});
|
|
1757
|
+
cmd.command("call-method <kn-id> <method>").description(
|
|
1758
|
+
"Call any MCP method by name (e.g. tools/list, resources/read) \u2014 current or future"
|
|
1759
|
+
).option("--args <json>", "method params as JSON").option(
|
|
1760
|
+
"--arg <key=value>",
|
|
1761
|
+
"one param (repeatable; value parsed as JSON, else string)",
|
|
1762
|
+
collectArg,
|
|
1763
|
+
[]
|
|
1764
|
+
).action(async (knId, method, opts, cmd2) => {
|
|
1765
|
+
printJson(
|
|
1766
|
+
await clientFrom(cmd2).context.callMethod(knId, method, buildArgs(opts)),
|
|
1767
|
+
outputOptions(cmd2)
|
|
1768
|
+
);
|
|
1627
1769
|
});
|
|
1628
1770
|
cmd.command("resources <kn-id>").description("List MCP resources").action(async (knId, _opts, cmd2) => {
|
|
1629
1771
|
printJson(await clientFrom(cmd2).context.resources(knId), outputOptions(cmd2));
|
|
@@ -1655,19 +1797,19 @@ function contextCommand() {
|
|
|
1655
1797
|
throw new InputError("--args must be valid JSON");
|
|
1656
1798
|
}
|
|
1657
1799
|
};
|
|
1658
|
-
cmd.command("query-instance-subgraph <kn-id>").description("
|
|
1800
|
+
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) => {
|
|
1659
1801
|
printJson(
|
|
1660
1802
|
await clientFrom(cmd2).context.queryInstanceSubgraph(knId, jsonArgs(opts.args)),
|
|
1661
1803
|
outputOptions(cmd2)
|
|
1662
1804
|
);
|
|
1663
1805
|
});
|
|
1664
|
-
cmd.command("get-logic-properties <kn-id>").description("
|
|
1806
|
+
cmd.command("get-logic-properties <kn-id>").description("Compute logic-property values for instances").requiredOption("--args <json>", "tool arguments as JSON").action(async (knId, opts, cmd2) => {
|
|
1665
1807
|
printJson(
|
|
1666
1808
|
await clientFrom(cmd2).context.logicProperties(knId, jsonArgs(opts.args)),
|
|
1667
1809
|
outputOptions(cmd2)
|
|
1668
1810
|
);
|
|
1669
1811
|
});
|
|
1670
|
-
cmd.command("get-action-info <kn-id>").description("
|
|
1812
|
+
cmd.command("get-action-info <kn-id>").description("Fetch action info / dynamic tools for an instance").requiredOption("--args <json>", "tool arguments as JSON").action(async (knId, opts, cmd2) => {
|
|
1671
1813
|
printJson(
|
|
1672
1814
|
await clientFrom(cmd2).context.actionInfo(knId, jsonArgs(opts.args)),
|
|
1673
1815
|
outputOptions(cmd2)
|
|
@@ -1677,20 +1819,24 @@ function contextCommand() {
|
|
|
1677
1819
|
}
|
|
1678
1820
|
|
|
1679
1821
|
// src/commands/dataflow.ts
|
|
1680
|
-
import { Command as
|
|
1681
|
-
var
|
|
1822
|
+
import { Command as Command9 } from "commander";
|
|
1823
|
+
var int6 = (v) => Number.parseInt(v, 10);
|
|
1682
1824
|
function dataflowCommand() {
|
|
1683
|
-
const cmd = new
|
|
1825
|
+
const cmd = new Command9("dataflow").description("Dataflow document workflows \u2014 list, runs, logs");
|
|
1684
1826
|
cmd.command("list").description("List all dataflows").action(async (_opts, cmd2) => {
|
|
1685
1827
|
printJson(await clientFrom(cmd2).dataflows.list(), outputOptions(cmd2));
|
|
1686
1828
|
});
|
|
1687
|
-
cmd.command("runs <dagId>").description("List run records for one dataflow").option("--since <date>", "filter runs since a date").action(async (dagId, opts, cmd2) => {
|
|
1829
|
+
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) => {
|
|
1688
1830
|
printJson(
|
|
1689
|
-
await clientFrom(cmd2).dataflows.runs(dagId, {
|
|
1831
|
+
await clientFrom(cmd2).dataflows.runs(dagId, {
|
|
1832
|
+
since: opts.since,
|
|
1833
|
+
page: opts.page,
|
|
1834
|
+
limit: opts.limit
|
|
1835
|
+
}),
|
|
1690
1836
|
outputOptions(cmd2)
|
|
1691
1837
|
);
|
|
1692
1838
|
});
|
|
1693
|
-
cmd.command("logs <dagId> <instanceId>").description("Show logs for one run").option("--page <n>", "page",
|
|
1839
|
+
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) => {
|
|
1694
1840
|
printJson(
|
|
1695
1841
|
await clientFrom(cmd2).dataflows.logs(dagId, instanceId, {
|
|
1696
1842
|
page: opts.page,
|
|
@@ -1752,8 +1898,8 @@ function dataflowCommand() {
|
|
|
1752
1898
|
|
|
1753
1899
|
// src/commands/explore.ts
|
|
1754
1900
|
import { createServer } from "http";
|
|
1755
|
-
import { Command as
|
|
1756
|
-
var
|
|
1901
|
+
import { Command as Command10 } from "commander";
|
|
1902
|
+
var int7 = (v) => Number.parseInt(v, 10);
|
|
1757
1903
|
var ROUTES = {
|
|
1758
1904
|
"GET /api/bkn/meta": (c, q) => c.kn.get(req(q, "knId")),
|
|
1759
1905
|
"POST /api/bkn/search": (c, _q, b) => c.kn.search(str(b.knId), str(b.query), {
|
|
@@ -1761,7 +1907,6 @@ var ROUTES = {
|
|
|
1761
1907
|
}),
|
|
1762
1908
|
"POST /api/bkn/instances": (c, _q, b) => c.kn.objectTypeQuery(str(b.knId), str(b.objectTypeId), b.body ?? {}),
|
|
1763
1909
|
"POST /api/bkn/subgraph": (c, _q, b) => c.kn.subgraph(str(b.knId), b.body ?? b),
|
|
1764
|
-
"POST /api/bkn/properties": (c, _q, b) => c.kn.objectTypeProperties(str(b.knId), str(b.objectTypeId)),
|
|
1765
1910
|
"GET /api/vega/catalogs": (c) => c.vega.catalogs(),
|
|
1766
1911
|
"GET /api/vega/catalog": (c, q) => c.vega.getCatalog(req(q, "catalogId")),
|
|
1767
1912
|
"GET /api/vega/catalog-resources": (c, q) => c.vega.catalogResources(req(q, "catalogId"), q.get("category") ?? void 0),
|
|
@@ -1798,10 +1943,10 @@ var INDEX = `<!doctype html><meta charset="utf-8"><title>openbkn explore</title>
|
|
|
1798
1943
|
<p>Read-only JSON endpoints for bkn + vega:</p>
|
|
1799
1944
|
<ul>${Object.keys(ROUTES).map((r) => `<li><code>${r}</code></li>`).join("")}</ul>`;
|
|
1800
1945
|
function exploreCommand() {
|
|
1801
|
-
const cmd = new
|
|
1946
|
+
const cmd = new Command10("explore").description(
|
|
1802
1947
|
"Start a local web server with read-only bkn + vega JSON endpoints"
|
|
1803
1948
|
);
|
|
1804
|
-
cmd.option("--port <n>", "port to listen on",
|
|
1949
|
+
cmd.option("--port <n>", "port to listen on", int7, 7777).option("--host <h>", "host to bind", "127.0.0.1").action(async (opts, command) => {
|
|
1805
1950
|
const client = clientFrom(command);
|
|
1806
1951
|
const server = createServer((reqMsg, res) => {
|
|
1807
1952
|
void handle(client, reqMsg, res);
|
|
@@ -1839,8 +1984,14 @@ async function handle(client, reqMsg, res) {
|
|
|
1839
1984
|
}
|
|
1840
1985
|
|
|
1841
1986
|
// src/commands/model.ts
|
|
1842
|
-
import { Command as
|
|
1843
|
-
var
|
|
1987
|
+
import { Command as Command11 } from "commander";
|
|
1988
|
+
var int8 = (v) => Number.parseInt(v, 10);
|
|
1989
|
+
async function resolveLlmModelName(client, model) {
|
|
1990
|
+
if (!/^\d+$/.test(model)) return model;
|
|
1991
|
+
const detail = await client.models.llm.get(model);
|
|
1992
|
+
if (!detail?.model_name) throw new InputError(`No LLM found with id ${model}.`);
|
|
1993
|
+
return detail.model_name;
|
|
1994
|
+
}
|
|
1844
1995
|
function addManagementCommands(parent, kind) {
|
|
1845
1996
|
parent.command("add").description("Register a model (definition JSON via --body / --body-file)").option("--body <json>", "model definition JSON").option("--body-file <path>", "read model definition JSON from a file").action(async (opts, cmd) => {
|
|
1846
1997
|
printJson(await clientFrom(cmd).models[kind].add(readBody(opts)), outputOptions(cmd));
|
|
@@ -1856,9 +2007,11 @@ function addManagementCommands(parent, kind) {
|
|
|
1856
2007
|
});
|
|
1857
2008
|
}
|
|
1858
2009
|
function modelCommand() {
|
|
1859
|
-
const model = new
|
|
2010
|
+
const model = new Command11("model").description(
|
|
2011
|
+
"Model factory \u2014 LLM / small-model CRUD, chat / embeddings / rerank, default selection"
|
|
2012
|
+
);
|
|
1860
2013
|
const llm = model.command("llm").description("Large language models");
|
|
1861
|
-
llm.command("list").description("List LLM models").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size",
|
|
2014
|
+
llm.command("list").description("List LLM models").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size", int8, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int8, 1).action(async (opts, cmd) => {
|
|
1862
2015
|
printJson(
|
|
1863
2016
|
await clientFrom(cmd).models.llm.list({
|
|
1864
2017
|
name: opts.name,
|
|
@@ -1872,18 +2025,26 @@ function modelCommand() {
|
|
|
1872
2025
|
llm.command("get <modelId>").description("Get an LLM model").action(async (id, _opts, cmd) => {
|
|
1873
2026
|
printJson(await clientFrom(cmd).models.llm.get(id), outputOptions(cmd));
|
|
1874
2027
|
});
|
|
1875
|
-
llm.command("chat <
|
|
2028
|
+
llm.command("chat <model>").description("OpenAI-compatible chat completion (<model> = model name or numeric id)").requiredOption("-m, --message <text>", "user message").option("--stream", "stream the reply token-by-token to stdout").action(async (model2, opts, cmd) => {
|
|
2029
|
+
const client = clientFrom(cmd);
|
|
2030
|
+
const name = await resolveLlmModelName(client, model2);
|
|
1876
2031
|
const messages = [{ role: "user", content: opts.message }];
|
|
1877
2032
|
if (opts.stream) {
|
|
1878
|
-
await
|
|
2033
|
+
await client.models.llm.chatStream(name, messages, (t) => process.stdout.write(t));
|
|
1879
2034
|
process.stdout.write("\n");
|
|
1880
2035
|
return;
|
|
1881
2036
|
}
|
|
1882
|
-
printJson(await
|
|
2037
|
+
printJson(await client.models.llm.chat(name, messages), outputOptions(cmd));
|
|
2038
|
+
});
|
|
2039
|
+
llm.command("set-default <modelId>").description("Set this LLM as the system default (admin)").action(async (id, _opts, cmd) => {
|
|
2040
|
+
printJson(await clientFrom(cmd).models.llm.setDefault(id, true), outputOptions(cmd));
|
|
2041
|
+
});
|
|
2042
|
+
llm.command("unset-default <modelId>").description("Clear this LLM as the system default (admin)").action(async (id, _opts, cmd) => {
|
|
2043
|
+
printJson(await clientFrom(cmd).models.llm.setDefault(id, false), outputOptions(cmd));
|
|
1883
2044
|
});
|
|
1884
2045
|
addManagementCommands(llm, "llm");
|
|
1885
2046
|
const small = model.command("small").description("Small models (embedding / reranker)");
|
|
1886
|
-
small.command("list").description("List small models").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size",
|
|
2047
|
+
small.command("list").description("List small models").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size", int8, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int8, 1).action(async (opts, cmd) => {
|
|
1887
2048
|
printJson(
|
|
1888
2049
|
await clientFrom(cmd).models.small.list({
|
|
1889
2050
|
name: opts.name,
|
|
@@ -1909,37 +2070,81 @@ function modelCommand() {
|
|
|
1909
2070
|
outputOptions(cmd)
|
|
1910
2071
|
);
|
|
1911
2072
|
});
|
|
2073
|
+
small.command("get-default").description("Show the system default small model for a type").option("--type <t>", "model type: embedding | reranker", "embedding").action(async (opts, cmd) => {
|
|
2074
|
+
printJson(await clientFrom(cmd).models.small.getDefault(opts.type), outputOptions(cmd));
|
|
2075
|
+
});
|
|
2076
|
+
small.command("set-default <modelId>").description("Set this small model as the system default for its type (admin)").action(async (id, _opts, cmd) => {
|
|
2077
|
+
printJson(await clientFrom(cmd).models.small.setDefault(id, true), outputOptions(cmd));
|
|
2078
|
+
});
|
|
2079
|
+
small.command("unset-default <modelId>").description("Clear this small model as the system default (admin)").action(async (id, _opts, cmd) => {
|
|
2080
|
+
printJson(await clientFrom(cmd).models.small.setDefault(id, false), outputOptions(cmd));
|
|
2081
|
+
});
|
|
1912
2082
|
addManagementCommands(small, "small");
|
|
2083
|
+
model.addHelpText(
|
|
2084
|
+
"after",
|
|
2085
|
+
`
|
|
2086
|
+
Identifiers:
|
|
2087
|
+
\u2022 get / set-default / delete take the numeric model id (e.g. 2071747547839467520).
|
|
2088
|
+
\u2022 chat takes a model NAME, but also accepts a numeric id (resolved to its name).
|
|
2089
|
+
|
|
2090
|
+
Examples:
|
|
2091
|
+
$ openbkn model llm list # ids + the 'default' flag
|
|
2092
|
+
$ openbkn model llm chat deepseek_v4_flash -m hi # by name
|
|
2093
|
+
$ openbkn model llm chat 2071747547839467520 -m hi --stream # by id, streamed
|
|
2094
|
+
$ openbkn model llm set-default 2071747547839467520 # system default LLM
|
|
2095
|
+
$ openbkn model small get-default --type embedding # current default
|
|
2096
|
+
$ openbkn model small set-default <id> # default embedding/reranker`
|
|
2097
|
+
);
|
|
1913
2098
|
return group(model, "MODELS & SKILLS");
|
|
1914
2099
|
}
|
|
1915
2100
|
|
|
1916
2101
|
// src/commands/resource.ts
|
|
1917
|
-
import { Command as
|
|
1918
|
-
var
|
|
2102
|
+
import { Command as Command12 } from "commander";
|
|
2103
|
+
var int9 = (v) => Number.parseInt(v, 10);
|
|
2104
|
+
var parsePairs = (raw) => {
|
|
2105
|
+
if (!raw) return void 0;
|
|
2106
|
+
return raw.split(",").map((part) => {
|
|
2107
|
+
const idx = part.indexOf("=");
|
|
2108
|
+
if (idx < 1) throw new Error("--extension must be key=value[,key=value]");
|
|
2109
|
+
return { key: part.slice(0, idx).trim(), value: part.slice(idx + 1).trim() };
|
|
2110
|
+
}).filter((p) => p.key.length > 0);
|
|
2111
|
+
};
|
|
1919
2112
|
function resourceCommand() {
|
|
1920
|
-
const cmd = new
|
|
1921
|
-
cmd.command("list").description("List resources under a catalog").option("--catalog-id <id>", "filter by catalog id").option("--datasource-id <id>", "alias of --catalog-id").option("--category <c>", "resource category (table | logicview | dataset)").option("--type <c>", "alias of --category").option("--limit <n>", "page size",
|
|
2113
|
+
const cmd = new Command12("resource").alias("res").description("Resources \u2014 list, find, get, query, delete");
|
|
2114
|
+
cmd.command("list").description("List resources under a catalog").option("--catalog-id <id>", "filter by catalog id").option("--datasource-id <id>", "alias of --catalog-id").option("--category <c>", "resource category (table | logicview | dataset)").option("--type <c>", "alias of --category").option("--status <status>", "filter by status").option("--database <name>", "filter by database").option("--limit <n>", "page size", int9, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int9, 0).option("--include-extensions", "include all extension key/value pairs").option("--include-extension-keys <keys>", "include selected extension keys").option("--extension <k=v,...>", "filter by extension key/value pairs").option("--sort <field>", "sort field: name | create_time | update_time").option("--direction <dir>", "sort direction: asc | desc").action(async (opts, cmd2) => {
|
|
1922
2115
|
const data = await clientFrom(cmd2).resource.list({
|
|
1923
2116
|
datasourceId: opts.catalogId ?? opts.datasourceId,
|
|
1924
2117
|
category: opts.category ?? opts.type,
|
|
1925
|
-
|
|
2118
|
+
status: opts.status,
|
|
2119
|
+
database: opts.database,
|
|
2120
|
+
limit: opts.limit,
|
|
2121
|
+
offset: opts.offset,
|
|
2122
|
+
includeExtensions: opts.includeExtensions,
|
|
2123
|
+
includeExtensionKeys: opts.includeExtensionKeys,
|
|
2124
|
+
extensionPairs: parsePairs(opts.extension),
|
|
2125
|
+
sort: opts.sort,
|
|
2126
|
+
direction: opts.direction
|
|
1926
2127
|
});
|
|
1927
2128
|
printJson(data, outputOptions(cmd2));
|
|
1928
2129
|
});
|
|
1929
|
-
cmd.command("find").description("Search resources by name (fuzzy; --exact for strict)").requiredOption("--name <name>", "resource name to search").option("--exact", "exact name match").option("--catalog-id <id>", "limit to a catalog").option("--datasource-id <id>", "alias of --catalog-id").action(async (opts, cmd2) => {
|
|
2130
|
+
cmd.command("find").description("Search resources by name (fuzzy; --exact for strict)").requiredOption("--name <name>", "resource name to search").option("--exact", "exact name match").option("--catalog-id <id>", "limit to a catalog").option("--datasource-id <id>", "alias of --catalog-id").option("--limit <n>", "rows to scan before filtering", int9, DEFAULT_LIST_LIMIT).action(async (opts, cmd2) => {
|
|
1930
2131
|
const data = await clientFrom(cmd2).resource.find(opts.name, {
|
|
1931
2132
|
exact: opts.exact,
|
|
1932
|
-
datasourceId: opts.catalogId ?? opts.datasourceId
|
|
2133
|
+
datasourceId: opts.catalogId ?? opts.datasourceId,
|
|
2134
|
+
limit: opts.limit
|
|
1933
2135
|
});
|
|
1934
2136
|
printJson(data, outputOptions(cmd2));
|
|
1935
2137
|
});
|
|
1936
2138
|
cmd.command("get <id>").description("Get resource details").action(async (id, _opts, cmd2) => {
|
|
1937
2139
|
printJson(await clientFrom(cmd2).resource.get(id), outputOptions(cmd2));
|
|
1938
2140
|
});
|
|
1939
|
-
cmd.command("query <id>").description("Fetch data rows from a resource").option("--limit <n>", "row limit",
|
|
2141
|
+
cmd.command("query <id>").description("Fetch data rows from a resource").option("--limit <n>", "row limit", int9, DEFAULT_QUERY_LIMIT).option("--offset <n>", "row offset", int9, 0).option("--paging-mode <mode>", "paging mode: single | cursor").option("--keep-alive-sec <s>", "cursor keep-alive in seconds (60\u20133600)", int9).option("--cursor <cursor>", "opaque cursor returned by the previous page").option("--need-total", "include total count").action(async (id, opts, cmd2) => {
|
|
1940
2142
|
const data = await clientFrom(cmd2).resource.query(id, {
|
|
1941
2143
|
limit: opts.limit,
|
|
1942
2144
|
offset: opts.offset,
|
|
2145
|
+
pagingMode: opts.pagingMode,
|
|
2146
|
+
keepAliveSec: opts.keepAliveSec,
|
|
2147
|
+
cursor: opts.cursor,
|
|
1943
2148
|
needTotal: opts.needTotal
|
|
1944
2149
|
});
|
|
1945
2150
|
printJson(data, outputOptions(cmd2));
|
|
@@ -1951,11 +2156,11 @@ function resourceCommand() {
|
|
|
1951
2156
|
}
|
|
1952
2157
|
|
|
1953
2158
|
// src/commands/skill.ts
|
|
1954
|
-
import { Command as
|
|
1955
|
-
var
|
|
2159
|
+
import { Command as Command13 } from "commander";
|
|
2160
|
+
var int10 = (v) => Number.parseInt(v, 10);
|
|
1956
2161
|
function skillCommand() {
|
|
1957
|
-
const cmd = new
|
|
1958
|
-
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",
|
|
2162
|
+
const cmd = new Command13("skill").description("Skill registry and market");
|
|
2163
|
+
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", int10, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int10, 1);
|
|
1959
2164
|
listOpts(cmd.command("list").description("List skills")).option("--create-user <s>", "filter by creator").action(async (opts, cmd2) => {
|
|
1960
2165
|
printJson(
|
|
1961
2166
|
await clientFrom(cmd2).skills.list({
|
|
@@ -2041,11 +2246,11 @@ function skillCommand() {
|
|
|
2041
2246
|
}
|
|
2042
2247
|
|
|
2043
2248
|
// src/commands/toolbox.ts
|
|
2044
|
-
import { Command as
|
|
2045
|
-
var
|
|
2249
|
+
import { Command as Command14 } from "commander";
|
|
2250
|
+
var int11 = (v) => Number.parseInt(v, 10);
|
|
2046
2251
|
function toolboxCommand() {
|
|
2047
|
-
const cmd = new
|
|
2048
|
-
cmd.command("list").description("List toolboxes").option("--keyword <s>", "filter by keyword").option("--limit <n>", "page size",
|
|
2252
|
+
const cmd = new Command14("toolbox").description("Agent toolbox lifecycle");
|
|
2253
|
+
cmd.command("list").description("List toolboxes").option("--keyword <s>", "filter by keyword").option("--limit <n>", "page size", int11, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int11, 0).action(async (opts, cmd2) => {
|
|
2049
2254
|
printJson(
|
|
2050
2255
|
await clientFrom(cmd2).toolboxes.list({
|
|
2051
2256
|
keyword: opts.keyword,
|
|
@@ -2086,9 +2291,16 @@ function toolboxCommand() {
|
|
|
2086
2291
|
return group(cmd, "DECISION AGENT");
|
|
2087
2292
|
}
|
|
2088
2293
|
function toolCommand() {
|
|
2089
|
-
const cmd = new
|
|
2090
|
-
cmd.command("list").description("List tools in a toolbox").requiredOption("--toolbox <box-id>", "toolbox id").action(async (opts, cmd2) => {
|
|
2091
|
-
printJson(
|
|
2294
|
+
const cmd = new Command14("tool").description("Tools inside a toolbox");
|
|
2295
|
+
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)", int11).option("--page <n>", "page (1-based; backend default 1)", int11).option("--all", "return every tool, ignoring page size").action(async (opts, cmd2) => {
|
|
2296
|
+
printJson(
|
|
2297
|
+
await clientFrom(cmd2).toolboxes.tools(opts.toolbox, {
|
|
2298
|
+
page: opts.page,
|
|
2299
|
+
pageSize: opts.limit,
|
|
2300
|
+
all: opts.all
|
|
2301
|
+
}),
|
|
2302
|
+
outputOptions(cmd2)
|
|
2303
|
+
);
|
|
2092
2304
|
});
|
|
2093
2305
|
cmd.command("enable <tool-ids...>").description("Enable one or more tools").requiredOption("--toolbox <box-id>", "toolbox id").action(async (toolIds, opts, cmd2) => {
|
|
2094
2306
|
printJson(
|
|
@@ -2102,7 +2314,7 @@ function toolCommand() {
|
|
|
2102
2314
|
outputOptions(cmd2)
|
|
2103
2315
|
);
|
|
2104
2316
|
});
|
|
2105
|
-
const invokeOpts = (c) => c.requiredOption("--toolbox <box-id>", "toolbox id").option("--body <json>", "request body JSON").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",
|
|
2317
|
+
const invokeOpts = (c) => c.requiredOption("--toolbox <box-id>", "toolbox id").option("--body <json>", "request body JSON").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", int11);
|
|
2106
2318
|
const parseJson = (s, label) => {
|
|
2107
2319
|
if (!s) return void 0;
|
|
2108
2320
|
try {
|
|
@@ -2144,11 +2356,11 @@ function toolCommand() {
|
|
|
2144
2356
|
}
|
|
2145
2357
|
|
|
2146
2358
|
// src/commands/trace.ts
|
|
2147
|
-
import { readFileSync as
|
|
2148
|
-
import { Command as
|
|
2359
|
+
import { readFileSync as readFileSync5, writeFileSync } from "fs";
|
|
2360
|
+
import { Command as Command15 } from "commander";
|
|
2149
2361
|
|
|
2150
|
-
// src/trace
|
|
2151
|
-
import { readFileSync as
|
|
2362
|
+
// src/bkn-trace/schema-validate.ts
|
|
2363
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
2152
2364
|
import { extname } from "path";
|
|
2153
2365
|
import yaml from "js-yaml";
|
|
2154
2366
|
import { z } from "zod";
|
|
@@ -2185,7 +2397,7 @@ var DiagnosisRule = z.object({
|
|
|
2185
2397
|
params: z.record(z.string(), z.unknown()).optional()
|
|
2186
2398
|
});
|
|
2187
2399
|
function parseFile(file) {
|
|
2188
|
-
const text =
|
|
2400
|
+
const text = readFileSync4(file, "utf8");
|
|
2189
2401
|
const ext = extname(file).toLowerCase();
|
|
2190
2402
|
if (ext === ".yaml" || ext === ".yml") return yaml.load(text);
|
|
2191
2403
|
return JSON.parse(text);
|
|
@@ -2223,9 +2435,36 @@ function validateSchemaFile(file, kind) {
|
|
|
2223
2435
|
|
|
2224
2436
|
// src/commands/trace.ts
|
|
2225
2437
|
function traceCommand() {
|
|
2226
|
-
const cmd = new
|
|
2227
|
-
"Trace
|
|
2438
|
+
const cmd = new Command15("trace").description(
|
|
2439
|
+
"BKN Trace \u2014 fetch spans, diagnose (symbolic + LLM rubric), scan, eval-set, schema validate"
|
|
2228
2440
|
);
|
|
2441
|
+
cmd.command("graph <trace-id>").description("Fetch normalized trace graph by trace id").action(async (traceId, _opts, cmd2) => {
|
|
2442
|
+
printJson(await clientFrom(cmd2).trace.graph(traceId), outputOptions(cmd2));
|
|
2443
|
+
});
|
|
2444
|
+
cmd.command("evidence-chain [trace-id]").description("Fetch BKN Trace evidence chain by trace id or --request-id").option("--request-id <id>", "BKN request id scope").option("--limit <n>", "maximum evidence trace batches", (v) => Number.parseInt(v, 10)).action(async (traceId, opts, cmd2) => {
|
|
2445
|
+
printJson(
|
|
2446
|
+
await clientFrom(cmd2).trace.evidenceChain(traceScope(traceId, opts.requestId), {
|
|
2447
|
+
limit: opts.limit
|
|
2448
|
+
}),
|
|
2449
|
+
outputOptions(cmd2)
|
|
2450
|
+
);
|
|
2451
|
+
});
|
|
2452
|
+
cmd.command("business-graph [trace-id]").description("Fetch BKN Trace business semantic graph by trace id or --request-id").option("--request-id <id>", "BKN request id scope").option("--limit <n>", "maximum evidence trace batches", (v) => Number.parseInt(v, 10)).action(async (traceId, opts, cmd2) => {
|
|
2453
|
+
printJson(
|
|
2454
|
+
await clientFrom(cmd2).trace.businessGraph(traceScope(traceId, opts.requestId), {
|
|
2455
|
+
limit: opts.limit
|
|
2456
|
+
}),
|
|
2457
|
+
outputOptions(cmd2)
|
|
2458
|
+
);
|
|
2459
|
+
});
|
|
2460
|
+
cmd.command("snapshot-preview [trace-id]").description("Fetch metadata-only evidence snapshot preview by trace id or --request-id").option("--request-id <id>", "BKN request id scope").option("--limit <n>", "maximum evidence trace batches", (v) => Number.parseInt(v, 10)).action(async (traceId, opts, cmd2) => {
|
|
2461
|
+
printJson(
|
|
2462
|
+
await clientFrom(cmd2).trace.snapshotPreview(traceScope(traceId, opts.requestId), {
|
|
2463
|
+
limit: opts.limit
|
|
2464
|
+
}),
|
|
2465
|
+
outputOptions(cmd2)
|
|
2466
|
+
);
|
|
2467
|
+
});
|
|
2229
2468
|
cmd.command("get <conversation-id>").description("Fetch all trace spans for a conversation").option("--max-spans <n>", "max spans", (v) => Number.parseInt(v, 10)).action(async (conversationId, opts, cmd2) => {
|
|
2230
2469
|
printJson(
|
|
2231
2470
|
await clientFrom(cmd2).trace.spans(conversationId, { maxSpans: opts.maxSpans }),
|
|
@@ -2252,7 +2491,7 @@ function traceCommand() {
|
|
|
2252
2491
|
});
|
|
2253
2492
|
const evalSet = cmd.command("eval-set").description("Build + run trace eval sets");
|
|
2254
2493
|
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) => {
|
|
2255
|
-
const raw = JSON.parse(
|
|
2494
|
+
const raw = JSON.parse(readFileSync5(queriesFile, "utf8"));
|
|
2256
2495
|
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2257
2496
|
if (opts.out) {
|
|
2258
2497
|
writeFileSync(opts.out, JSON.stringify({ cases }, null, 2));
|
|
@@ -2262,7 +2501,7 @@ function traceCommand() {
|
|
|
2262
2501
|
}
|
|
2263
2502
|
});
|
|
2264
2503
|
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) => {
|
|
2265
|
-
const raw = JSON.parse(
|
|
2504
|
+
const raw = JSON.parse(readFileSync5(casesFile, "utf8"));
|
|
2266
2505
|
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2267
2506
|
const result = await clientFrom(cmd2).trace.evalSetTest(opts.agent, cases, {
|
|
2268
2507
|
version: opts.version,
|
|
@@ -2277,45 +2516,108 @@ function traceCommand() {
|
|
|
2277
2516
|
printJson(result, outputOptions(cmd2));
|
|
2278
2517
|
if (!result.valid) process.exitCode = 1;
|
|
2279
2518
|
});
|
|
2519
|
+
cmd.command("validate-fixture <path>").description("Validate BKN Trace 1.0/2.0/2.1 fixture JSON files").action(async (path, _opts, cmd2) => {
|
|
2520
|
+
const result = validateFixturePath(path);
|
|
2521
|
+
printJson(result, outputOptions(cmd2));
|
|
2522
|
+
if (!result.ok) process.exitCode = 1;
|
|
2523
|
+
});
|
|
2524
|
+
const evidence = cmd.command("evidence").description("Submit BKN Trace 2.x business evidence events");
|
|
2525
|
+
evidence.command("emit <file>").description("Submit a BKN Trace 2.0/2.1 event batch JSON file").action(async (file, _opts, cmd2) => {
|
|
2526
|
+
const body = JSON.parse(readFileSync5(file, "utf8"));
|
|
2527
|
+
printJson(await clientFrom(cmd2).trace.emitEvidenceEvents(body), outputOptions(cmd2));
|
|
2528
|
+
});
|
|
2280
2529
|
return group(cmd, "TRACE AI");
|
|
2281
2530
|
}
|
|
2531
|
+
function traceScope(traceId, requestId) {
|
|
2532
|
+
if (traceId && requestId) {
|
|
2533
|
+
throw new InputError("Provide either trace id or --request-id, not both.");
|
|
2534
|
+
}
|
|
2535
|
+
if (requestId) return { requestId };
|
|
2536
|
+
if (traceId) return traceId;
|
|
2537
|
+
throw new InputError("Provide a trace id or --request-id.");
|
|
2538
|
+
}
|
|
2282
2539
|
|
|
2283
2540
|
// src/commands/vega.ts
|
|
2284
|
-
import { Command as
|
|
2541
|
+
import { Command as Command16 } from "commander";
|
|
2542
|
+
var int12 = (v) => Number.parseInt(v, 10);
|
|
2543
|
+
var parsePairs2 = (raw) => {
|
|
2544
|
+
if (!raw) return void 0;
|
|
2545
|
+
return raw.split(",").map((part) => {
|
|
2546
|
+
const idx = part.indexOf("=");
|
|
2547
|
+
if (idx < 1) throw new InputError("--extension must be key=value[,key=value]");
|
|
2548
|
+
return { key: part.slice(0, idx).trim(), value: part.slice(idx + 1).trim() };
|
|
2549
|
+
}).filter((p) => p.key.length > 0);
|
|
2550
|
+
};
|
|
2285
2551
|
function vegaCommand() {
|
|
2286
|
-
const vega = new
|
|
2552
|
+
const vega = new Command16("vega").description(
|
|
2287
2553
|
"Vega observability \u2014 catalog, resources, index build tasks"
|
|
2288
2554
|
);
|
|
2289
2555
|
const catalog = vega.command("catalog").description("Catalog entries");
|
|
2290
|
-
catalog.command("list").description("List catalog entries").option("--limit <n>", "page size", (v) => Number.parseInt(v, 10), DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", (v) => Number.parseInt(v, 10), 0).action(async (_opts, cmd) => {
|
|
2556
|
+
catalog.command("list").description("List catalog entries").option("--limit <n>", "page size", (v) => Number.parseInt(v, 10), DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", (v) => Number.parseInt(v, 10), 0).option("--name <s>", "filter by name").option("--tag <s>", "filter by tag").option("--type <type>", "filter by catalog type: physical | logical").option("--enabled <bool>", "filter by enabled state").option("--health-check-status <s>", "filter by health status").option("--include-extensions", "include all extension key/value pairs").option("--include-extension-keys <keys>", "include selected extension keys").option("--extension <k=v,...>", "filter by extension key/value pairs").option("--sort <field>", "sort field: name | create_time | update_time").option("--direction <dir>", "sort direction: asc | desc").action(async (_opts, cmd) => {
|
|
2291
2557
|
const o = cmd.optsWithGlobals();
|
|
2292
|
-
const data = await clientFrom(cmd).vega.catalogs({
|
|
2558
|
+
const data = await clientFrom(cmd).vega.catalogs({
|
|
2559
|
+
limit: o.limit,
|
|
2560
|
+
offset: o.offset,
|
|
2561
|
+
name: o.name,
|
|
2562
|
+
tag: o.tag,
|
|
2563
|
+
type: o.type,
|
|
2564
|
+
enabled: o.enabled === void 0 ? void 0 : o.enabled === "true",
|
|
2565
|
+
healthCheckStatus: o.healthCheckStatus,
|
|
2566
|
+
includeExtensions: o.includeExtensions,
|
|
2567
|
+
includeExtensionKeys: o.includeExtensionKeys,
|
|
2568
|
+
extensionPairs: parsePairs2(o.extension),
|
|
2569
|
+
sort: o.sort,
|
|
2570
|
+
direction: o.direction
|
|
2571
|
+
});
|
|
2293
2572
|
printJson(data, outputOptions(cmd));
|
|
2294
2573
|
});
|
|
2295
2574
|
catalog.command("get <id>").description("Get a catalog by id").action(async (id, _opts, cmd) => {
|
|
2296
2575
|
printJson(await clientFrom(cmd).vega.getCatalog(id), outputOptions(cmd));
|
|
2297
2576
|
});
|
|
2298
|
-
catalog.command("resources <id>").description("List resources under a catalog").option("--category <c>", "filter by category (e.g. table)").action(async (id, opts, cmd) => {
|
|
2299
|
-
printJson(
|
|
2577
|
+
catalog.command("resources <id>").description("List resources under a catalog").option("--category <c>", "filter by category (e.g. table)").option("--limit <n>", "page size (backend default 20, max 1000; -1 = all)", int12).option("--offset <n>", "page offset", int12, 0).action(async (id, opts, cmd) => {
|
|
2578
|
+
printJson(
|
|
2579
|
+
await clientFrom(cmd).vega.catalogResources(id, opts.category, opts.limit, opts.offset),
|
|
2580
|
+
outputOptions(cmd)
|
|
2581
|
+
);
|
|
2300
2582
|
});
|
|
2301
2583
|
catalog.command("health <ids...>").description("Health-status for one or more catalogs").action(async (ids, _opts, cmd) => {
|
|
2302
2584
|
printJson(await clientFrom(cmd).vega.catalogHealth(ids), outputOptions(cmd));
|
|
2303
2585
|
});
|
|
2304
|
-
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("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--enabled", "create enabled (default: disabled)").action(async (opts, cmd) => {
|
|
2586
|
+
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("--extensions <json>", "extension key/value JSON object").action(async (opts, cmd) => {
|
|
2305
2587
|
let connectorConfig;
|
|
2306
2588
|
try {
|
|
2307
2589
|
connectorConfig = JSON.parse(opts.connectorConfig);
|
|
2308
2590
|
} catch {
|
|
2309
2591
|
throw new Error("--connector-config must be valid JSON");
|
|
2310
2592
|
}
|
|
2593
|
+
const extensions = opts.extensions ? JSON.parse(opts.extensions) : void 0;
|
|
2311
2594
|
printJson(
|
|
2312
2595
|
await clientFrom(cmd).vega.createCatalog({
|
|
2596
|
+
id: opts.id,
|
|
2313
2597
|
name: opts.name,
|
|
2314
2598
|
connectorType: opts.connectorType,
|
|
2315
2599
|
connectorConfig,
|
|
2316
2600
|
tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
|
|
2317
2601
|
description: opts.description,
|
|
2318
|
-
enabled: opts.enabled ? true : void 0
|
|
2602
|
+
enabled: opts.enabled ? true : void 0,
|
|
2603
|
+
internal: opts.internal ? true : void 0,
|
|
2604
|
+
extensions
|
|
2605
|
+
}),
|
|
2606
|
+
outputOptions(cmd)
|
|
2607
|
+
);
|
|
2608
|
+
});
|
|
2609
|
+
catalog.command("update <id>").description("Update a catalog").option("--name <s>", "catalog name").option("--connector-type <s>", "connector type").option("--connector-config <json>", "connector config JSON").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--enabled <bool>", "enabled state").option("--extensions <json>", "extension key/value JSON object").action(async (id, opts, cmd) => {
|
|
2610
|
+
const connectorConfig = opts.connectorConfig ? JSON.parse(opts.connectorConfig) : void 0;
|
|
2611
|
+
const extensions = opts.extensions ? JSON.parse(opts.extensions) : void 0;
|
|
2612
|
+
printJson(
|
|
2613
|
+
await clientFrom(cmd).vega.updateCatalog(id, {
|
|
2614
|
+
name: opts.name,
|
|
2615
|
+
connectorType: opts.connectorType,
|
|
2616
|
+
connectorConfig,
|
|
2617
|
+
tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
|
|
2618
|
+
description: opts.description,
|
|
2619
|
+
enabled: opts.enabled === void 0 ? void 0 : opts.enabled === "true",
|
|
2620
|
+
extensions
|
|
2319
2621
|
}),
|
|
2320
2622
|
outputOptions(cmd)
|
|
2321
2623
|
);
|
|
@@ -2323,6 +2625,15 @@ function vegaCommand() {
|
|
|
2323
2625
|
catalog.command("enable <id>").description("Enable a catalog (required before discovery)").action(async (id, _opts, cmd) => {
|
|
2324
2626
|
printJson(await clientFrom(cmd).vega.enableCatalog(id), outputOptions(cmd));
|
|
2325
2627
|
});
|
|
2628
|
+
catalog.command("disable <id>").description("Disable a catalog").action(async (id, _opts, cmd) => {
|
|
2629
|
+
printJson(await clientFrom(cmd).vega.disableCatalog(id), outputOptions(cmd));
|
|
2630
|
+
});
|
|
2631
|
+
catalog.command("delete <id>").description("Delete a catalog").action(async (id, _opts, cmd) => {
|
|
2632
|
+
printJson(await clientFrom(cmd).vega.deleteCatalog(id), outputOptions(cmd));
|
|
2633
|
+
});
|
|
2634
|
+
catalog.command("test-connection <id>").description("Test a catalog connection").action(async (id, _opts, cmd) => {
|
|
2635
|
+
printJson(await clientFrom(cmd).vega.testCatalogConnection(id), outputOptions(cmd));
|
|
2636
|
+
});
|
|
2326
2637
|
catalog.command("discover <id>").description("Trigger catalog resource discovery").option("--wait", "wait for discovery to complete").action(async (id, opts, cmd) => {
|
|
2327
2638
|
printJson(
|
|
2328
2639
|
await clientFrom(cmd).vega.discoverCatalog(id, Boolean(opts.wait)),
|
|
@@ -2336,13 +2647,67 @@ function vegaCommand() {
|
|
|
2336
2647
|
connector.command("get <type>").description("Get a connector type").action(async (type, _opts, cmd) => {
|
|
2337
2648
|
printJson(await clientFrom(cmd).vega.connectorType(type), outputOptions(cmd));
|
|
2338
2649
|
});
|
|
2650
|
+
vega.command("sql").description("Run SQL / OpenSearch DSL directly against a vega-backend data source").option(
|
|
2651
|
+
"--query <sql>",
|
|
2652
|
+
"SQL string; reference a resource with a {{<resource-id>}} placeholder"
|
|
2653
|
+
).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)", int12).option("--offset <n>", "first-page offset", int12).option("--keep-alive-sec <s>", "cursor keep-alive in seconds (60\u20133600)", int12).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)", int12).option(
|
|
2654
|
+
"-d, --data <json>",
|
|
2655
|
+
"full request body as JSON (advanced; wins over individual query flags)"
|
|
2656
|
+
).action(async (opts, cmd) => {
|
|
2657
|
+
let body;
|
|
2658
|
+
if (opts.data) {
|
|
2659
|
+
try {
|
|
2660
|
+
body = JSON.parse(opts.data);
|
|
2661
|
+
} catch {
|
|
2662
|
+
throw new InputError("--data must be valid JSON");
|
|
2663
|
+
}
|
|
2664
|
+
} else if (opts.cursor) {
|
|
2665
|
+
if (opts.query || opts.inputDialect || opts.pagingMode || opts.limit !== void 0 || opts.offset !== void 0 || opts.keepAliveSec !== void 0 || opts.queryTimeoutSec !== void 0) {
|
|
2666
|
+
throw new InputError("--cursor cannot be combined with initial-query options");
|
|
2667
|
+
}
|
|
2668
|
+
body = {
|
|
2669
|
+
paging: { cursor: opts.cursor },
|
|
2670
|
+
...opts.needTotal ? { need_total: true } : {}
|
|
2671
|
+
};
|
|
2672
|
+
} else {
|
|
2673
|
+
if (!opts.query) {
|
|
2674
|
+
throw new InputError("Provide --query, --cursor, or --data.");
|
|
2675
|
+
}
|
|
2676
|
+
if (opts.pagingMode === "cursor" && opts.limit === void 0) {
|
|
2677
|
+
throw new InputError("--limit is required when --paging-mode cursor");
|
|
2678
|
+
}
|
|
2679
|
+
const paging = {
|
|
2680
|
+
...opts.pagingMode ? { mode: opts.pagingMode } : {},
|
|
2681
|
+
...opts.limit !== void 0 ? { limit: opts.limit } : {},
|
|
2682
|
+
...opts.offset !== void 0 ? { offset: opts.offset } : {},
|
|
2683
|
+
...opts.keepAliveSec !== void 0 ? { keep_alive_sec: opts.keepAliveSec } : {}
|
|
2684
|
+
};
|
|
2685
|
+
body = {
|
|
2686
|
+
query: opts.query,
|
|
2687
|
+
query_format: "sql",
|
|
2688
|
+
...opts.inputDialect ? { input_dialect: opts.inputDialect } : {},
|
|
2689
|
+
...Object.keys(paging).length ? { paging } : {},
|
|
2690
|
+
...opts.needTotal ? { need_total: true } : {},
|
|
2691
|
+
...opts.queryTimeoutSec !== void 0 ? { query_timeout_sec: opts.queryTimeoutSec } : {}
|
|
2692
|
+
};
|
|
2693
|
+
}
|
|
2694
|
+
printJson(await clientFrom(cmd).vega.sql(body), outputOptions(cmd));
|
|
2695
|
+
});
|
|
2339
2696
|
const resource = vega.command("resource").description("Vega-backend resources");
|
|
2340
|
-
resource.command("list").description("List resources").option("--datasource-id <id>", "filter by catalog/datasource id").option("--catalog-id <id>", "alias of --datasource-id").option("--type <category>", "resource category").option("--category <category>", "alias of --type").option("--limit <n>", "page size", (v) => Number.parseInt(v, 10), DEFAULT_LIST_LIMIT).action(async (opts, cmd) => {
|
|
2697
|
+
resource.command("list").description("List resources").option("--datasource-id <id>", "filter by catalog/datasource id").option("--catalog-id <id>", "alias of --datasource-id").option("--type <category>", "resource category").option("--category <category>", "alias of --type").option("--status <status>", "filter by status").option("--database <name>", "filter by database").option("--limit <n>", "page size", (v) => Number.parseInt(v, 10), DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int12, 0).option("--include-extensions", "include all extension key/value pairs").option("--include-extension-keys <keys>", "include selected extension keys").option("--extension <k=v,...>", "filter by extension key/value pairs").option("--sort <field>", "sort field: name | create_time | update_time").option("--direction <dir>", "sort direction: asc | desc").action(async (opts, cmd) => {
|
|
2341
2698
|
printJson(
|
|
2342
2699
|
await clientFrom(cmd).resource.list({
|
|
2343
2700
|
datasourceId: opts.datasourceId ?? opts.catalogId,
|
|
2344
2701
|
category: opts.type ?? opts.category,
|
|
2345
|
-
|
|
2702
|
+
status: opts.status,
|
|
2703
|
+
database: opts.database,
|
|
2704
|
+
limit: opts.limit,
|
|
2705
|
+
offset: opts.offset,
|
|
2706
|
+
includeExtensions: opts.includeExtensions,
|
|
2707
|
+
includeExtensionKeys: opts.includeExtensionKeys,
|
|
2708
|
+
extensionPairs: parsePairs2(opts.extension),
|
|
2709
|
+
sort: opts.sort,
|
|
2710
|
+
direction: opts.direction
|
|
2346
2711
|
}),
|
|
2347
2712
|
outputOptions(cmd)
|
|
2348
2713
|
);
|
|
@@ -2360,16 +2725,25 @@ function vegaCommand() {
|
|
|
2360
2725
|
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(
|
|
2361
2726
|
"--build-key-fields <list>",
|
|
2362
2727
|
"comma-separated key fields (batch: time; streaming: row id)"
|
|
2363
|
-
).option("--embedding-model <id>", "embedding model id
|
|
2728
|
+
).option("--embedding-model <id>", "default embedding model name/id").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) => {
|
|
2364
2729
|
const o = cmd.optsWithGlobals();
|
|
2730
|
+
const embeddingFields = csv(o.embeddingFields);
|
|
2731
|
+
const buildKeyFields = csv(o.buildKeyFields);
|
|
2732
|
+
const fulltextFields = csv(o.fulltextFields);
|
|
2733
|
+
if (embeddingFields || buildKeyFields || o.embeddingModel || fulltextFields || o.fulltextAnalyzer) {
|
|
2734
|
+
await clientFrom(cmd).resource.configureIndex(resourceId, {
|
|
2735
|
+
embeddingFields,
|
|
2736
|
+
buildKeyFields,
|
|
2737
|
+
embeddingModel: o.embeddingModel,
|
|
2738
|
+
fulltextFields,
|
|
2739
|
+
fulltextAnalyzer: o.fulltextAnalyzer
|
|
2740
|
+
});
|
|
2741
|
+
}
|
|
2365
2742
|
const task = await clientFrom(cmd).vega.build(
|
|
2366
2743
|
{
|
|
2367
2744
|
resource_id: resourceId,
|
|
2368
2745
|
mode: o.mode,
|
|
2369
|
-
|
|
2370
|
-
build_key_fields: csv(o.buildKeyFields),
|
|
2371
|
-
embedding_model: o.embeddingModel,
|
|
2372
|
-
model_dimensions: o.modelDimensions
|
|
2746
|
+
execute_type: o.executeType
|
|
2373
2747
|
},
|
|
2374
2748
|
{ wait: Boolean(o.wait), timeoutMs: o.timeout * 1e3 }
|
|
2375
2749
|
);
|
|
@@ -2379,15 +2753,50 @@ function vegaCommand() {
|
|
|
2379
2753
|
const task = await clientFrom(cmd).vega.buildStatus(taskId);
|
|
2380
2754
|
printJson(task, outputOptions(cmd));
|
|
2381
2755
|
});
|
|
2756
|
+
dataset.command("build-list").description("List BuildTasks").option("--limit <n>", "page size", int12, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int12, 0).option("--resource-id <id>", "filter by resource id").option("--catalog-id <id>", "filter by catalog id").option("--status <status>", "comma-separated statuses").option("--active", "only running/init tasks").option("--mode <mode>", "filter by mode: batch | streaming").option("--order-by <field>", "default | created_at | updated_at | status | mode").option("--order <dir>", "asc | desc").action(async (opts, cmd) => {
|
|
2757
|
+
printJson(
|
|
2758
|
+
await clientFrom(cmd).vega.buildTasks({
|
|
2759
|
+
limit: opts.limit,
|
|
2760
|
+
offset: opts.offset,
|
|
2761
|
+
resourceId: opts.resourceId,
|
|
2762
|
+
catalogId: opts.catalogId,
|
|
2763
|
+
status: opts.status,
|
|
2764
|
+
active: opts.active,
|
|
2765
|
+
mode: opts.mode,
|
|
2766
|
+
orderBy: opts.orderBy,
|
|
2767
|
+
order: opts.order
|
|
2768
|
+
}),
|
|
2769
|
+
outputOptions(cmd)
|
|
2770
|
+
);
|
|
2771
|
+
});
|
|
2772
|
+
dataset.command("build-start <task-id>").description("Start a BuildTask").option("--reset", "restart from the beginning").action(async (taskId, opts, cmd) => {
|
|
2773
|
+
printJson(
|
|
2774
|
+
await clientFrom(cmd).vega.startBuildTask(taskId, { reset: opts.reset }),
|
|
2775
|
+
outputOptions(cmd)
|
|
2776
|
+
);
|
|
2777
|
+
});
|
|
2778
|
+
dataset.command("build-stop <task-id>").description("Stop a BuildTask").action(async (taskId, _opts, cmd) => {
|
|
2779
|
+
printJson(await clientFrom(cmd).vega.stopBuildTask(taskId), outputOptions(cmd));
|
|
2780
|
+
});
|
|
2781
|
+
dataset.command("build-delete <ids...>").description("Delete one or more BuildTasks").option("--ignore-missing", "ignore missing task ids").option("--delete-active-index", "delete active indexes too").action(async (ids, opts, cmd) => {
|
|
2782
|
+
printJson(
|
|
2783
|
+
await clientFrom(cmd).vega.deleteBuildTasks(ids, {
|
|
2784
|
+
ignoreMissing: opts.ignoreMissing,
|
|
2785
|
+
deleteActiveIndex: opts.deleteActiveIndex
|
|
2786
|
+
}),
|
|
2787
|
+
outputOptions(cmd)
|
|
2788
|
+
);
|
|
2789
|
+
});
|
|
2382
2790
|
return group(vega, "AI DATA PLATFORM");
|
|
2383
2791
|
}
|
|
2384
2792
|
|
|
2385
2793
|
// src/cli.ts
|
|
2386
|
-
var program = new
|
|
2387
|
-
program.name("openbkn").description("Operate the BKN platform from the CLI").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("-k, --insecure", "skip TLS verification (dev / self-signed only)").showHelpAfterError();
|
|
2794
|
+
var program = new Command17();
|
|
2795
|
+
program.name("openbkn").description("Operate the BKN platform from the CLI").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("-k, --insecure", "skip TLS verification (dev / self-signed only)").showHelpAfterError();
|
|
2388
2796
|
program.addCommand(authCommand());
|
|
2389
2797
|
program.addCommand(callCommand());
|
|
2390
2798
|
program.addCommand(configCommand());
|
|
2799
|
+
program.addCommand(appkeyCommand());
|
|
2391
2800
|
program.addCommand(vegaCommand());
|
|
2392
2801
|
program.addCommand(bknCommand());
|
|
2393
2802
|
program.addCommand(resourceCommand());
|