@openbkn/bkn-sdk 0.1.1-alpha.8 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -0
- package/NOTICE +21 -0
- package/README.md +31 -25
- package/README.zh.md +10 -12
- package/dist/{chunk-DTU5DGJW.js → chunk-NC6DZ2AU.js} +648 -194
- package/dist/cli.js +504 -179
- package/dist/index.d.ts +383 -64
- package/dist/index.js +1 -1
- package/package.json +5 -4
- package/dist/chunk-DTU5DGJW.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,7 +27,6 @@ import {
|
|
|
28
27
|
rawCall,
|
|
29
28
|
readPlatformConfig,
|
|
30
29
|
renderReportMarkdown,
|
|
31
|
-
request,
|
|
32
30
|
resolveContext,
|
|
33
31
|
setActivePlatform,
|
|
34
32
|
status,
|
|
@@ -37,15 +35,15 @@ import {
|
|
|
37
35
|
use,
|
|
38
36
|
whoami,
|
|
39
37
|
writePlatformConfig
|
|
40
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-NC6DZ2AU.js";
|
|
41
39
|
|
|
42
40
|
// src/cli.ts
|
|
43
|
-
import { Command as
|
|
41
|
+
import { Command as Command17 } from "commander";
|
|
44
42
|
|
|
45
43
|
// package.json
|
|
46
44
|
var package_default = {
|
|
47
45
|
name: "@openbkn/bkn-sdk",
|
|
48
|
-
version: "0.1.1
|
|
46
|
+
version: "0.1.1",
|
|
49
47
|
description: "Unified TypeScript SDK + CLI for the BKN (Business Knowledge Network) platform.",
|
|
50
48
|
type: "module",
|
|
51
49
|
license: "Apache-2.0",
|
|
@@ -63,7 +61,7 @@ var package_default = {
|
|
|
63
61
|
import: "./dist/index.js"
|
|
64
62
|
}
|
|
65
63
|
},
|
|
66
|
-
files: ["dist", "README.md", "README.zh.md", "LICENSE"],
|
|
64
|
+
files: ["dist", "!dist/**/*.map", "README.md", "README.zh.md", "LICENSE", "NOTICE"],
|
|
67
65
|
publishConfig: {
|
|
68
66
|
access: "public"
|
|
69
67
|
},
|
|
@@ -76,7 +74,8 @@ var package_default = {
|
|
|
76
74
|
build: "tsup",
|
|
77
75
|
dev: "tsup --watch",
|
|
78
76
|
typecheck: "tsc --noEmit",
|
|
79
|
-
|
|
77
|
+
"check:deps": "node scripts/check-no-self-dep.mjs",
|
|
78
|
+
lint: "npm run check:deps && biome check . && tsc --noEmit",
|
|
80
79
|
format: "biome format --write .",
|
|
81
80
|
test: "vitest run",
|
|
82
81
|
"test:cover": "vitest run --coverage",
|
|
@@ -85,12 +84,12 @@ var package_default = {
|
|
|
85
84
|
},
|
|
86
85
|
dependencies: {
|
|
87
86
|
"@clack/prompts": "^0.9.1",
|
|
88
|
-
"@openbkn/bkn-sdk": "^0.1.1-alpha.3",
|
|
89
87
|
chalk: "^5.4.1",
|
|
90
88
|
commander: "^13.1.0",
|
|
91
89
|
"csv-parse": "^6.2.1",
|
|
92
90
|
"js-yaml": "^4.2.0",
|
|
93
91
|
jszip: "^3.10.1",
|
|
92
|
+
undici: "^8.7.0",
|
|
94
93
|
zod: "^3.24.1"
|
|
95
94
|
},
|
|
96
95
|
devDependencies: {
|
|
@@ -104,6 +103,7 @@ var package_default = {
|
|
|
104
103
|
};
|
|
105
104
|
|
|
106
105
|
// src/commands/admin.ts
|
|
106
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
107
107
|
import { Command as Command2 } from "commander";
|
|
108
108
|
|
|
109
109
|
// src/help/grouped-help.ts
|
|
@@ -215,7 +215,8 @@ var ROW_ENVELOPES = [
|
|
|
215
215
|
"users",
|
|
216
216
|
"roles",
|
|
217
217
|
"departments",
|
|
218
|
-
"members"
|
|
218
|
+
"members",
|
|
219
|
+
"keys"
|
|
219
220
|
];
|
|
220
221
|
function toRows(value) {
|
|
221
222
|
const isRowArray = (v) => Array.isArray(v) && v.length > 0 && v.every((x) => x !== null && typeof x === "object" && !Array.isArray(x));
|
|
@@ -300,6 +301,25 @@ function stringifyCell(v) {
|
|
|
300
301
|
return s.length > CELL_MAX ? `${s.slice(0, CELL_MAX - 1)}\u2026` : s;
|
|
301
302
|
}
|
|
302
303
|
|
|
304
|
+
// src/utils/prompt.ts
|
|
305
|
+
import { createInterface } from "readline";
|
|
306
|
+
function promptLine(query, hidden = false) {
|
|
307
|
+
return new Promise((resolve2) => {
|
|
308
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
309
|
+
if (hidden) {
|
|
310
|
+
const mutable = rl;
|
|
311
|
+
mutable._writeToOutput = (s) => {
|
|
312
|
+
if (s.startsWith(query)) process.stdout.write(query);
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
rl.question(query, (answer) => {
|
|
316
|
+
rl.close();
|
|
317
|
+
if (hidden) process.stdout.write("\n");
|
|
318
|
+
resolve2(answer.trim());
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
303
323
|
// src/commands/_shared.ts
|
|
304
324
|
import { readFileSync } from "fs";
|
|
305
325
|
function clientFrom(cmd) {
|
|
@@ -331,27 +351,7 @@ function readBody(opts) {
|
|
|
331
351
|
}
|
|
332
352
|
|
|
333
353
|
// src/commands/auth.ts
|
|
334
|
-
import { createInterface } from "readline";
|
|
335
354
|
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
355
|
async function resolveAccount(baseUrl, accessToken, insecure, idToken) {
|
|
356
356
|
const sub = decodeJwt(idToken ?? accessToken)?.sub;
|
|
357
357
|
if (!sub) return void 0;
|
|
@@ -365,22 +365,6 @@ async function resolveAccount(baseUrl, accessToken, insecure, idToken) {
|
|
|
365
365
|
return void 0;
|
|
366
366
|
}
|
|
367
367
|
}
|
|
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
368
|
function renderSessions(items) {
|
|
385
369
|
const byPlatform = /* @__PURE__ */ new Map();
|
|
386
370
|
for (const it of items) {
|
|
@@ -396,25 +380,17 @@ function renderSessions(items) {
|
|
|
396
380
|
return lines.join("\n") || "(no saved sessions)";
|
|
397
381
|
}
|
|
398
382
|
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(
|
|
383
|
+
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
384
|
"--timeout <s>",
|
|
405
385
|
"device-login wait before timing out",
|
|
406
386
|
(v) => Number.parseInt(v, 10),
|
|
407
387
|
120
|
|
408
|
-
).option("--no-browser", "
|
|
388
|
+
).option("--no-browser", "print the URL instead of opening a browser").action(async (url, opts, cmd2) => {
|
|
409
389
|
const g = cmd2.optsWithGlobals();
|
|
410
|
-
if (g.insecure) process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
411
390
|
const out = outputOptions(cmd2);
|
|
412
391
|
const report = (r) => {
|
|
413
392
|
if (out.json || out.compact) {
|
|
414
393
|
printJson({ loggedIn: true, ...r }, out);
|
|
415
|
-
} else if (r.noAuth) {
|
|
416
|
-
process.stdout.write(`Registered ${r.baseUrl ?? url} (no authentication)
|
|
417
|
-
`);
|
|
418
394
|
} else {
|
|
419
395
|
process.stdout.write(`Logged in to ${r.baseUrl ?? url} as ${r.username ?? r.userId}
|
|
420
396
|
`);
|
|
@@ -425,19 +401,6 @@ function registerAuthLeaves(cmd) {
|
|
|
425
401
|
report(attachToken(url, token, { insecure: g.insecure }));
|
|
426
402
|
return;
|
|
427
403
|
}
|
|
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
404
|
let tokens;
|
|
442
405
|
let account;
|
|
443
406
|
try {
|
|
@@ -448,7 +411,8 @@ function registerAuthLeaves(cmd) {
|
|
|
448
411
|
tokens = await credentialDeviceLogin(url, username, password, {
|
|
449
412
|
clientId: opts.clientId,
|
|
450
413
|
audience: opts.audience,
|
|
451
|
-
timeoutMs: opts.timeout * 1e3
|
|
414
|
+
timeoutMs: opts.timeout * 1e3,
|
|
415
|
+
insecure: g.insecure
|
|
452
416
|
});
|
|
453
417
|
} else {
|
|
454
418
|
const headless = isHeadless();
|
|
@@ -457,6 +421,7 @@ function registerAuthLeaves(cmd) {
|
|
|
457
421
|
clientId: opts.clientId,
|
|
458
422
|
audience: opts.audience,
|
|
459
423
|
timeoutMs: opts.timeout * 1e3,
|
|
424
|
+
insecure: g.insecure,
|
|
460
425
|
onPrompt: ({ userCode, verificationUri, verificationUriComplete }) => {
|
|
461
426
|
const target = verificationUriComplete ?? verificationUri;
|
|
462
427
|
process.stderr.write(
|
|
@@ -475,9 +440,9 @@ User code: ${userCode}
|
|
|
475
440
|
}
|
|
476
441
|
} catch (e) {
|
|
477
442
|
if (e instanceof Error && /Device auth failed \(404\)/.test(e.message)) {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
443
|
+
throw new InputError(
|
|
444
|
+
`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\`.`
|
|
445
|
+
);
|
|
481
446
|
}
|
|
482
447
|
throw e;
|
|
483
448
|
}
|
|
@@ -493,29 +458,29 @@ User code: ${userCode}
|
|
|
493
458
|
attachToken(url, tokens.accessToken, {
|
|
494
459
|
refreshToken: tokens.refreshToken,
|
|
495
460
|
idToken: tokens.idToken,
|
|
496
|
-
|
|
497
|
-
|
|
461
|
+
username: account,
|
|
462
|
+
insecure: g.insecure
|
|
498
463
|
})
|
|
499
464
|
);
|
|
500
465
|
});
|
|
501
|
-
cmd.command("status").description("Show base URL and whether a token is configured").action(
|
|
466
|
+
cmd.command("status").description("Show base URL and whether a token is configured").action(
|
|
467
|
+
(_opts, cmd2) => printJson(status({ user: cmd2.optsWithGlobals().user }), outputOptions(cmd2))
|
|
468
|
+
);
|
|
502
469
|
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
470
|
const g = cmd2.optsWithGlobals();
|
|
504
|
-
|
|
505
|
-
const token = opts.refresh === false ? currentToken() : await currentTokenFresh();
|
|
471
|
+
const token = opts.refresh === false ? currentToken({ user: g.user }) : await currentTokenFresh({ insecure: g.insecure, user: g.user });
|
|
506
472
|
process.stdout.write(`${token}
|
|
507
473
|
`);
|
|
508
474
|
});
|
|
509
475
|
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
476
|
const g = cmd2.optsWithGlobals();
|
|
511
|
-
|
|
512
|
-
const me = whoami();
|
|
477
|
+
const me = whoami({ user: g.user });
|
|
513
478
|
if (opts.lookup !== false && me.baseUrl && me.sub) {
|
|
514
479
|
try {
|
|
515
480
|
const u = await getUserSafe(
|
|
516
481
|
{
|
|
517
482
|
baseUrl: me.baseUrl,
|
|
518
|
-
token: currentToken(),
|
|
483
|
+
token: currentToken({ user: g.user }),
|
|
519
484
|
businessDomain: DEFAULT_BUSINESS_DOMAIN,
|
|
520
485
|
insecure: Boolean(g.insecure)
|
|
521
486
|
},
|
|
@@ -580,9 +545,8 @@ User code: ${userCode}
|
|
|
580
545
|
cmd.command("export").description("Export the active session's tokens (for a headless host)").action((_opts, cmd2) => {
|
|
581
546
|
printJson(exportCreds(), outputOptions(cmd2));
|
|
582
547
|
});
|
|
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").
|
|
548
|
+
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
549
|
const g = cmd2.optsWithGlobals();
|
|
585
|
-
if (g.insecure) process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
586
550
|
const ctx = resolveContext({
|
|
587
551
|
baseUrl: url ?? g.baseUrl,
|
|
588
552
|
token: g.token,
|
|
@@ -623,10 +587,14 @@ function authCommand() {
|
|
|
623
587
|
// src/commands/admin.ts
|
|
624
588
|
var int = (v) => Number.parseInt(v, 10);
|
|
625
589
|
var DEFAULT_RESET_PASSWORD = "openbkn";
|
|
590
|
+
async function importLicenseFile(cmd, file, receipt) {
|
|
591
|
+
const text = readFileSync2(file, "utf8");
|
|
592
|
+
const res = await clientFrom(cmd).admin.licenseImport(text, { receipt });
|
|
593
|
+
printJson(res, outputOptions(cmd));
|
|
594
|
+
if ("stored" in res && res.stored) process.exitCode = 1;
|
|
595
|
+
}
|
|
626
596
|
function adminCommand() {
|
|
627
|
-
const admin = new Command2("admin").description(
|
|
628
|
-
"Operator CLI (kweaver-admin): org, user, role, models, audit"
|
|
629
|
-
);
|
|
597
|
+
const admin = new Command2("admin").description("Operator CLI: org, user, role, models, audit");
|
|
630
598
|
registerAuthLeaves(admin.command("auth").description("Operator authentication"));
|
|
631
599
|
const org = admin.command("org").description("Departments and org structure");
|
|
632
600
|
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 +723,19 @@ function adminCommand() {
|
|
|
755
723
|
user.command("delete <id>").description("Delete a user").action(async (id, _opts, cmd) => {
|
|
756
724
|
printJson(await clientFrom(cmd).admin.userDelete(id), outputOptions(cmd));
|
|
757
725
|
});
|
|
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) => {
|
|
726
|
+
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
727
|
const userId = id ?? opts.id ?? opts.user;
|
|
760
728
|
if (!userId) throw new Error("Provide a user id (positional or --id).");
|
|
761
|
-
|
|
729
|
+
let explicit = opts.password ?? opts.newPassword;
|
|
730
|
+
if (!explicit && opts.promptPassword) {
|
|
731
|
+
explicit = await promptLine("New password: ", true);
|
|
732
|
+
if (!explicit) throw new InputError("No password entered.");
|
|
733
|
+
}
|
|
734
|
+
const pwd = explicit ?? DEFAULT_RESET_PASSWORD;
|
|
762
735
|
const r = await clientFrom(cmd).admin.userResetPassword(userId, pwd);
|
|
763
736
|
const out = outputOptions(cmd);
|
|
764
737
|
if (out.json || out.compact) printJson(r, out);
|
|
765
|
-
else if (
|
|
766
|
-
process.stdout.write(`Password reset for ${userId}.
|
|
738
|
+
else if (explicit) process.stdout.write(`Password reset for ${userId}.
|
|
767
739
|
`);
|
|
768
740
|
else
|
|
769
741
|
process.stdout.write(
|
|
@@ -906,6 +878,27 @@ function adminCommand() {
|
|
|
906
878
|
);
|
|
907
879
|
});
|
|
908
880
|
}
|
|
881
|
+
const license = admin.command("license").description("Cluster license management");
|
|
882
|
+
license.command("show").description("Current license detail (state/edition/expiry/features)").action(async (_opts, cmd) => {
|
|
883
|
+
printJson(await clientFrom(cmd).admin.licenseGet(), outputOptions(cmd));
|
|
884
|
+
});
|
|
885
|
+
license.command("import <file>").description("Import a .lic license file (online deployments auto-activate)").action(async (file, _opts, cmd) => {
|
|
886
|
+
await importLicenseFile(cmd, file, false);
|
|
887
|
+
});
|
|
888
|
+
license.command("receipt <file>").description("Import an offline activation receipt (.lic from the license portal)").action(async (file, _opts, cmd) => {
|
|
889
|
+
await importLicenseFile(cmd, file, true);
|
|
890
|
+
});
|
|
891
|
+
license.command("activate").description("Report the installed license to the issuer (online deployments)").action(async (_opts, cmd) => {
|
|
892
|
+
printJson(await clientFrom(cmd).admin.licenseActivate(), outputOptions(cmd));
|
|
893
|
+
});
|
|
894
|
+
license.command("remove").description("Remove the installed license (back to unactivated)").action(async (_opts, cmd) => {
|
|
895
|
+
printJson(await clientFrom(cmd).admin.licenseRemove(), outputOptions(cmd));
|
|
896
|
+
});
|
|
897
|
+
license.command("fingerprint").description(
|
|
898
|
+
"This cluster's machine code (paste into the license portal for offline activation)"
|
|
899
|
+
).action(async (_opts, cmd) => {
|
|
900
|
+
printJson(await clientFrom(cmd).admin.licenseFingerprint(), outputOptions(cmd));
|
|
901
|
+
});
|
|
909
902
|
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
903
|
printJson(
|
|
911
904
|
await clientFrom(cmd).admin.auditList({
|
|
@@ -966,7 +959,14 @@ function adminCommand() {
|
|
|
966
959
|
import { Command as Command3 } from "commander";
|
|
967
960
|
var int2 = (v) => Number.parseInt(v, 10);
|
|
968
961
|
function agentCommand() {
|
|
969
|
-
const cmd = new Command3("agent").description(
|
|
962
|
+
const cmd = new Command3("agent").description(
|
|
963
|
+
"[DEPRECATED] Decision Agent \u2014 CRUD, chat, sessions, publish (being phased out)"
|
|
964
|
+
);
|
|
965
|
+
cmd.hook("preAction", () => {
|
|
966
|
+
process.stderr.write(
|
|
967
|
+
"\u26A0\uFE0F `openbkn agent` is deprecated and may be removed in a future release.\n"
|
|
968
|
+
);
|
|
969
|
+
});
|
|
970
970
|
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
971
|
const data = await clientFrom(cmd2).agents.list({
|
|
972
972
|
name: opts.name,
|
|
@@ -1068,11 +1068,78 @@ function agentCommand() {
|
|
|
1068
1068
|
return group(cmd, "DECISION AGENT");
|
|
1069
1069
|
}
|
|
1070
1070
|
|
|
1071
|
-
// src/commands/
|
|
1071
|
+
// src/commands/appkey.ts
|
|
1072
1072
|
import { Command as Command4 } from "commander";
|
|
1073
|
+
var int3 = (v) => Number.parseInt(v, 10);
|
|
1074
|
+
var DAY_MS = 864e5;
|
|
1075
|
+
function printNewKey(created, out) {
|
|
1076
|
+
if (out.json || out.compact) {
|
|
1077
|
+
printJson(created, out);
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
process.stderr.write(
|
|
1081
|
+
"\u26A0\uFE0F Copy this key now \u2014 the plaintext is shown only once and cannot be retrieved again.\n\n"
|
|
1082
|
+
);
|
|
1083
|
+
const fields = [
|
|
1084
|
+
["key", created.key],
|
|
1085
|
+
["name", created.name],
|
|
1086
|
+
["id", `${created.id} (use this to revoke/regenerate)`],
|
|
1087
|
+
["key_id", created.key_id],
|
|
1088
|
+
["expires_at", created.expires_at ?? "never"]
|
|
1089
|
+
];
|
|
1090
|
+
const w = Math.max(...fields.map(([k]) => k.length));
|
|
1091
|
+
for (const [k, v] of fields) process.stdout.write(` ${k.padEnd(w)} ${v}
|
|
1092
|
+
`);
|
|
1093
|
+
}
|
|
1094
|
+
function appkeyCommand() {
|
|
1095
|
+
const appkey = new Command4("appkey").description(
|
|
1096
|
+
"AppKeys \u2014 user-issued long-lived credentials (bak_) for the Context Loader"
|
|
1097
|
+
);
|
|
1098
|
+
appkey.command("list").description("List your own AppKeys (no secrets)").action(async (_opts, cmd) => {
|
|
1099
|
+
printJson(await clientFrom(cmd).appKeys.list(), outputOptions(cmd));
|
|
1100
|
+
});
|
|
1101
|
+
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) => {
|
|
1102
|
+
let expiresAt = opts.expiresAt;
|
|
1103
|
+
if (opts.expireDays !== void 0) {
|
|
1104
|
+
if (!Number.isFinite(opts.expireDays) || opts.expireDays <= 0) {
|
|
1105
|
+
throw new InputError("--expire-days must be a positive integer.");
|
|
1106
|
+
}
|
|
1107
|
+
if (expiresAt) {
|
|
1108
|
+
throw new InputError("Use either --expires-at or --expire-days, not both.");
|
|
1109
|
+
}
|
|
1110
|
+
expiresAt = new Date(Date.now() + opts.expireDays * DAY_MS).toISOString();
|
|
1111
|
+
}
|
|
1112
|
+
const created = await clientFrom(cmd).appKeys.create({
|
|
1113
|
+
name: opts.name,
|
|
1114
|
+
expiresAt,
|
|
1115
|
+
neverExpire: Boolean(opts.neverExpire)
|
|
1116
|
+
});
|
|
1117
|
+
printNewKey(created, outputOptions(cmd));
|
|
1118
|
+
});
|
|
1119
|
+
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) => {
|
|
1120
|
+
const created = await clientFrom(cmd).appKeys.regenerate(id);
|
|
1121
|
+
printNewKey(created, outputOptions(cmd));
|
|
1122
|
+
});
|
|
1123
|
+
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) => {
|
|
1124
|
+
await clientFrom(cmd).appKeys.revoke(id);
|
|
1125
|
+
printJson({ revoked: id }, outputOptions(cmd));
|
|
1126
|
+
});
|
|
1127
|
+
const admin = appkey.command("admin").description("Admin governance over all AppKeys");
|
|
1128
|
+
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) => {
|
|
1129
|
+
printJson(await clientFrom(cmd).appKeys.adminList(opts.ownerId), outputOptions(cmd));
|
|
1130
|
+
});
|
|
1131
|
+
admin.command("revoke <id>").alias("delete").alias("rm").description("Revoke any AppKey by id").action(async (id, _opts, cmd) => {
|
|
1132
|
+
await clientFrom(cmd).appKeys.adminRevoke(id);
|
|
1133
|
+
printJson({ revoked: id }, outputOptions(cmd));
|
|
1134
|
+
});
|
|
1135
|
+
return group(appkey, "AUTHENTICATION & CONFIG");
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
// src/commands/bkn.ts
|
|
1139
|
+
import { Command as Command5 } from "commander";
|
|
1073
1140
|
|
|
1074
1141
|
// src/utils/bkn-validate.ts
|
|
1075
|
-
import { existsSync, readFileSync as
|
|
1142
|
+
import { existsSync, readFileSync as readFileSync3, readdirSync, statSync } from "fs";
|
|
1076
1143
|
import { join, resolve } from "path";
|
|
1077
1144
|
var BKN_OBJECT_NAME_MAX_LENGTH = 40;
|
|
1078
1145
|
function parseFrontmatter(text) {
|
|
@@ -1125,7 +1192,7 @@ function validateBknDirectory(dirPath) {
|
|
|
1125
1192
|
if (!existsSync(networkPath)) {
|
|
1126
1193
|
errors.push("Missing network.bkn at the BKN root.");
|
|
1127
1194
|
} else {
|
|
1128
|
-
const fm = parseFrontmatter(
|
|
1195
|
+
const fm = parseFrontmatter(readFileSync3(networkPath, "utf8"));
|
|
1129
1196
|
if (!fm) errors.push("network.bkn has no frontmatter block.");
|
|
1130
1197
|
else {
|
|
1131
1198
|
if (fm.type !== "knowledge_network")
|
|
@@ -1137,7 +1204,7 @@ function validateBknDirectory(dirPath) {
|
|
|
1137
1204
|
const otIds = /* @__PURE__ */ new Set();
|
|
1138
1205
|
const otFiles = bknFiles(join(dir, "object_types"));
|
|
1139
1206
|
for (const file of otFiles) {
|
|
1140
|
-
const fm = parseFrontmatter(
|
|
1207
|
+
const fm = parseFrontmatter(readFileSync3(file, "utf8"));
|
|
1141
1208
|
const rel = file.slice(dir.length + 1);
|
|
1142
1209
|
if (!fm || fm.type !== "object_type") {
|
|
1143
1210
|
errors.push(`${rel}: not a valid object_type (missing/wrong frontmatter type).`);
|
|
@@ -1157,7 +1224,7 @@ function validateBknDirectory(dirPath) {
|
|
|
1157
1224
|
}
|
|
1158
1225
|
const rtFiles = bknFiles(join(dir, "relation_types"));
|
|
1159
1226
|
for (const file of rtFiles) {
|
|
1160
|
-
const text =
|
|
1227
|
+
const text = readFileSync3(file, "utf8");
|
|
1161
1228
|
const fm = parseFrontmatter(text);
|
|
1162
1229
|
const rel = file.slice(dir.length + 1);
|
|
1163
1230
|
if (!fm || fm.type !== "relation_type") {
|
|
@@ -1187,10 +1254,10 @@ function validateBknDirectory(dirPath) {
|
|
|
1187
1254
|
}
|
|
1188
1255
|
|
|
1189
1256
|
// src/commands/bkn.ts
|
|
1190
|
-
var
|
|
1257
|
+
var int4 = (v) => Number.parseInt(v, 10);
|
|
1191
1258
|
function bknCommand() {
|
|
1192
|
-
const bkn = new
|
|
1193
|
-
bkn.command("list").description("List knowledge networks").option("--limit <n>", "page size",
|
|
1259
|
+
const bkn = new Command5("bkn").description("Knowledge networks \u2014 list, query, schema, instances");
|
|
1260
|
+
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
1261
|
const o = cmd.optsWithGlobals();
|
|
1195
1262
|
const data = await clientFrom(cmd).kn.list({
|
|
1196
1263
|
limit: o.limit,
|
|
@@ -1209,7 +1276,7 @@ function bknCommand() {
|
|
|
1209
1276
|
});
|
|
1210
1277
|
printJson(data, outputOptions(cmd));
|
|
1211
1278
|
});
|
|
1212
|
-
bkn.command("search <kn-id> <query>").description("Semantic search within a knowledge network").option("--max-concepts <n>", "max concepts to return",
|
|
1279
|
+
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
1280
|
const data = await clientFrom(cmd).kn.search(knId, query, {
|
|
1214
1281
|
maxConcepts: opts.maxConcepts,
|
|
1215
1282
|
mode: opts.mode
|
|
@@ -1298,7 +1365,7 @@ function bknCommand() {
|
|
|
1298
1365
|
printJson(await clientFrom(cmd).kn.subgraph(knId, readBody(opts)), outputOptions(cmd));
|
|
1299
1366
|
});
|
|
1300
1367
|
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",
|
|
1368
|
+
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
1369
|
printJson(
|
|
1303
1370
|
await clientFrom(cmd).kn.actionLogs(knId, {
|
|
1304
1371
|
status: opts.status,
|
|
@@ -1478,7 +1545,7 @@ function bknCommand() {
|
|
|
1478
1545
|
printJson(result, outputOptions(cmd));
|
|
1479
1546
|
if (!result.valid) process.exitCode = 1;
|
|
1480
1547
|
});
|
|
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",
|
|
1548
|
+
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
1549
|
"--embedding-fields <map>",
|
|
1483
1550
|
"columns to vectorize per table (with --build): '<table>:<col>[+<col>...][,...]'"
|
|
1484
1551
|
).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,13 +1571,13 @@ function bknCommand() {
|
|
|
1504
1571
|
}
|
|
1505
1572
|
|
|
1506
1573
|
// src/commands/call.ts
|
|
1507
|
-
import { Command as
|
|
1574
|
+
import { Command as Command6 } from "commander";
|
|
1508
1575
|
function collect(value, prev) {
|
|
1509
1576
|
prev.push(value);
|
|
1510
1577
|
return prev;
|
|
1511
1578
|
}
|
|
1512
1579
|
function callCommand() {
|
|
1513
|
-
const cmd = new
|
|
1580
|
+
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
1581
|
"-F, --form <field>",
|
|
1515
1582
|
"multipart field key=value or key=@file (repeatable)",
|
|
1516
1583
|
collect,
|
|
@@ -1545,14 +1612,14 @@ function callCommand() {
|
|
|
1545
1612
|
}
|
|
1546
1613
|
|
|
1547
1614
|
// src/commands/config.ts
|
|
1548
|
-
import { Command as
|
|
1615
|
+
import { Command as Command7 } from "commander";
|
|
1549
1616
|
function requireActive() {
|
|
1550
1617
|
const baseUrl = activePlatform();
|
|
1551
1618
|
if (!baseUrl) throw new InputError("No active platform. Run `openbkn auth login <url>` first.");
|
|
1552
1619
|
return baseUrl;
|
|
1553
1620
|
}
|
|
1554
1621
|
function configCommand() {
|
|
1555
|
-
const config = new
|
|
1622
|
+
const config = new Command7("config").description("Per-platform CLI configuration");
|
|
1556
1623
|
config.command("show").description("Show the active platform and business domain").action((_opts, cmd) => {
|
|
1557
1624
|
const baseUrl = activePlatform();
|
|
1558
1625
|
printJson(
|
|
@@ -1585,13 +1652,56 @@ function configCommand() {
|
|
|
1585
1652
|
}
|
|
1586
1653
|
|
|
1587
1654
|
// src/commands/context.ts
|
|
1588
|
-
import { Command as
|
|
1589
|
-
var
|
|
1655
|
+
import { Command as Command8 } from "commander";
|
|
1656
|
+
var int5 = (v) => Number.parseInt(v, 10);
|
|
1657
|
+
var collectArg = (v, prev) => {
|
|
1658
|
+
prev.push(v);
|
|
1659
|
+
return prev;
|
|
1660
|
+
};
|
|
1661
|
+
function buildArgs(opts) {
|
|
1662
|
+
let out = {};
|
|
1663
|
+
if (opts.args) {
|
|
1664
|
+
try {
|
|
1665
|
+
out = JSON.parse(opts.args);
|
|
1666
|
+
} catch {
|
|
1667
|
+
throw new InputError("--args must be valid JSON");
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
for (const pair of opts.arg ?? []) {
|
|
1671
|
+
const idx = pair.indexOf("=");
|
|
1672
|
+
if (idx <= 0) throw new InputError(`--arg must be key=value (got: ${pair})`);
|
|
1673
|
+
const key = pair.slice(0, idx);
|
|
1674
|
+
const raw = pair.slice(idx + 1);
|
|
1675
|
+
try {
|
|
1676
|
+
out[key] = JSON.parse(raw);
|
|
1677
|
+
} catch {
|
|
1678
|
+
out[key] = raw;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
return out;
|
|
1682
|
+
}
|
|
1683
|
+
function printToolList(res, out) {
|
|
1684
|
+
if (out.json || out.compact) {
|
|
1685
|
+
printJson(res, out);
|
|
1686
|
+
return;
|
|
1687
|
+
}
|
|
1688
|
+
const r = res ?? {};
|
|
1689
|
+
const arr = [res, r.tools, r.result?.tools, r.data].find(Array.isArray);
|
|
1690
|
+
if (!arr) {
|
|
1691
|
+
printJson(res, out);
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
const rows = arr.map((t) => ({
|
|
1695
|
+
name: t.name ?? t.tool_name ?? t.key ?? "",
|
|
1696
|
+
description: typeof t.description === "string" ? t.description : ""
|
|
1697
|
+
}));
|
|
1698
|
+
printJson(rows, out);
|
|
1699
|
+
}
|
|
1590
1700
|
function contextCommand() {
|
|
1591
|
-
const cmd = new
|
|
1701
|
+
const cmd = new Command8("context").description(
|
|
1592
1702
|
"Context loader (MCP) \u2014 schema discovery, instance query, skill recall"
|
|
1593
1703
|
);
|
|
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",
|
|
1704
|
+
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
1705
|
const data = await clientFrom(cmd2).context.searchSchema(knId, query, {
|
|
1596
1706
|
searchScope: opts.scope ? String(opts.scope).split(",") : void 0,
|
|
1597
1707
|
maxConcepts: opts.max
|
|
@@ -1607,23 +1717,51 @@ function contextCommand() {
|
|
|
1607
1717
|
}
|
|
1608
1718
|
printJson(await clientFrom(cmd2).context.queryObjectInstance(knId, args), outputOptions(cmd2));
|
|
1609
1719
|
});
|
|
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)",
|
|
1720
|
+
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
1721
|
printJson(
|
|
1612
1722
|
await clientFrom(cmd2).context.findSkills(knId, otId, opts.topK),
|
|
1613
1723
|
outputOptions(cmd2)
|
|
1614
1724
|
);
|
|
1615
1725
|
});
|
|
1616
|
-
cmd.command("
|
|
1617
|
-
|
|
1726
|
+
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) => {
|
|
1727
|
+
const level = opts.detailLevel === "full" ? "full" : "summary";
|
|
1728
|
+
printJson(await clientFrom(cmd2).context.knDetail(knId, level), outputOptions(cmd2));
|
|
1618
1729
|
});
|
|
1619
|
-
cmd.command("
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1730
|
+
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) => {
|
|
1731
|
+
printJson(await clientFrom(cmd2).context.objectTypes(knId, ids), outputOptions(cmd2));
|
|
1732
|
+
});
|
|
1733
|
+
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) => {
|
|
1734
|
+
printJson(await clientFrom(cmd2).context.relationTypes(knId, ids), outputOptions(cmd2));
|
|
1735
|
+
});
|
|
1736
|
+
cmd.command("info").description("List the deploy's MCP tool catalog (global \u2014 no KN needed)").action(async (_opts, cmd2) => {
|
|
1737
|
+
printToolList(await clientFrom(cmd2).context.info(), outputOptions(cmd2));
|
|
1738
|
+
});
|
|
1739
|
+
cmd.command("tools <kn-id>").description("List MCP tools advertised for a KN session").action(async (knId, _opts, cmd2) => {
|
|
1740
|
+
printToolList(await clientFrom(cmd2).context.tools(knId), outputOptions(cmd2));
|
|
1741
|
+
});
|
|
1742
|
+
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(
|
|
1743
|
+
"--arg <key=value>",
|
|
1744
|
+
"one argument (repeatable; value parsed as JSON, else string)",
|
|
1745
|
+
collectArg,
|
|
1746
|
+
[]
|
|
1747
|
+
).action(async (knId, name, opts, cmd2) => {
|
|
1748
|
+
printJson(
|
|
1749
|
+
await clientFrom(cmd2).context.toolCall(knId, name, buildArgs(opts)),
|
|
1750
|
+
outputOptions(cmd2)
|
|
1751
|
+
);
|
|
1752
|
+
});
|
|
1753
|
+
cmd.command("call-method <kn-id> <method>").description(
|
|
1754
|
+
"Call any MCP method by name (e.g. tools/list, resources/read) \u2014 current or future"
|
|
1755
|
+
).option("--args <json>", "method params as JSON").option(
|
|
1756
|
+
"--arg <key=value>",
|
|
1757
|
+
"one param (repeatable; value parsed as JSON, else string)",
|
|
1758
|
+
collectArg,
|
|
1759
|
+
[]
|
|
1760
|
+
).action(async (knId, method, opts, cmd2) => {
|
|
1761
|
+
printJson(
|
|
1762
|
+
await clientFrom(cmd2).context.callMethod(knId, method, buildArgs(opts)),
|
|
1763
|
+
outputOptions(cmd2)
|
|
1764
|
+
);
|
|
1627
1765
|
});
|
|
1628
1766
|
cmd.command("resources <kn-id>").description("List MCP resources").action(async (knId, _opts, cmd2) => {
|
|
1629
1767
|
printJson(await clientFrom(cmd2).context.resources(knId), outputOptions(cmd2));
|
|
@@ -1655,19 +1793,19 @@ function contextCommand() {
|
|
|
1655
1793
|
throw new InputError("--args must be valid JSON");
|
|
1656
1794
|
}
|
|
1657
1795
|
};
|
|
1658
|
-
cmd.command("query-instance-subgraph <kn-id>").description("
|
|
1796
|
+
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
1797
|
printJson(
|
|
1660
1798
|
await clientFrom(cmd2).context.queryInstanceSubgraph(knId, jsonArgs(opts.args)),
|
|
1661
1799
|
outputOptions(cmd2)
|
|
1662
1800
|
);
|
|
1663
1801
|
});
|
|
1664
|
-
cmd.command("get-logic-properties <kn-id>").description("
|
|
1802
|
+
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
1803
|
printJson(
|
|
1666
1804
|
await clientFrom(cmd2).context.logicProperties(knId, jsonArgs(opts.args)),
|
|
1667
1805
|
outputOptions(cmd2)
|
|
1668
1806
|
);
|
|
1669
1807
|
});
|
|
1670
|
-
cmd.command("get-action-info <kn-id>").description("
|
|
1808
|
+
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
1809
|
printJson(
|
|
1672
1810
|
await clientFrom(cmd2).context.actionInfo(knId, jsonArgs(opts.args)),
|
|
1673
1811
|
outputOptions(cmd2)
|
|
@@ -1677,10 +1815,10 @@ function contextCommand() {
|
|
|
1677
1815
|
}
|
|
1678
1816
|
|
|
1679
1817
|
// src/commands/dataflow.ts
|
|
1680
|
-
import { Command as
|
|
1681
|
-
var
|
|
1818
|
+
import { Command as Command9 } from "commander";
|
|
1819
|
+
var int6 = (v) => Number.parseInt(v, 10);
|
|
1682
1820
|
function dataflowCommand() {
|
|
1683
|
-
const cmd = new
|
|
1821
|
+
const cmd = new Command9("dataflow").description("Dataflow document workflows \u2014 list, runs, logs");
|
|
1684
1822
|
cmd.command("list").description("List all dataflows").action(async (_opts, cmd2) => {
|
|
1685
1823
|
printJson(await clientFrom(cmd2).dataflows.list(), outputOptions(cmd2));
|
|
1686
1824
|
});
|
|
@@ -1690,7 +1828,7 @@ function dataflowCommand() {
|
|
|
1690
1828
|
outputOptions(cmd2)
|
|
1691
1829
|
);
|
|
1692
1830
|
});
|
|
1693
|
-
cmd.command("logs <dagId> <instanceId>").description("Show logs for one run").option("--page <n>", "page",
|
|
1831
|
+
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
1832
|
printJson(
|
|
1695
1833
|
await clientFrom(cmd2).dataflows.logs(dagId, instanceId, {
|
|
1696
1834
|
page: opts.page,
|
|
@@ -1752,8 +1890,8 @@ function dataflowCommand() {
|
|
|
1752
1890
|
|
|
1753
1891
|
// src/commands/explore.ts
|
|
1754
1892
|
import { createServer } from "http";
|
|
1755
|
-
import { Command as
|
|
1756
|
-
var
|
|
1893
|
+
import { Command as Command10 } from "commander";
|
|
1894
|
+
var int7 = (v) => Number.parseInt(v, 10);
|
|
1757
1895
|
var ROUTES = {
|
|
1758
1896
|
"GET /api/bkn/meta": (c, q) => c.kn.get(req(q, "knId")),
|
|
1759
1897
|
"POST /api/bkn/search": (c, _q, b) => c.kn.search(str(b.knId), str(b.query), {
|
|
@@ -1798,10 +1936,10 @@ var INDEX = `<!doctype html><meta charset="utf-8"><title>openbkn explore</title>
|
|
|
1798
1936
|
<p>Read-only JSON endpoints for bkn + vega:</p>
|
|
1799
1937
|
<ul>${Object.keys(ROUTES).map((r) => `<li><code>${r}</code></li>`).join("")}</ul>`;
|
|
1800
1938
|
function exploreCommand() {
|
|
1801
|
-
const cmd = new
|
|
1939
|
+
const cmd = new Command10("explore").description(
|
|
1802
1940
|
"Start a local web server with read-only bkn + vega JSON endpoints"
|
|
1803
1941
|
);
|
|
1804
|
-
cmd.option("--port <n>", "port to listen on",
|
|
1942
|
+
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
1943
|
const client = clientFrom(command);
|
|
1806
1944
|
const server = createServer((reqMsg, res) => {
|
|
1807
1945
|
void handle(client, reqMsg, res);
|
|
@@ -1839,8 +1977,14 @@ async function handle(client, reqMsg, res) {
|
|
|
1839
1977
|
}
|
|
1840
1978
|
|
|
1841
1979
|
// src/commands/model.ts
|
|
1842
|
-
import { Command as
|
|
1843
|
-
var
|
|
1980
|
+
import { Command as Command11 } from "commander";
|
|
1981
|
+
var int8 = (v) => Number.parseInt(v, 10);
|
|
1982
|
+
async function resolveLlmModelName(client, model) {
|
|
1983
|
+
if (!/^\d+$/.test(model)) return model;
|
|
1984
|
+
const detail = await client.models.llm.get(model);
|
|
1985
|
+
if (!detail?.model_name) throw new InputError(`No LLM found with id ${model}.`);
|
|
1986
|
+
return detail.model_name;
|
|
1987
|
+
}
|
|
1844
1988
|
function addManagementCommands(parent, kind) {
|
|
1845
1989
|
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
1990
|
printJson(await clientFrom(cmd).models[kind].add(readBody(opts)), outputOptions(cmd));
|
|
@@ -1856,9 +2000,11 @@ function addManagementCommands(parent, kind) {
|
|
|
1856
2000
|
});
|
|
1857
2001
|
}
|
|
1858
2002
|
function modelCommand() {
|
|
1859
|
-
const model = new
|
|
2003
|
+
const model = new Command11("model").description(
|
|
2004
|
+
"Model factory \u2014 LLM / small-model CRUD, chat / embeddings / rerank, default selection"
|
|
2005
|
+
);
|
|
1860
2006
|
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",
|
|
2007
|
+
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
2008
|
printJson(
|
|
1863
2009
|
await clientFrom(cmd).models.llm.list({
|
|
1864
2010
|
name: opts.name,
|
|
@@ -1872,18 +2018,26 @@ function modelCommand() {
|
|
|
1872
2018
|
llm.command("get <modelId>").description("Get an LLM model").action(async (id, _opts, cmd) => {
|
|
1873
2019
|
printJson(await clientFrom(cmd).models.llm.get(id), outputOptions(cmd));
|
|
1874
2020
|
});
|
|
1875
|
-
llm.command("chat <
|
|
2021
|
+
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) => {
|
|
2022
|
+
const client = clientFrom(cmd);
|
|
2023
|
+
const name = await resolveLlmModelName(client, model2);
|
|
1876
2024
|
const messages = [{ role: "user", content: opts.message }];
|
|
1877
2025
|
if (opts.stream) {
|
|
1878
|
-
await
|
|
2026
|
+
await client.models.llm.chatStream(name, messages, (t) => process.stdout.write(t));
|
|
1879
2027
|
process.stdout.write("\n");
|
|
1880
2028
|
return;
|
|
1881
2029
|
}
|
|
1882
|
-
printJson(await
|
|
2030
|
+
printJson(await client.models.llm.chat(name, messages), outputOptions(cmd));
|
|
2031
|
+
});
|
|
2032
|
+
llm.command("set-default <modelId>").description("Set this LLM as the system default (admin)").action(async (id, _opts, cmd) => {
|
|
2033
|
+
printJson(await clientFrom(cmd).models.llm.setDefault(id, true), outputOptions(cmd));
|
|
2034
|
+
});
|
|
2035
|
+
llm.command("unset-default <modelId>").description("Clear this LLM as the system default (admin)").action(async (id, _opts, cmd) => {
|
|
2036
|
+
printJson(await clientFrom(cmd).models.llm.setDefault(id, false), outputOptions(cmd));
|
|
1883
2037
|
});
|
|
1884
2038
|
addManagementCommands(llm, "llm");
|
|
1885
2039
|
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",
|
|
2040
|
+
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
2041
|
printJson(
|
|
1888
2042
|
await clientFrom(cmd).models.small.list({
|
|
1889
2043
|
name: opts.name,
|
|
@@ -1909,20 +2063,60 @@ function modelCommand() {
|
|
|
1909
2063
|
outputOptions(cmd)
|
|
1910
2064
|
);
|
|
1911
2065
|
});
|
|
2066
|
+
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) => {
|
|
2067
|
+
printJson(await clientFrom(cmd).models.small.getDefault(opts.type), outputOptions(cmd));
|
|
2068
|
+
});
|
|
2069
|
+
small.command("set-default <modelId>").description("Set this small model as the system default for its type (admin)").action(async (id, _opts, cmd) => {
|
|
2070
|
+
printJson(await clientFrom(cmd).models.small.setDefault(id, true), outputOptions(cmd));
|
|
2071
|
+
});
|
|
2072
|
+
small.command("unset-default <modelId>").description("Clear this small model as the system default (admin)").action(async (id, _opts, cmd) => {
|
|
2073
|
+
printJson(await clientFrom(cmd).models.small.setDefault(id, false), outputOptions(cmd));
|
|
2074
|
+
});
|
|
1912
2075
|
addManagementCommands(small, "small");
|
|
2076
|
+
model.addHelpText(
|
|
2077
|
+
"after",
|
|
2078
|
+
`
|
|
2079
|
+
Identifiers:
|
|
2080
|
+
\u2022 get / set-default / delete take the numeric model id (e.g. 2071747547839467520).
|
|
2081
|
+
\u2022 chat takes a model NAME, but also accepts a numeric id (resolved to its name).
|
|
2082
|
+
|
|
2083
|
+
Examples:
|
|
2084
|
+
$ openbkn model llm list # ids + the 'default' flag
|
|
2085
|
+
$ openbkn model llm chat deepseek_v4_flash -m hi # by name
|
|
2086
|
+
$ openbkn model llm chat 2071747547839467520 -m hi --stream # by id, streamed
|
|
2087
|
+
$ openbkn model llm set-default 2071747547839467520 # system default LLM
|
|
2088
|
+
$ openbkn model small get-default --type embedding # current default
|
|
2089
|
+
$ openbkn model small set-default <id> # default embedding/reranker`
|
|
2090
|
+
);
|
|
1913
2091
|
return group(model, "MODELS & SKILLS");
|
|
1914
2092
|
}
|
|
1915
2093
|
|
|
1916
2094
|
// src/commands/resource.ts
|
|
1917
|
-
import { Command as
|
|
1918
|
-
var
|
|
2095
|
+
import { Command as Command12 } from "commander";
|
|
2096
|
+
var int9 = (v) => Number.parseInt(v, 10);
|
|
2097
|
+
var parsePairs = (raw) => {
|
|
2098
|
+
if (!raw) return void 0;
|
|
2099
|
+
return raw.split(",").map((part) => {
|
|
2100
|
+
const idx = part.indexOf("=");
|
|
2101
|
+
if (idx < 1) throw new Error("--extension must be key=value[,key=value]");
|
|
2102
|
+
return { key: part.slice(0, idx).trim(), value: part.slice(idx + 1).trim() };
|
|
2103
|
+
}).filter((p) => p.key.length > 0);
|
|
2104
|
+
};
|
|
1919
2105
|
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",
|
|
2106
|
+
const cmd = new Command12("resource").alias("res").description("Resources \u2014 list, find, get, query, delete");
|
|
2107
|
+
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
2108
|
const data = await clientFrom(cmd2).resource.list({
|
|
1923
2109
|
datasourceId: opts.catalogId ?? opts.datasourceId,
|
|
1924
2110
|
category: opts.category ?? opts.type,
|
|
1925
|
-
|
|
2111
|
+
status: opts.status,
|
|
2112
|
+
database: opts.database,
|
|
2113
|
+
limit: opts.limit,
|
|
2114
|
+
offset: opts.offset,
|
|
2115
|
+
includeExtensions: opts.includeExtensions,
|
|
2116
|
+
includeExtensionKeys: opts.includeExtensionKeys,
|
|
2117
|
+
extensionPairs: parsePairs(opts.extension),
|
|
2118
|
+
sort: opts.sort,
|
|
2119
|
+
direction: opts.direction
|
|
1926
2120
|
});
|
|
1927
2121
|
printJson(data, outputOptions(cmd2));
|
|
1928
2122
|
});
|
|
@@ -1936,7 +2130,7 @@ function resourceCommand() {
|
|
|
1936
2130
|
cmd.command("get <id>").description("Get resource details").action(async (id, _opts, cmd2) => {
|
|
1937
2131
|
printJson(await clientFrom(cmd2).resource.get(id), outputOptions(cmd2));
|
|
1938
2132
|
});
|
|
1939
|
-
cmd.command("query <id>").description("Fetch data rows from a resource").option("--limit <n>", "row limit",
|
|
2133
|
+
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("--need-total", "include total count").action(async (id, opts, cmd2) => {
|
|
1940
2134
|
const data = await clientFrom(cmd2).resource.query(id, {
|
|
1941
2135
|
limit: opts.limit,
|
|
1942
2136
|
offset: opts.offset,
|
|
@@ -1951,11 +2145,11 @@ function resourceCommand() {
|
|
|
1951
2145
|
}
|
|
1952
2146
|
|
|
1953
2147
|
// src/commands/skill.ts
|
|
1954
|
-
import { Command as
|
|
1955
|
-
var
|
|
2148
|
+
import { Command as Command13 } from "commander";
|
|
2149
|
+
var int10 = (v) => Number.parseInt(v, 10);
|
|
1956
2150
|
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",
|
|
2151
|
+
const cmd = new Command13("skill").description("Skill registry and market");
|
|
2152
|
+
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
2153
|
listOpts(cmd.command("list").description("List skills")).option("--create-user <s>", "filter by creator").action(async (opts, cmd2) => {
|
|
1960
2154
|
printJson(
|
|
1961
2155
|
await clientFrom(cmd2).skills.list({
|
|
@@ -2041,11 +2235,11 @@ function skillCommand() {
|
|
|
2041
2235
|
}
|
|
2042
2236
|
|
|
2043
2237
|
// src/commands/toolbox.ts
|
|
2044
|
-
import { Command as
|
|
2045
|
-
var
|
|
2238
|
+
import { Command as Command14 } from "commander";
|
|
2239
|
+
var int11 = (v) => Number.parseInt(v, 10);
|
|
2046
2240
|
function toolboxCommand() {
|
|
2047
|
-
const cmd = new
|
|
2048
|
-
cmd.command("list").description("List toolboxes").option("--keyword <s>", "filter by keyword").option("--limit <n>", "page size",
|
|
2241
|
+
const cmd = new Command14("toolbox").description("Agent toolbox lifecycle");
|
|
2242
|
+
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
2243
|
printJson(
|
|
2050
2244
|
await clientFrom(cmd2).toolboxes.list({
|
|
2051
2245
|
keyword: opts.keyword,
|
|
@@ -2086,7 +2280,7 @@ function toolboxCommand() {
|
|
|
2086
2280
|
return group(cmd, "DECISION AGENT");
|
|
2087
2281
|
}
|
|
2088
2282
|
function toolCommand() {
|
|
2089
|
-
const cmd = new
|
|
2283
|
+
const cmd = new Command14("tool").description("Tools inside a toolbox");
|
|
2090
2284
|
cmd.command("list").description("List tools in a toolbox").requiredOption("--toolbox <box-id>", "toolbox id").action(async (opts, cmd2) => {
|
|
2091
2285
|
printJson(await clientFrom(cmd2).toolboxes.tools(opts.toolbox), outputOptions(cmd2));
|
|
2092
2286
|
});
|
|
@@ -2102,7 +2296,7 @@ function toolCommand() {
|
|
|
2102
2296
|
outputOptions(cmd2)
|
|
2103
2297
|
);
|
|
2104
2298
|
});
|
|
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",
|
|
2299
|
+
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
2300
|
const parseJson = (s, label) => {
|
|
2107
2301
|
if (!s) return void 0;
|
|
2108
2302
|
try {
|
|
@@ -2144,11 +2338,11 @@ function toolCommand() {
|
|
|
2144
2338
|
}
|
|
2145
2339
|
|
|
2146
2340
|
// src/commands/trace.ts
|
|
2147
|
-
import { readFileSync as
|
|
2148
|
-
import { Command as
|
|
2341
|
+
import { readFileSync as readFileSync5, writeFileSync } from "fs";
|
|
2342
|
+
import { Command as Command15 } from "commander";
|
|
2149
2343
|
|
|
2150
|
-
// src/trace
|
|
2151
|
-
import { readFileSync as
|
|
2344
|
+
// src/bkn-trace/schema-validate.ts
|
|
2345
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
2152
2346
|
import { extname } from "path";
|
|
2153
2347
|
import yaml from "js-yaml";
|
|
2154
2348
|
import { z } from "zod";
|
|
@@ -2185,7 +2379,7 @@ var DiagnosisRule = z.object({
|
|
|
2185
2379
|
params: z.record(z.string(), z.unknown()).optional()
|
|
2186
2380
|
});
|
|
2187
2381
|
function parseFile(file) {
|
|
2188
|
-
const text =
|
|
2382
|
+
const text = readFileSync4(file, "utf8");
|
|
2189
2383
|
const ext = extname(file).toLowerCase();
|
|
2190
2384
|
if (ext === ".yaml" || ext === ".yml") return yaml.load(text);
|
|
2191
2385
|
return JSON.parse(text);
|
|
@@ -2223,8 +2417,8 @@ function validateSchemaFile(file, kind) {
|
|
|
2223
2417
|
|
|
2224
2418
|
// src/commands/trace.ts
|
|
2225
2419
|
function traceCommand() {
|
|
2226
|
-
const cmd = new
|
|
2227
|
-
"Trace
|
|
2420
|
+
const cmd = new Command15("trace").description(
|
|
2421
|
+
"BKN Trace \u2014 fetch spans, diagnose (symbolic + LLM rubric), scan, eval-set, schema validate"
|
|
2228
2422
|
);
|
|
2229
2423
|
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
2424
|
printJson(
|
|
@@ -2252,7 +2446,7 @@ function traceCommand() {
|
|
|
2252
2446
|
});
|
|
2253
2447
|
const evalSet = cmd.command("eval-set").description("Build + run trace eval sets");
|
|
2254
2448
|
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(
|
|
2449
|
+
const raw = JSON.parse(readFileSync5(queriesFile, "utf8"));
|
|
2256
2450
|
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2257
2451
|
if (opts.out) {
|
|
2258
2452
|
writeFileSync(opts.out, JSON.stringify({ cases }, null, 2));
|
|
@@ -2262,7 +2456,7 @@ function traceCommand() {
|
|
|
2262
2456
|
}
|
|
2263
2457
|
});
|
|
2264
2458
|
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(
|
|
2459
|
+
const raw = JSON.parse(readFileSync5(casesFile, "utf8"));
|
|
2266
2460
|
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2267
2461
|
const result = await clientFrom(cmd2).trace.evalSetTest(opts.agent, cases, {
|
|
2268
2462
|
version: opts.version,
|
|
@@ -2281,15 +2475,37 @@ function traceCommand() {
|
|
|
2281
2475
|
}
|
|
2282
2476
|
|
|
2283
2477
|
// src/commands/vega.ts
|
|
2284
|
-
import { Command as
|
|
2478
|
+
import { Command as Command16 } from "commander";
|
|
2479
|
+
var int12 = (v) => Number.parseInt(v, 10);
|
|
2480
|
+
var parsePairs2 = (raw) => {
|
|
2481
|
+
if (!raw) return void 0;
|
|
2482
|
+
return raw.split(",").map((part) => {
|
|
2483
|
+
const idx = part.indexOf("=");
|
|
2484
|
+
if (idx < 1) throw new InputError("--extension must be key=value[,key=value]");
|
|
2485
|
+
return { key: part.slice(0, idx).trim(), value: part.slice(idx + 1).trim() };
|
|
2486
|
+
}).filter((p) => p.key.length > 0);
|
|
2487
|
+
};
|
|
2285
2488
|
function vegaCommand() {
|
|
2286
|
-
const vega = new
|
|
2489
|
+
const vega = new Command16("vega").description(
|
|
2287
2490
|
"Vega observability \u2014 catalog, resources, index build tasks"
|
|
2288
2491
|
);
|
|
2289
2492
|
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) => {
|
|
2493
|
+
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
2494
|
const o = cmd.optsWithGlobals();
|
|
2292
|
-
const data = await clientFrom(cmd).vega.catalogs({
|
|
2495
|
+
const data = await clientFrom(cmd).vega.catalogs({
|
|
2496
|
+
limit: o.limit,
|
|
2497
|
+
offset: o.offset,
|
|
2498
|
+
name: o.name,
|
|
2499
|
+
tag: o.tag,
|
|
2500
|
+
type: o.type,
|
|
2501
|
+
enabled: o.enabled === void 0 ? void 0 : o.enabled === "true",
|
|
2502
|
+
healthCheckStatus: o.healthCheckStatus,
|
|
2503
|
+
includeExtensions: o.includeExtensions,
|
|
2504
|
+
includeExtensionKeys: o.includeExtensionKeys,
|
|
2505
|
+
extensionPairs: parsePairs2(o.extension),
|
|
2506
|
+
sort: o.sort,
|
|
2507
|
+
direction: o.direction
|
|
2508
|
+
});
|
|
2293
2509
|
printJson(data, outputOptions(cmd));
|
|
2294
2510
|
});
|
|
2295
2511
|
catalog.command("get <id>").description("Get a catalog by id").action(async (id, _opts, cmd) => {
|
|
@@ -2301,21 +2517,41 @@ function vegaCommand() {
|
|
|
2301
2517
|
catalog.command("health <ids...>").description("Health-status for one or more catalogs").action(async (ids, _opts, cmd) => {
|
|
2302
2518
|
printJson(await clientFrom(cmd).vega.catalogHealth(ids), outputOptions(cmd));
|
|
2303
2519
|
});
|
|
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) => {
|
|
2520
|
+
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
2521
|
let connectorConfig;
|
|
2306
2522
|
try {
|
|
2307
2523
|
connectorConfig = JSON.parse(opts.connectorConfig);
|
|
2308
2524
|
} catch {
|
|
2309
2525
|
throw new Error("--connector-config must be valid JSON");
|
|
2310
2526
|
}
|
|
2527
|
+
const extensions = opts.extensions ? JSON.parse(opts.extensions) : void 0;
|
|
2311
2528
|
printJson(
|
|
2312
2529
|
await clientFrom(cmd).vega.createCatalog({
|
|
2530
|
+
id: opts.id,
|
|
2531
|
+
name: opts.name,
|
|
2532
|
+
connectorType: opts.connectorType,
|
|
2533
|
+
connectorConfig,
|
|
2534
|
+
tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
|
|
2535
|
+
description: opts.description,
|
|
2536
|
+
enabled: opts.enabled ? true : void 0,
|
|
2537
|
+
internal: opts.internal ? true : void 0,
|
|
2538
|
+
extensions
|
|
2539
|
+
}),
|
|
2540
|
+
outputOptions(cmd)
|
|
2541
|
+
);
|
|
2542
|
+
});
|
|
2543
|
+
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) => {
|
|
2544
|
+
const connectorConfig = opts.connectorConfig ? JSON.parse(opts.connectorConfig) : void 0;
|
|
2545
|
+
const extensions = opts.extensions ? JSON.parse(opts.extensions) : void 0;
|
|
2546
|
+
printJson(
|
|
2547
|
+
await clientFrom(cmd).vega.updateCatalog(id, {
|
|
2313
2548
|
name: opts.name,
|
|
2314
2549
|
connectorType: opts.connectorType,
|
|
2315
2550
|
connectorConfig,
|
|
2316
2551
|
tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
|
|
2317
2552
|
description: opts.description,
|
|
2318
|
-
enabled: opts.enabled ?
|
|
2553
|
+
enabled: opts.enabled === void 0 ? void 0 : opts.enabled === "true",
|
|
2554
|
+
extensions
|
|
2319
2555
|
}),
|
|
2320
2556
|
outputOptions(cmd)
|
|
2321
2557
|
);
|
|
@@ -2323,6 +2559,15 @@ function vegaCommand() {
|
|
|
2323
2559
|
catalog.command("enable <id>").description("Enable a catalog (required before discovery)").action(async (id, _opts, cmd) => {
|
|
2324
2560
|
printJson(await clientFrom(cmd).vega.enableCatalog(id), outputOptions(cmd));
|
|
2325
2561
|
});
|
|
2562
|
+
catalog.command("disable <id>").description("Disable a catalog").action(async (id, _opts, cmd) => {
|
|
2563
|
+
printJson(await clientFrom(cmd).vega.disableCatalog(id), outputOptions(cmd));
|
|
2564
|
+
});
|
|
2565
|
+
catalog.command("delete <id>").description("Delete a catalog").action(async (id, _opts, cmd) => {
|
|
2566
|
+
printJson(await clientFrom(cmd).vega.deleteCatalog(id), outputOptions(cmd));
|
|
2567
|
+
});
|
|
2568
|
+
catalog.command("test-connection <id>").description("Test a catalog connection").action(async (id, _opts, cmd) => {
|
|
2569
|
+
printJson(await clientFrom(cmd).vega.testCatalogConnection(id), outputOptions(cmd));
|
|
2570
|
+
});
|
|
2326
2571
|
catalog.command("discover <id>").description("Trigger catalog resource discovery").option("--wait", "wait for discovery to complete").action(async (id, opts, cmd) => {
|
|
2327
2572
|
printJson(
|
|
2328
2573
|
await clientFrom(cmd).vega.discoverCatalog(id, Boolean(opts.wait)),
|
|
@@ -2336,13 +2581,49 @@ function vegaCommand() {
|
|
|
2336
2581
|
connector.command("get <type>").description("Get a connector type").action(async (type, _opts, cmd) => {
|
|
2337
2582
|
printJson(await clientFrom(cmd).vega.connectorType(type), outputOptions(cmd));
|
|
2338
2583
|
});
|
|
2584
|
+
vega.command("sql").description("Run SQL / OpenSearch DSL directly against a vega-backend data source").requiredOption("--resource-type <type>", "source type (mysql | postgresql | opensearch | \u2026)").option("--query-type <type>", "query mode: standard | stream").option(
|
|
2585
|
+
"--query <sql>",
|
|
2586
|
+
"SQL string; reference a resource with a {{<resource-id>}} placeholder"
|
|
2587
|
+
).option("--stream-size <n>", "streaming batch size (100\u201310000)", int12).option("--query-timeout <s>", "query timeout in seconds (1\u20133600)", int12).option(
|
|
2588
|
+
"-d, --data <json>",
|
|
2589
|
+
"full request body as JSON (advanced; wins over --query/--resource-type)"
|
|
2590
|
+
).action(async (opts, cmd) => {
|
|
2591
|
+
let body;
|
|
2592
|
+
if (opts.data) {
|
|
2593
|
+
try {
|
|
2594
|
+
body = JSON.parse(opts.data);
|
|
2595
|
+
} catch {
|
|
2596
|
+
throw new InputError("--data must be valid JSON");
|
|
2597
|
+
}
|
|
2598
|
+
} else {
|
|
2599
|
+
if (!opts.query) {
|
|
2600
|
+
throw new InputError("Provide --query (and optionally --resource-type), or --data.");
|
|
2601
|
+
}
|
|
2602
|
+
body = {
|
|
2603
|
+
query: opts.query,
|
|
2604
|
+
resource_type: opts.resourceType,
|
|
2605
|
+
...opts.queryType ? { query_type: opts.queryType } : {},
|
|
2606
|
+
...opts.streamSize !== void 0 ? { stream_size: opts.streamSize } : {},
|
|
2607
|
+
...opts.queryTimeout !== void 0 ? { query_timeout: opts.queryTimeout } : {}
|
|
2608
|
+
};
|
|
2609
|
+
}
|
|
2610
|
+
printJson(await clientFrom(cmd).vega.sql(body), outputOptions(cmd));
|
|
2611
|
+
});
|
|
2339
2612
|
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) => {
|
|
2613
|
+
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
2614
|
printJson(
|
|
2342
2615
|
await clientFrom(cmd).resource.list({
|
|
2343
2616
|
datasourceId: opts.datasourceId ?? opts.catalogId,
|
|
2344
2617
|
category: opts.type ?? opts.category,
|
|
2345
|
-
|
|
2618
|
+
status: opts.status,
|
|
2619
|
+
database: opts.database,
|
|
2620
|
+
limit: opts.limit,
|
|
2621
|
+
offset: opts.offset,
|
|
2622
|
+
includeExtensions: opts.includeExtensions,
|
|
2623
|
+
includeExtensionKeys: opts.includeExtensionKeys,
|
|
2624
|
+
extensionPairs: parsePairs2(opts.extension),
|
|
2625
|
+
sort: opts.sort,
|
|
2626
|
+
direction: opts.direction
|
|
2346
2627
|
}),
|
|
2347
2628
|
outputOptions(cmd)
|
|
2348
2629
|
);
|
|
@@ -2360,16 +2641,25 @@ function vegaCommand() {
|
|
|
2360
2641
|
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
2642
|
"--build-key-fields <list>",
|
|
2362
2643
|
"comma-separated key fields (batch: time; streaming: row id)"
|
|
2363
|
-
).option("--embedding-model <id>", "embedding model id
|
|
2644
|
+
).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
2645
|
const o = cmd.optsWithGlobals();
|
|
2646
|
+
const embeddingFields = csv(o.embeddingFields);
|
|
2647
|
+
const buildKeyFields = csv(o.buildKeyFields);
|
|
2648
|
+
const fulltextFields = csv(o.fulltextFields);
|
|
2649
|
+
if (embeddingFields || buildKeyFields || o.embeddingModel || fulltextFields || o.fulltextAnalyzer) {
|
|
2650
|
+
await clientFrom(cmd).resource.configureIndex(resourceId, {
|
|
2651
|
+
embeddingFields,
|
|
2652
|
+
buildKeyFields,
|
|
2653
|
+
embeddingModel: o.embeddingModel,
|
|
2654
|
+
fulltextFields,
|
|
2655
|
+
fulltextAnalyzer: o.fulltextAnalyzer
|
|
2656
|
+
});
|
|
2657
|
+
}
|
|
2365
2658
|
const task = await clientFrom(cmd).vega.build(
|
|
2366
2659
|
{
|
|
2367
2660
|
resource_id: resourceId,
|
|
2368
2661
|
mode: o.mode,
|
|
2369
|
-
|
|
2370
|
-
build_key_fields: csv(o.buildKeyFields),
|
|
2371
|
-
embedding_model: o.embeddingModel,
|
|
2372
|
-
model_dimensions: o.modelDimensions
|
|
2662
|
+
execute_type: o.executeType
|
|
2373
2663
|
},
|
|
2374
2664
|
{ wait: Boolean(o.wait), timeoutMs: o.timeout * 1e3 }
|
|
2375
2665
|
);
|
|
@@ -2379,15 +2669,50 @@ function vegaCommand() {
|
|
|
2379
2669
|
const task = await clientFrom(cmd).vega.buildStatus(taskId);
|
|
2380
2670
|
printJson(task, outputOptions(cmd));
|
|
2381
2671
|
});
|
|
2672
|
+
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) => {
|
|
2673
|
+
printJson(
|
|
2674
|
+
await clientFrom(cmd).vega.buildTasks({
|
|
2675
|
+
limit: opts.limit,
|
|
2676
|
+
offset: opts.offset,
|
|
2677
|
+
resourceId: opts.resourceId,
|
|
2678
|
+
catalogId: opts.catalogId,
|
|
2679
|
+
status: opts.status,
|
|
2680
|
+
active: opts.active,
|
|
2681
|
+
mode: opts.mode,
|
|
2682
|
+
orderBy: opts.orderBy,
|
|
2683
|
+
order: opts.order
|
|
2684
|
+
}),
|
|
2685
|
+
outputOptions(cmd)
|
|
2686
|
+
);
|
|
2687
|
+
});
|
|
2688
|
+
dataset.command("build-start <task-id>").description("Start a BuildTask").option("--reset", "restart from the beginning").action(async (taskId, opts, cmd) => {
|
|
2689
|
+
printJson(
|
|
2690
|
+
await clientFrom(cmd).vega.startBuildTask(taskId, { reset: opts.reset }),
|
|
2691
|
+
outputOptions(cmd)
|
|
2692
|
+
);
|
|
2693
|
+
});
|
|
2694
|
+
dataset.command("build-stop <task-id>").description("Stop a BuildTask").action(async (taskId, _opts, cmd) => {
|
|
2695
|
+
printJson(await clientFrom(cmd).vega.stopBuildTask(taskId), outputOptions(cmd));
|
|
2696
|
+
});
|
|
2697
|
+
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) => {
|
|
2698
|
+
printJson(
|
|
2699
|
+
await clientFrom(cmd).vega.deleteBuildTasks(ids, {
|
|
2700
|
+
ignoreMissing: opts.ignoreMissing,
|
|
2701
|
+
deleteActiveIndex: opts.deleteActiveIndex
|
|
2702
|
+
}),
|
|
2703
|
+
outputOptions(cmd)
|
|
2704
|
+
);
|
|
2705
|
+
});
|
|
2382
2706
|
return group(vega, "AI DATA PLATFORM");
|
|
2383
2707
|
}
|
|
2384
2708
|
|
|
2385
2709
|
// src/cli.ts
|
|
2386
|
-
var program = new
|
|
2710
|
+
var program = new Command17();
|
|
2387
2711
|
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();
|
|
2388
2712
|
program.addCommand(authCommand());
|
|
2389
2713
|
program.addCommand(callCommand());
|
|
2390
2714
|
program.addCommand(configCommand());
|
|
2715
|
+
program.addCommand(appkeyCommand());
|
|
2391
2716
|
program.addCommand(vegaCommand());
|
|
2392
2717
|
program.addCommand(bknCommand());
|
|
2393
2718
|
program.addCommand(resourceCommand());
|