@openbkn/bkn-sdk 0.1.1-alpha.16 → 0.1.1-alpha.19
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 +202 -132
- package/NOTICE +6 -16
- package/README.md +5 -9
- package/README.zh.md +5 -8
- package/dist/{chunk-SH2KLES5.js → chunk-ISJHU26W.js} +454 -147
- package/dist/cli.js +196 -96
- package/dist/index.d.ts +266 -58
- package/dist/index.js +1 -1
- package/package.json +6 -5
- package/dist/chunk-SH2KLES5.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,7 +35,7 @@ import {
|
|
|
37
35
|
use,
|
|
38
36
|
whoami,
|
|
39
37
|
writePlatformConfig
|
|
40
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-ISJHU26W.js";
|
|
41
39
|
|
|
42
40
|
// src/cli.ts
|
|
43
41
|
import { Command as Command17 } from "commander";
|
|
@@ -45,10 +43,10 @@ import { Command as Command17 } from "commander";
|
|
|
45
43
|
// package.json
|
|
46
44
|
var package_default = {
|
|
47
45
|
name: "@openbkn/bkn-sdk",
|
|
48
|
-
version: "0.1.1-alpha.
|
|
46
|
+
version: "0.1.1-alpha.19",
|
|
49
47
|
description: "Unified TypeScript SDK + CLI for the BKN (Business Knowledge Network) platform.",
|
|
50
48
|
type: "module",
|
|
51
|
-
license: "
|
|
49
|
+
license: "Apache-2.0",
|
|
52
50
|
engines: {
|
|
53
51
|
node: ">=18"
|
|
54
52
|
},
|
|
@@ -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", "NOTICE"],
|
|
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
|
|
@@ -352,25 +352,6 @@ function readBody(opts) {
|
|
|
352
352
|
|
|
353
353
|
// src/commands/auth.ts
|
|
354
354
|
import { Command } from "commander";
|
|
355
|
-
|
|
356
|
-
// src/api/eacp-crypto.ts
|
|
357
|
-
import {
|
|
358
|
-
constants,
|
|
359
|
-
createPrivateKey,
|
|
360
|
-
createPublicKey,
|
|
361
|
-
publicEncrypt
|
|
362
|
-
} from "crypto";
|
|
363
|
-
|
|
364
|
-
// src/api/admin.ts
|
|
365
|
-
async function changePasswordSafe(ctx, account, oldPassword, newPassword) {
|
|
366
|
-
await request(ctx, "/api/safe/v1/auth/change-password", {
|
|
367
|
-
method: "POST",
|
|
368
|
-
body: { account, old_password: oldPassword, new_password: newPassword }
|
|
369
|
-
});
|
|
370
|
-
return { ok: true };
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// src/commands/auth.ts
|
|
374
355
|
async function resolveAccount(baseUrl, accessToken, insecure, idToken) {
|
|
375
356
|
const sub = decodeJwt(idToken ?? accessToken)?.sub;
|
|
376
357
|
if (!sub) return void 0;
|
|
@@ -399,25 +380,17 @@ function renderSessions(items) {
|
|
|
399
380
|
return lines.join("\n") || "(no saved sessions)";
|
|
400
381
|
}
|
|
401
382
|
function registerAuthLeaves(cmd) {
|
|
402
|
-
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>", "
|
|
403
|
-
"--port <n>",
|
|
404
|
-
"loopback redirect port for the auth_code flow",
|
|
405
|
-
(v) => Number.parseInt(v, 10)
|
|
406
|
-
).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(
|
|
407
384
|
"--timeout <s>",
|
|
408
385
|
"device-login wait before timing out",
|
|
409
386
|
(v) => Number.parseInt(v, 10),
|
|
410
387
|
120
|
|
411
|
-
).option("--no-browser", "
|
|
388
|
+
).option("--no-browser", "print the URL instead of opening a browser").action(async (url, opts, cmd2) => {
|
|
412
389
|
const g = cmd2.optsWithGlobals();
|
|
413
|
-
if (g.insecure) process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
414
390
|
const out = outputOptions(cmd2);
|
|
415
391
|
const report = (r) => {
|
|
416
392
|
if (out.json || out.compact) {
|
|
417
393
|
printJson({ loggedIn: true, ...r }, out);
|
|
418
|
-
} else if (r.noAuth) {
|
|
419
|
-
process.stdout.write(`Registered ${r.baseUrl ?? url} (no authentication)
|
|
420
|
-
`);
|
|
421
394
|
} else {
|
|
422
395
|
process.stdout.write(`Logged in to ${r.baseUrl ?? url} as ${r.username ?? r.userId}
|
|
423
396
|
`);
|
|
@@ -425,20 +398,7 @@ function registerAuthLeaves(cmd) {
|
|
|
425
398
|
};
|
|
426
399
|
const token = opts.token ?? g.token;
|
|
427
400
|
if (token) {
|
|
428
|
-
report(attachToken(url, token
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
if (opts.auth === false) {
|
|
432
|
-
report(attachNoAuth(url, { insecure: g.insecure }));
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
const authStatus = await fetchAuthStatus(url);
|
|
436
|
-
if (authStatus && !authStatus.enabled) {
|
|
437
|
-
process.stderr.write(
|
|
438
|
-
`Platform auth is disabled (stack: ${authStatus.stack ?? "none"}) \u2014 registering without auth.
|
|
439
|
-
`
|
|
440
|
-
);
|
|
441
|
-
report(attachNoAuth(url, { insecure: g.insecure }));
|
|
401
|
+
report(attachToken(url, token));
|
|
442
402
|
return;
|
|
443
403
|
}
|
|
444
404
|
let tokens;
|
|
@@ -451,7 +411,8 @@ function registerAuthLeaves(cmd) {
|
|
|
451
411
|
tokens = await credentialDeviceLogin(url, username, password, {
|
|
452
412
|
clientId: opts.clientId,
|
|
453
413
|
audience: opts.audience,
|
|
454
|
-
timeoutMs: opts.timeout * 1e3
|
|
414
|
+
timeoutMs: opts.timeout * 1e3,
|
|
415
|
+
insecure: g.insecure
|
|
455
416
|
});
|
|
456
417
|
} else {
|
|
457
418
|
const headless = isHeadless();
|
|
@@ -460,6 +421,7 @@ function registerAuthLeaves(cmd) {
|
|
|
460
421
|
clientId: opts.clientId,
|
|
461
422
|
audience: opts.audience,
|
|
462
423
|
timeoutMs: opts.timeout * 1e3,
|
|
424
|
+
insecure: g.insecure,
|
|
463
425
|
onPrompt: ({ userCode, verificationUri, verificationUriComplete }) => {
|
|
464
426
|
const target = verificationUriComplete ?? verificationUri;
|
|
465
427
|
process.stderr.write(
|
|
@@ -478,9 +440,9 @@ User code: ${userCode}
|
|
|
478
440
|
}
|
|
479
441
|
} catch (e) {
|
|
480
442
|
if (e instanceof Error && /Device auth failed \(404\)/.test(e.message)) {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
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
|
+
);
|
|
484
446
|
}
|
|
485
447
|
throw e;
|
|
486
448
|
}
|
|
@@ -496,29 +458,28 @@ User code: ${userCode}
|
|
|
496
458
|
attachToken(url, tokens.accessToken, {
|
|
497
459
|
refreshToken: tokens.refreshToken,
|
|
498
460
|
idToken: tokens.idToken,
|
|
499
|
-
insecure: g.insecure,
|
|
500
461
|
username: account
|
|
501
462
|
})
|
|
502
463
|
);
|
|
503
464
|
});
|
|
504
|
-
cmd.command("status").description("Show base URL and whether a token is configured").action(
|
|
465
|
+
cmd.command("status").description("Show base URL and whether a token is configured").action(
|
|
466
|
+
(_opts, cmd2) => printJson(status({ user: cmd2.optsWithGlobals().user }), outputOptions(cmd2))
|
|
467
|
+
);
|
|
505
468
|
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) => {
|
|
506
469
|
const g = cmd2.optsWithGlobals();
|
|
507
|
-
|
|
508
|
-
const token = opts.refresh === false ? currentToken() : await currentTokenFresh();
|
|
470
|
+
const token = opts.refresh === false ? currentToken({ user: g.user }) : await currentTokenFresh({ insecure: g.insecure, user: g.user });
|
|
509
471
|
process.stdout.write(`${token}
|
|
510
472
|
`);
|
|
511
473
|
});
|
|
512
474
|
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) => {
|
|
513
475
|
const g = cmd2.optsWithGlobals();
|
|
514
|
-
|
|
515
|
-
const me = whoami();
|
|
476
|
+
const me = whoami({ user: g.user });
|
|
516
477
|
if (opts.lookup !== false && me.baseUrl && me.sub) {
|
|
517
478
|
try {
|
|
518
479
|
const u = await getUserSafe(
|
|
519
480
|
{
|
|
520
481
|
baseUrl: me.baseUrl,
|
|
521
|
-
token: currentToken(),
|
|
482
|
+
token: currentToken({ user: g.user }),
|
|
522
483
|
businessDomain: DEFAULT_BUSINESS_DOMAIN,
|
|
523
484
|
insecure: Boolean(g.insecure)
|
|
524
485
|
},
|
|
@@ -583,9 +544,8 @@ User code: ${userCode}
|
|
|
583
544
|
cmd.command("export").description("Export the active session's tokens (for a headless host)").action((_opts, cmd2) => {
|
|
584
545
|
printJson(exportCreds(), outputOptions(cmd2));
|
|
585
546
|
});
|
|
586
|
-
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").
|
|
547
|
+
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) => {
|
|
587
548
|
const g = cmd2.optsWithGlobals();
|
|
588
|
-
if (g.insecure) process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
589
549
|
const ctx = resolveContext({
|
|
590
550
|
baseUrl: url ?? g.baseUrl,
|
|
591
551
|
token: g.token,
|
|
@@ -626,6 +586,12 @@ function authCommand() {
|
|
|
626
586
|
// src/commands/admin.ts
|
|
627
587
|
var int = (v) => Number.parseInt(v, 10);
|
|
628
588
|
var DEFAULT_RESET_PASSWORD = "openbkn";
|
|
589
|
+
async function importLicenseFile(cmd, file, receipt) {
|
|
590
|
+
const text = readFileSync2(file, "utf8");
|
|
591
|
+
const res = await clientFrom(cmd).admin.licenseImport(text, { receipt });
|
|
592
|
+
printJson(res, outputOptions(cmd));
|
|
593
|
+
if ("stored" in res && res.stored) process.exitCode = 1;
|
|
594
|
+
}
|
|
629
595
|
function adminCommand() {
|
|
630
596
|
const admin = new Command2("admin").description("Operator CLI: org, user, role, models, audit");
|
|
631
597
|
registerAuthLeaves(admin.command("auth").description("Operator authentication"));
|
|
@@ -911,6 +877,27 @@ function adminCommand() {
|
|
|
911
877
|
);
|
|
912
878
|
});
|
|
913
879
|
}
|
|
880
|
+
const license = admin.command("license").description("Cluster license management");
|
|
881
|
+
license.command("show").description("Current license detail (state/edition/expiry/features)").action(async (_opts, cmd) => {
|
|
882
|
+
printJson(await clientFrom(cmd).admin.licenseGet(), outputOptions(cmd));
|
|
883
|
+
});
|
|
884
|
+
license.command("import <file>").description("Import a .lic license file (online deployments auto-activate)").action(async (file, _opts, cmd) => {
|
|
885
|
+
await importLicenseFile(cmd, file, false);
|
|
886
|
+
});
|
|
887
|
+
license.command("receipt <file>").description("Import an offline activation receipt (.lic from the license portal)").action(async (file, _opts, cmd) => {
|
|
888
|
+
await importLicenseFile(cmd, file, true);
|
|
889
|
+
});
|
|
890
|
+
license.command("activate").description("Report the installed license to the issuer (online deployments)").action(async (_opts, cmd) => {
|
|
891
|
+
printJson(await clientFrom(cmd).admin.licenseActivate(), outputOptions(cmd));
|
|
892
|
+
});
|
|
893
|
+
license.command("remove").description("Remove the installed license (back to unactivated)").action(async (_opts, cmd) => {
|
|
894
|
+
printJson(await clientFrom(cmd).admin.licenseRemove(), outputOptions(cmd));
|
|
895
|
+
});
|
|
896
|
+
license.command("fingerprint").description(
|
|
897
|
+
"This cluster's machine code (paste into the license portal for offline activation)"
|
|
898
|
+
).action(async (_opts, cmd) => {
|
|
899
|
+
printJson(await clientFrom(cmd).admin.licenseFingerprint(), outputOptions(cmd));
|
|
900
|
+
});
|
|
914
901
|
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) => {
|
|
915
902
|
printJson(
|
|
916
903
|
await clientFrom(cmd).admin.auditList({
|
|
@@ -1151,7 +1138,7 @@ function appkeyCommand() {
|
|
|
1151
1138
|
import { Command as Command5 } from "commander";
|
|
1152
1139
|
|
|
1153
1140
|
// src/utils/bkn-validate.ts
|
|
1154
|
-
import { existsSync, readFileSync as
|
|
1141
|
+
import { existsSync, readFileSync as readFileSync3, readdirSync, statSync } from "fs";
|
|
1155
1142
|
import { join, resolve } from "path";
|
|
1156
1143
|
var BKN_OBJECT_NAME_MAX_LENGTH = 40;
|
|
1157
1144
|
function parseFrontmatter(text) {
|
|
@@ -1204,7 +1191,7 @@ function validateBknDirectory(dirPath) {
|
|
|
1204
1191
|
if (!existsSync(networkPath)) {
|
|
1205
1192
|
errors.push("Missing network.bkn at the BKN root.");
|
|
1206
1193
|
} else {
|
|
1207
|
-
const fm = parseFrontmatter(
|
|
1194
|
+
const fm = parseFrontmatter(readFileSync3(networkPath, "utf8"));
|
|
1208
1195
|
if (!fm) errors.push("network.bkn has no frontmatter block.");
|
|
1209
1196
|
else {
|
|
1210
1197
|
if (fm.type !== "knowledge_network")
|
|
@@ -1216,7 +1203,7 @@ function validateBknDirectory(dirPath) {
|
|
|
1216
1203
|
const otIds = /* @__PURE__ */ new Set();
|
|
1217
1204
|
const otFiles = bknFiles(join(dir, "object_types"));
|
|
1218
1205
|
for (const file of otFiles) {
|
|
1219
|
-
const fm = parseFrontmatter(
|
|
1206
|
+
const fm = parseFrontmatter(readFileSync3(file, "utf8"));
|
|
1220
1207
|
const rel = file.slice(dir.length + 1);
|
|
1221
1208
|
if (!fm || fm.type !== "object_type") {
|
|
1222
1209
|
errors.push(`${rel}: not a valid object_type (missing/wrong frontmatter type).`);
|
|
@@ -1236,7 +1223,7 @@ function validateBknDirectory(dirPath) {
|
|
|
1236
1223
|
}
|
|
1237
1224
|
const rtFiles = bknFiles(join(dir, "relation_types"));
|
|
1238
1225
|
for (const file of rtFiles) {
|
|
1239
|
-
const text =
|
|
1226
|
+
const text = readFileSync3(file, "utf8");
|
|
1240
1227
|
const fm = parseFrontmatter(text);
|
|
1241
1228
|
const rel = file.slice(dir.length + 1);
|
|
1242
1229
|
if (!fm || fm.type !== "relation_type") {
|
|
@@ -2106,13 +2093,29 @@ Examples:
|
|
|
2106
2093
|
// src/commands/resource.ts
|
|
2107
2094
|
import { Command as Command12 } from "commander";
|
|
2108
2095
|
var int9 = (v) => Number.parseInt(v, 10);
|
|
2096
|
+
var parsePairs = (raw) => {
|
|
2097
|
+
if (!raw) return void 0;
|
|
2098
|
+
return raw.split(",").map((part) => {
|
|
2099
|
+
const idx = part.indexOf("=");
|
|
2100
|
+
if (idx < 1) throw new Error("--extension must be key=value[,key=value]");
|
|
2101
|
+
return { key: part.slice(0, idx).trim(), value: part.slice(idx + 1).trim() };
|
|
2102
|
+
}).filter((p) => p.key.length > 0);
|
|
2103
|
+
};
|
|
2109
2104
|
function resourceCommand() {
|
|
2110
2105
|
const cmd = new Command12("resource").alias("res").description("Resources \u2014 list, find, get, query, delete");
|
|
2111
|
-
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", int9, DEFAULT_LIST_LIMIT).action(async (opts, cmd2) => {
|
|
2106
|
+
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) => {
|
|
2112
2107
|
const data = await clientFrom(cmd2).resource.list({
|
|
2113
2108
|
datasourceId: opts.catalogId ?? opts.datasourceId,
|
|
2114
2109
|
category: opts.category ?? opts.type,
|
|
2115
|
-
|
|
2110
|
+
status: opts.status,
|
|
2111
|
+
database: opts.database,
|
|
2112
|
+
limit: opts.limit,
|
|
2113
|
+
offset: opts.offset,
|
|
2114
|
+
includeExtensions: opts.includeExtensions,
|
|
2115
|
+
includeExtensionKeys: opts.includeExtensionKeys,
|
|
2116
|
+
extensionPairs: parsePairs(opts.extension),
|
|
2117
|
+
sort: opts.sort,
|
|
2118
|
+
direction: opts.direction
|
|
2116
2119
|
});
|
|
2117
2120
|
printJson(data, outputOptions(cmd2));
|
|
2118
2121
|
});
|
|
@@ -2334,11 +2337,11 @@ function toolCommand() {
|
|
|
2334
2337
|
}
|
|
2335
2338
|
|
|
2336
2339
|
// src/commands/trace.ts
|
|
2337
|
-
import { readFileSync as
|
|
2340
|
+
import { readFileSync as readFileSync5, writeFileSync } from "fs";
|
|
2338
2341
|
import { Command as Command15 } from "commander";
|
|
2339
2342
|
|
|
2340
|
-
// src/trace
|
|
2341
|
-
import { readFileSync as
|
|
2343
|
+
// src/bkn-trace/schema-validate.ts
|
|
2344
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
2342
2345
|
import { extname } from "path";
|
|
2343
2346
|
import yaml from "js-yaml";
|
|
2344
2347
|
import { z } from "zod";
|
|
@@ -2375,7 +2378,7 @@ var DiagnosisRule = z.object({
|
|
|
2375
2378
|
params: z.record(z.string(), z.unknown()).optional()
|
|
2376
2379
|
});
|
|
2377
2380
|
function parseFile(file) {
|
|
2378
|
-
const text =
|
|
2381
|
+
const text = readFileSync4(file, "utf8");
|
|
2379
2382
|
const ext = extname(file).toLowerCase();
|
|
2380
2383
|
if (ext === ".yaml" || ext === ".yml") return yaml.load(text);
|
|
2381
2384
|
return JSON.parse(text);
|
|
@@ -2414,7 +2417,7 @@ function validateSchemaFile(file, kind) {
|
|
|
2414
2417
|
// src/commands/trace.ts
|
|
2415
2418
|
function traceCommand() {
|
|
2416
2419
|
const cmd = new Command15("trace").description(
|
|
2417
|
-
"Trace
|
|
2420
|
+
"BKN Trace \u2014 fetch spans, diagnose (symbolic + LLM rubric), scan, eval-set, schema validate"
|
|
2418
2421
|
);
|
|
2419
2422
|
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) => {
|
|
2420
2423
|
printJson(
|
|
@@ -2442,7 +2445,7 @@ function traceCommand() {
|
|
|
2442
2445
|
});
|
|
2443
2446
|
const evalSet = cmd.command("eval-set").description("Build + run trace eval sets");
|
|
2444
2447
|
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) => {
|
|
2445
|
-
const raw = JSON.parse(
|
|
2448
|
+
const raw = JSON.parse(readFileSync5(queriesFile, "utf8"));
|
|
2446
2449
|
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2447
2450
|
if (opts.out) {
|
|
2448
2451
|
writeFileSync(opts.out, JSON.stringify({ cases }, null, 2));
|
|
@@ -2452,7 +2455,7 @@ function traceCommand() {
|
|
|
2452
2455
|
}
|
|
2453
2456
|
});
|
|
2454
2457
|
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) => {
|
|
2455
|
-
const raw = JSON.parse(
|
|
2458
|
+
const raw = JSON.parse(readFileSync5(casesFile, "utf8"));
|
|
2456
2459
|
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
2457
2460
|
const result = await clientFrom(cmd2).trace.evalSetTest(opts.agent, cases, {
|
|
2458
2461
|
version: opts.version,
|
|
@@ -2473,14 +2476,35 @@ function traceCommand() {
|
|
|
2473
2476
|
// src/commands/vega.ts
|
|
2474
2477
|
import { Command as Command16 } from "commander";
|
|
2475
2478
|
var int12 = (v) => Number.parseInt(v, 10);
|
|
2479
|
+
var parsePairs2 = (raw) => {
|
|
2480
|
+
if (!raw) return void 0;
|
|
2481
|
+
return raw.split(",").map((part) => {
|
|
2482
|
+
const idx = part.indexOf("=");
|
|
2483
|
+
if (idx < 1) throw new InputError("--extension must be key=value[,key=value]");
|
|
2484
|
+
return { key: part.slice(0, idx).trim(), value: part.slice(idx + 1).trim() };
|
|
2485
|
+
}).filter((p) => p.key.length > 0);
|
|
2486
|
+
};
|
|
2476
2487
|
function vegaCommand() {
|
|
2477
2488
|
const vega = new Command16("vega").description(
|
|
2478
2489
|
"Vega observability \u2014 catalog, resources, index build tasks"
|
|
2479
2490
|
);
|
|
2480
2491
|
const catalog = vega.command("catalog").description("Catalog entries");
|
|
2481
|
-
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) => {
|
|
2492
|
+
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) => {
|
|
2482
2493
|
const o = cmd.optsWithGlobals();
|
|
2483
|
-
const data = await clientFrom(cmd).vega.catalogs({
|
|
2494
|
+
const data = await clientFrom(cmd).vega.catalogs({
|
|
2495
|
+
limit: o.limit,
|
|
2496
|
+
offset: o.offset,
|
|
2497
|
+
name: o.name,
|
|
2498
|
+
tag: o.tag,
|
|
2499
|
+
type: o.type,
|
|
2500
|
+
enabled: o.enabled === void 0 ? void 0 : o.enabled === "true",
|
|
2501
|
+
healthCheckStatus: o.healthCheckStatus,
|
|
2502
|
+
includeExtensions: o.includeExtensions,
|
|
2503
|
+
includeExtensionKeys: o.includeExtensionKeys,
|
|
2504
|
+
extensionPairs: parsePairs2(o.extension),
|
|
2505
|
+
sort: o.sort,
|
|
2506
|
+
direction: o.direction
|
|
2507
|
+
});
|
|
2484
2508
|
printJson(data, outputOptions(cmd));
|
|
2485
2509
|
});
|
|
2486
2510
|
catalog.command("get <id>").description("Get a catalog by id").action(async (id, _opts, cmd) => {
|
|
@@ -2492,21 +2516,41 @@ function vegaCommand() {
|
|
|
2492
2516
|
catalog.command("health <ids...>").description("Health-status for one or more catalogs").action(async (ids, _opts, cmd) => {
|
|
2493
2517
|
printJson(await clientFrom(cmd).vega.catalogHealth(ids), outputOptions(cmd));
|
|
2494
2518
|
});
|
|
2495
|
-
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) => {
|
|
2519
|
+
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) => {
|
|
2496
2520
|
let connectorConfig;
|
|
2497
2521
|
try {
|
|
2498
2522
|
connectorConfig = JSON.parse(opts.connectorConfig);
|
|
2499
2523
|
} catch {
|
|
2500
2524
|
throw new Error("--connector-config must be valid JSON");
|
|
2501
2525
|
}
|
|
2526
|
+
const extensions = opts.extensions ? JSON.parse(opts.extensions) : void 0;
|
|
2502
2527
|
printJson(
|
|
2503
2528
|
await clientFrom(cmd).vega.createCatalog({
|
|
2529
|
+
id: opts.id,
|
|
2504
2530
|
name: opts.name,
|
|
2505
2531
|
connectorType: opts.connectorType,
|
|
2506
2532
|
connectorConfig,
|
|
2507
2533
|
tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
|
|
2508
2534
|
description: opts.description,
|
|
2509
|
-
enabled: opts.enabled ? true : void 0
|
|
2535
|
+
enabled: opts.enabled ? true : void 0,
|
|
2536
|
+
internal: opts.internal ? true : void 0,
|
|
2537
|
+
extensions
|
|
2538
|
+
}),
|
|
2539
|
+
outputOptions(cmd)
|
|
2540
|
+
);
|
|
2541
|
+
});
|
|
2542
|
+
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) => {
|
|
2543
|
+
const connectorConfig = opts.connectorConfig ? JSON.parse(opts.connectorConfig) : void 0;
|
|
2544
|
+
const extensions = opts.extensions ? JSON.parse(opts.extensions) : void 0;
|
|
2545
|
+
printJson(
|
|
2546
|
+
await clientFrom(cmd).vega.updateCatalog(id, {
|
|
2547
|
+
name: opts.name,
|
|
2548
|
+
connectorType: opts.connectorType,
|
|
2549
|
+
connectorConfig,
|
|
2550
|
+
tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
|
|
2551
|
+
description: opts.description,
|
|
2552
|
+
enabled: opts.enabled === void 0 ? void 0 : opts.enabled === "true",
|
|
2553
|
+
extensions
|
|
2510
2554
|
}),
|
|
2511
2555
|
outputOptions(cmd)
|
|
2512
2556
|
);
|
|
@@ -2514,6 +2558,15 @@ function vegaCommand() {
|
|
|
2514
2558
|
catalog.command("enable <id>").description("Enable a catalog (required before discovery)").action(async (id, _opts, cmd) => {
|
|
2515
2559
|
printJson(await clientFrom(cmd).vega.enableCatalog(id), outputOptions(cmd));
|
|
2516
2560
|
});
|
|
2561
|
+
catalog.command("disable <id>").description("Disable a catalog").action(async (id, _opts, cmd) => {
|
|
2562
|
+
printJson(await clientFrom(cmd).vega.disableCatalog(id), outputOptions(cmd));
|
|
2563
|
+
});
|
|
2564
|
+
catalog.command("delete <id>").description("Delete a catalog").action(async (id, _opts, cmd) => {
|
|
2565
|
+
printJson(await clientFrom(cmd).vega.deleteCatalog(id), outputOptions(cmd));
|
|
2566
|
+
});
|
|
2567
|
+
catalog.command("test-connection <id>").description("Test a catalog connection").action(async (id, _opts, cmd) => {
|
|
2568
|
+
printJson(await clientFrom(cmd).vega.testCatalogConnection(id), outputOptions(cmd));
|
|
2569
|
+
});
|
|
2517
2570
|
catalog.command("discover <id>").description("Trigger catalog resource discovery").option("--wait", "wait for discovery to complete").action(async (id, opts, cmd) => {
|
|
2518
2571
|
printJson(
|
|
2519
2572
|
await clientFrom(cmd).vega.discoverCatalog(id, Boolean(opts.wait)),
|
|
@@ -2527,10 +2580,7 @@ function vegaCommand() {
|
|
|
2527
2580
|
connector.command("get <type>").description("Get a connector type").action(async (type, _opts, cmd) => {
|
|
2528
2581
|
printJson(await clientFrom(cmd).vega.connectorType(type), outputOptions(cmd));
|
|
2529
2582
|
});
|
|
2530
|
-
vega.command("sql").description("Run SQL / OpenSearch DSL directly against a vega-backend data source").option(
|
|
2531
|
-
"--resource-type <type>",
|
|
2532
|
-
"source type (mysql | postgresql | opensearch | \u2026); optional \u2014 inferred from the {{<id>}} placeholder"
|
|
2533
|
-
).option(
|
|
2583
|
+
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(
|
|
2534
2584
|
"--query <sql>",
|
|
2535
2585
|
"SQL string; reference a resource with a {{<resource-id>}} placeholder"
|
|
2536
2586
|
).option("--stream-size <n>", "streaming batch size (100\u201310000)", int12).option("--query-timeout <s>", "query timeout in seconds (1\u20133600)", int12).option(
|
|
@@ -2550,9 +2600,8 @@ function vegaCommand() {
|
|
|
2550
2600
|
}
|
|
2551
2601
|
body = {
|
|
2552
2602
|
query: opts.query,
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
...opts.resourceType ? { resource_type: opts.resourceType } : {},
|
|
2603
|
+
resource_type: opts.resourceType,
|
|
2604
|
+
...opts.queryType ? { query_type: opts.queryType } : {},
|
|
2556
2605
|
...opts.streamSize !== void 0 ? { stream_size: opts.streamSize } : {},
|
|
2557
2606
|
...opts.queryTimeout !== void 0 ? { query_timeout: opts.queryTimeout } : {}
|
|
2558
2607
|
};
|
|
@@ -2560,12 +2609,20 @@ function vegaCommand() {
|
|
|
2560
2609
|
printJson(await clientFrom(cmd).vega.sql(body), outputOptions(cmd));
|
|
2561
2610
|
});
|
|
2562
2611
|
const resource = vega.command("resource").description("Vega-backend resources");
|
|
2563
|
-
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) => {
|
|
2612
|
+
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) => {
|
|
2564
2613
|
printJson(
|
|
2565
2614
|
await clientFrom(cmd).resource.list({
|
|
2566
2615
|
datasourceId: opts.datasourceId ?? opts.catalogId,
|
|
2567
2616
|
category: opts.type ?? opts.category,
|
|
2568
|
-
|
|
2617
|
+
status: opts.status,
|
|
2618
|
+
database: opts.database,
|
|
2619
|
+
limit: opts.limit,
|
|
2620
|
+
offset: opts.offset,
|
|
2621
|
+
includeExtensions: opts.includeExtensions,
|
|
2622
|
+
includeExtensionKeys: opts.includeExtensionKeys,
|
|
2623
|
+
extensionPairs: parsePairs2(opts.extension),
|
|
2624
|
+
sort: opts.sort,
|
|
2625
|
+
direction: opts.direction
|
|
2569
2626
|
}),
|
|
2570
2627
|
outputOptions(cmd)
|
|
2571
2628
|
);
|
|
@@ -2583,16 +2640,25 @@ function vegaCommand() {
|
|
|
2583
2640
|
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(
|
|
2584
2641
|
"--build-key-fields <list>",
|
|
2585
2642
|
"comma-separated key fields (batch: time; streaming: row id)"
|
|
2586
|
-
).option("--embedding-model <id>", "embedding model id
|
|
2643
|
+
).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) => {
|
|
2587
2644
|
const o = cmd.optsWithGlobals();
|
|
2645
|
+
const embeddingFields = csv(o.embeddingFields);
|
|
2646
|
+
const buildKeyFields = csv(o.buildKeyFields);
|
|
2647
|
+
const fulltextFields = csv(o.fulltextFields);
|
|
2648
|
+
if (embeddingFields || buildKeyFields || o.embeddingModel || fulltextFields || o.fulltextAnalyzer) {
|
|
2649
|
+
await clientFrom(cmd).resource.configureIndex(resourceId, {
|
|
2650
|
+
embeddingFields,
|
|
2651
|
+
buildKeyFields,
|
|
2652
|
+
embeddingModel: o.embeddingModel,
|
|
2653
|
+
fulltextFields,
|
|
2654
|
+
fulltextAnalyzer: o.fulltextAnalyzer
|
|
2655
|
+
});
|
|
2656
|
+
}
|
|
2588
2657
|
const task = await clientFrom(cmd).vega.build(
|
|
2589
2658
|
{
|
|
2590
2659
|
resource_id: resourceId,
|
|
2591
2660
|
mode: o.mode,
|
|
2592
|
-
|
|
2593
|
-
build_key_fields: csv(o.buildKeyFields),
|
|
2594
|
-
embedding_model: o.embeddingModel,
|
|
2595
|
-
model_dimensions: o.modelDimensions
|
|
2661
|
+
execute_type: o.executeType
|
|
2596
2662
|
},
|
|
2597
2663
|
{ wait: Boolean(o.wait), timeoutMs: o.timeout * 1e3 }
|
|
2598
2664
|
);
|
|
@@ -2602,6 +2668,40 @@ function vegaCommand() {
|
|
|
2602
2668
|
const task = await clientFrom(cmd).vega.buildStatus(taskId);
|
|
2603
2669
|
printJson(task, outputOptions(cmd));
|
|
2604
2670
|
});
|
|
2671
|
+
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) => {
|
|
2672
|
+
printJson(
|
|
2673
|
+
await clientFrom(cmd).vega.buildTasks({
|
|
2674
|
+
limit: opts.limit,
|
|
2675
|
+
offset: opts.offset,
|
|
2676
|
+
resourceId: opts.resourceId,
|
|
2677
|
+
catalogId: opts.catalogId,
|
|
2678
|
+
status: opts.status,
|
|
2679
|
+
active: opts.active,
|
|
2680
|
+
mode: opts.mode,
|
|
2681
|
+
orderBy: opts.orderBy,
|
|
2682
|
+
order: opts.order
|
|
2683
|
+
}),
|
|
2684
|
+
outputOptions(cmd)
|
|
2685
|
+
);
|
|
2686
|
+
});
|
|
2687
|
+
dataset.command("build-start <task-id>").description("Start a BuildTask").option("--reset", "restart from the beginning").action(async (taskId, opts, cmd) => {
|
|
2688
|
+
printJson(
|
|
2689
|
+
await clientFrom(cmd).vega.startBuildTask(taskId, { reset: opts.reset }),
|
|
2690
|
+
outputOptions(cmd)
|
|
2691
|
+
);
|
|
2692
|
+
});
|
|
2693
|
+
dataset.command("build-stop <task-id>").description("Stop a BuildTask").action(async (taskId, _opts, cmd) => {
|
|
2694
|
+
printJson(await clientFrom(cmd).vega.stopBuildTask(taskId), outputOptions(cmd));
|
|
2695
|
+
});
|
|
2696
|
+
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) => {
|
|
2697
|
+
printJson(
|
|
2698
|
+
await clientFrom(cmd).vega.deleteBuildTasks(ids, {
|
|
2699
|
+
ignoreMissing: opts.ignoreMissing,
|
|
2700
|
+
deleteActiveIndex: opts.deleteActiveIndex
|
|
2701
|
+
}),
|
|
2702
|
+
outputOptions(cmd)
|
|
2703
|
+
);
|
|
2704
|
+
});
|
|
2605
2705
|
return group(vega, "AI DATA PLATFORM");
|
|
2606
2706
|
}
|
|
2607
2707
|
|