@openbkn/bkn-sdk 0.1.5-rc.1 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -7
- package/README.zh.md +53 -1
- package/dist/{chunk-WIYRGBAB.js → chunk-ORVEVDGJ.js} +3965 -1810
- package/dist/cli.js +2259 -830
- package/dist/index.d.ts +2300 -1032
- package/dist/index.js +9 -3
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
AUDIT_LOG_MAX_LIMIT,
|
|
4
|
+
BuildMode,
|
|
3
5
|
BuildTaskExecuteType,
|
|
4
6
|
BuildTaskSort,
|
|
5
7
|
BuildTaskStatus,
|
|
6
|
-
|
|
8
|
+
CatalogHealthCheckStatus,
|
|
9
|
+
ConnectorCategory,
|
|
10
|
+
ConnectorMode,
|
|
7
11
|
DEFAULT_LIST_LIMIT,
|
|
8
12
|
DEFAULT_QUERY_LIMIT,
|
|
9
13
|
DiscoverScheduleSort,
|
|
@@ -11,17 +15,28 @@ import {
|
|
|
11
15
|
DiscoverTaskSort,
|
|
12
16
|
DiscoverTaskTriggerType,
|
|
13
17
|
DryRunSignal,
|
|
18
|
+
FUNCTION_TEMPLATE_TYPES,
|
|
19
|
+
FunctionAiGenerationType,
|
|
14
20
|
HttpError,
|
|
21
|
+
IMPEX_TYPES,
|
|
15
22
|
InputError,
|
|
23
|
+
ResourceCategory,
|
|
24
|
+
ResourceStatus,
|
|
25
|
+
SKILL_SOURCES,
|
|
26
|
+
SKILL_STATUSES,
|
|
16
27
|
SemanticUnderstandingApplyMode,
|
|
17
28
|
SemanticUnderstandingScope,
|
|
18
29
|
SemanticUnderstandingTaskSort,
|
|
19
30
|
SortDirection,
|
|
31
|
+
TOOL_METADATA_TYPES,
|
|
20
32
|
VegaTaskStatus,
|
|
33
|
+
WaitTimeoutError,
|
|
21
34
|
activePlatform,
|
|
22
35
|
attachToken,
|
|
36
|
+
buildTaskState,
|
|
23
37
|
changePasswordSafe,
|
|
24
38
|
classifyPath,
|
|
39
|
+
configureVersionCheck,
|
|
25
40
|
createClient,
|
|
26
41
|
credentialDeviceLogin,
|
|
27
42
|
currentToken,
|
|
@@ -30,17 +45,19 @@ import {
|
|
|
30
45
|
deletePlatform,
|
|
31
46
|
deviceLogin,
|
|
32
47
|
enableDryRun,
|
|
48
|
+
ensureCompatible,
|
|
33
49
|
exportCreds,
|
|
34
50
|
filesUnder,
|
|
35
51
|
formatError,
|
|
36
|
-
|
|
52
|
+
getMeSafe,
|
|
53
|
+
isBuildTaskUnsuccessful,
|
|
37
54
|
isHeadless,
|
|
38
55
|
lifecycleHint,
|
|
39
56
|
listPlatforms,
|
|
40
57
|
logout,
|
|
41
58
|
openBrowser,
|
|
59
|
+
package_default,
|
|
42
60
|
parseBigIntJSON,
|
|
43
|
-
parseEmbeddingFields,
|
|
44
61
|
parsePkMap,
|
|
45
62
|
rawCall,
|
|
46
63
|
readPlatformConfig,
|
|
@@ -48,6 +65,8 @@ import {
|
|
|
48
65
|
renderReportMarkdown,
|
|
49
66
|
renderTree,
|
|
50
67
|
resolveContext,
|
|
68
|
+
scopeFromKinds,
|
|
69
|
+
sessionInsecure,
|
|
51
70
|
setActivePlatform,
|
|
52
71
|
status,
|
|
53
72
|
stringifyBigIntJSON,
|
|
@@ -56,83 +75,17 @@ import {
|
|
|
56
75
|
trimTrailingSlashes,
|
|
57
76
|
updatePlatformConfig,
|
|
58
77
|
use,
|
|
78
|
+
validateBknDirectory,
|
|
59
79
|
validateFixturePath,
|
|
60
80
|
whoami
|
|
61
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-ORVEVDGJ.js";
|
|
62
82
|
|
|
63
83
|
// src/cli-program.ts
|
|
64
|
-
import { Command as
|
|
65
|
-
|
|
66
|
-
// package.json
|
|
67
|
-
var package_default = {
|
|
68
|
-
name: "@openbkn/bkn-sdk",
|
|
69
|
-
version: "0.1.5-rc.1",
|
|
70
|
-
description: "Unified TypeScript SDK + CLI for the BKN (Business Knowledge Network) platform.",
|
|
71
|
-
type: "module",
|
|
72
|
-
license: "Apache-2.0",
|
|
73
|
-
engines: {
|
|
74
|
-
node: ">=22.19.0"
|
|
75
|
-
},
|
|
76
|
-
bin: {
|
|
77
|
-
openbkn: "./dist/cli.js"
|
|
78
|
-
},
|
|
79
|
-
main: "./dist/index.js",
|
|
80
|
-
types: "./dist/index.d.ts",
|
|
81
|
-
exports: {
|
|
82
|
-
".": {
|
|
83
|
-
types: "./dist/index.d.ts",
|
|
84
|
-
import: "./dist/index.js"
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
files: ["dist", "!dist/**/*.map", "README.md", "README.zh.md", "LICENSE", "NOTICE"],
|
|
88
|
-
publishConfig: {
|
|
89
|
-
access: "public"
|
|
90
|
-
},
|
|
91
|
-
repository: {
|
|
92
|
-
type: "git",
|
|
93
|
-
url: "git+https://github.com/openbkn-ai/bkn-sdk.git"
|
|
94
|
-
},
|
|
95
|
-
keywords: ["bkn", "openbkn", "knowledge-network", "cli", "sdk", "typescript"],
|
|
96
|
-
scripts: {
|
|
97
|
-
build: "tsup",
|
|
98
|
-
dev: "tsup --watch",
|
|
99
|
-
typecheck: "tsc --noEmit",
|
|
100
|
-
"check:deps": "node scripts/check-no-self-dep.mjs",
|
|
101
|
-
"capture:returns": "node scripts/capture-returns.mjs",
|
|
102
|
-
lint: "npm run check:deps && biome check . && tsc --noEmit",
|
|
103
|
-
format: "biome format --write .",
|
|
104
|
-
test: "vitest run",
|
|
105
|
-
"test:e2e:trace-business": "npm run build && node test/e2e/bkn-trace-business-interaction.mjs",
|
|
106
|
-
"test:e2e:smoke": "npm run build && test/e2e/live-smoke.sh",
|
|
107
|
-
"test:e2e:suite": "npm run build && test/e2e/live-suite.sh",
|
|
108
|
-
"test:e2e:write": "npm run build && test/e2e/live-write.sh",
|
|
109
|
-
"test:cover": "vitest run --coverage",
|
|
110
|
-
ci: "npm run lint && npm test",
|
|
111
|
-
prepublishOnly: "npm run ci && npm run build"
|
|
112
|
-
},
|
|
113
|
-
dependencies: {
|
|
114
|
-
"@clack/prompts": "^0.9.1",
|
|
115
|
-
chalk: "^5.4.1",
|
|
116
|
-
commander: "^13.1.0",
|
|
117
|
-
"csv-parse": "^6.2.1",
|
|
118
|
-
"js-yaml": "^4.3.0",
|
|
119
|
-
jszip: "^3.10.1",
|
|
120
|
-
undici: "^8.9.0",
|
|
121
|
-
zod: "^3.24.1"
|
|
122
|
-
},
|
|
123
|
-
devDependencies: {
|
|
124
|
-
"@biomejs/biome": "^1.9.4",
|
|
125
|
-
"@types/js-yaml": "^4.0.9",
|
|
126
|
-
"@types/node": "^24.0.0",
|
|
127
|
-
tsup: "^8.4.0",
|
|
128
|
-
typescript: "^5.8.0",
|
|
129
|
-
vitest: "^3.0.0"
|
|
130
|
-
}
|
|
131
|
-
};
|
|
84
|
+
import { Command as Command17 } from "commander";
|
|
132
85
|
|
|
133
86
|
// src/commands/admin.ts
|
|
134
87
|
import { readFileSync as readFileSync2 } from "fs";
|
|
135
|
-
import { Command as Command2 } from "commander";
|
|
88
|
+
import { Command as Command2, Option } from "commander";
|
|
136
89
|
|
|
137
90
|
// src/help/grouped-help.ts
|
|
138
91
|
var GROUP = /* @__PURE__ */ Symbol("openbkn.group");
|
|
@@ -161,11 +114,11 @@ var VERB_SECTIONS = [
|
|
|
161
114
|
"READ"
|
|
162
115
|
],
|
|
163
116
|
[
|
|
164
|
-
/^(query|execute|debug|run|test|chat|embeddings|rerank|diagnose|scan|discover|build|dry-run|validate|token|download|install|call|sql|receipt|fingerprint|test-connection|test-connection-config|attempt|retry|start|resume|ensure-current|create-new-generation|close|complete|fail|cancel|handoff|operations
|
|
117
|
+
/^(query|execute|debug|run|test|chat|embeddings|rerank|diagnose|scan|discover|build|dry-run|validate|token|download|install|call|sql|receipt|fingerprint|test-connection|test-connection-config|attempt|retry|start|stop|resume|ensure-current|create-new-generation|close|complete|fail|cancel|handoff|operations)$/,
|
|
165
118
|
"RUN"
|
|
166
119
|
],
|
|
167
120
|
[
|
|
168
|
-
/^(create|update|delete|add|edit|remove|set|register|upload|publish|unpublish|republish|import|activate|login|logout|use|switch|change-password|enable|disable|push|assign-role|revoke-role|add-member|remove-member|reset-password|grant-perm|revoke-perm|add-members|remove-members|set-status|regenerate|revoke|
|
|
121
|
+
/^(create|update|delete|add|edit|remove|set|register|upload|publish|unpublish|republish|import|activate|login|logout|use|switch|change-password|enable|disable|push|assign-role|revoke-role|add-member|remove-member|reset-password|grant-perm|revoke-perm|add-members|remove-members|set-status|regenerate|revoke|publish-history|update-metadata|update-package|create-from-catalog|export-config)$/,
|
|
169
122
|
"WRITE"
|
|
170
123
|
]
|
|
171
124
|
];
|
|
@@ -314,7 +267,8 @@ var ROW_ENVELOPES = [
|
|
|
314
267
|
"roles",
|
|
315
268
|
"departments",
|
|
316
269
|
"members",
|
|
317
|
-
"keys"
|
|
270
|
+
"keys",
|
|
271
|
+
"logs"
|
|
318
272
|
];
|
|
319
273
|
function toRows(value) {
|
|
320
274
|
const isRowArray = (v) => Array.isArray(v) && v.length > 0 && v.every((x) => x !== null && typeof x === "object" && !Array.isArray(x));
|
|
@@ -401,7 +355,7 @@ function stringifyCell(v) {
|
|
|
401
355
|
// src/utils/prompt.ts
|
|
402
356
|
import { createInterface } from "readline";
|
|
403
357
|
function promptLine(query, hidden = false) {
|
|
404
|
-
return new Promise((
|
|
358
|
+
return new Promise((resolve2) => {
|
|
405
359
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
406
360
|
if (hidden) {
|
|
407
361
|
const mutable = rl;
|
|
@@ -412,7 +366,7 @@ function promptLine(query, hidden = false) {
|
|
|
412
366
|
rl.question(query, (answer) => {
|
|
413
367
|
rl.close();
|
|
414
368
|
if (hidden) process.stdout.write("\n");
|
|
415
|
-
|
|
369
|
+
resolve2(answer.trim());
|
|
416
370
|
});
|
|
417
371
|
});
|
|
418
372
|
}
|
|
@@ -446,6 +400,17 @@ function traceOptionsFrom(o) {
|
|
|
446
400
|
...interactionId ? { interactionId } : {}
|
|
447
401
|
};
|
|
448
402
|
}
|
|
403
|
+
function retryOptionsFrom(o) {
|
|
404
|
+
return {
|
|
405
|
+
retry: o.retry !== false,
|
|
406
|
+
onRetry: (n) => {
|
|
407
|
+
process.stderr.write(
|
|
408
|
+
`openbkn: ${n.method} ${new URL(n.url).pathname} failed (${n.reason}); retry ${n.attempt}/${n.retries} in ${n.delayMs / 1e3}s
|
|
409
|
+
`
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
449
414
|
function clientFrom(cmd) {
|
|
450
415
|
const o = cmd.optsWithGlobals();
|
|
451
416
|
const trace = traceOptionsFrom(o);
|
|
@@ -455,8 +420,9 @@ function clientFrom(cmd) {
|
|
|
455
420
|
baseUrl: o.baseUrl,
|
|
456
421
|
token: o.token,
|
|
457
422
|
user: o.user,
|
|
458
|
-
businessDomain: o.bizDomain,
|
|
459
423
|
insecure: o.insecure,
|
|
424
|
+
versionCheckMode: "cli",
|
|
425
|
+
...retryOptionsFrom(o),
|
|
460
426
|
...trace ? { trace } : {},
|
|
461
427
|
...remembered.source === "stored" && remembered.id ? { rememberedConversationId: remembered.id } : {},
|
|
462
428
|
// Remember a conversation this run opens, so the next command continues the
|
|
@@ -484,10 +450,67 @@ function outputOptions(cmd) {
|
|
|
484
450
|
const o = cmd.optsWithGlobals();
|
|
485
451
|
return { json: Boolean(o.json), compact: Boolean(o.compact), full: Boolean(o.full) };
|
|
486
452
|
}
|
|
453
|
+
var positiveInt = (flag, max) => (v) => {
|
|
454
|
+
const bound = max === void 0 ? "a positive integer" : `an integer from 1 to ${max}`;
|
|
455
|
+
if (!/^\d+$/.test(v)) throw new InputError(`${flag} must be ${bound} (got '${v}')`);
|
|
456
|
+
const n = Number.parseInt(v, 10);
|
|
457
|
+
if (!Number.isSafeInteger(n) || n <= 0 || max !== void 0 && n > max) {
|
|
458
|
+
throw new InputError(`${flag} must be ${bound} (got '${v}')`);
|
|
459
|
+
}
|
|
460
|
+
return n;
|
|
461
|
+
};
|
|
462
|
+
var MAX_PAGE_SIZE = 100;
|
|
463
|
+
var oneOf = (flag, values) => (v) => {
|
|
464
|
+
if (values.includes(v)) return v;
|
|
465
|
+
throw new InputError(`${flag} must be one of: ${values.join(" | ")} (got '${v}')`);
|
|
466
|
+
};
|
|
487
467
|
function csv(value) {
|
|
488
468
|
if (!value) return void 0;
|
|
489
469
|
return value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
490
470
|
}
|
|
471
|
+
function readJsonArgs(opts, required = false) {
|
|
472
|
+
if (opts.args !== void 0 && opts.argsFile !== void 0) {
|
|
473
|
+
throw new InputError("--args and --args-file cannot be combined");
|
|
474
|
+
}
|
|
475
|
+
const file = opts.argsFile ?? (opts.args === "-" ? "-" : void 0);
|
|
476
|
+
let raw = opts.args;
|
|
477
|
+
if (file !== void 0) {
|
|
478
|
+
try {
|
|
479
|
+
raw = readFileSync(file === "-" ? 0 : file, "utf8");
|
|
480
|
+
} catch (error) {
|
|
481
|
+
throw new InputError(
|
|
482
|
+
`Cannot read ${file === "-" ? "stdin" : `--args-file '${file}'`}: ${error instanceof Error ? error.message : error}`
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
if (raw === void 0) {
|
|
487
|
+
if (required) throw new InputError("--args is required (run with --schema to see its shape)");
|
|
488
|
+
return void 0;
|
|
489
|
+
}
|
|
490
|
+
let parsed;
|
|
491
|
+
try {
|
|
492
|
+
parsed = parseBigIntJSON(raw);
|
|
493
|
+
} catch {
|
|
494
|
+
throw new InputError("--args must be valid JSON");
|
|
495
|
+
}
|
|
496
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
497
|
+
throw new InputError("--args must be a JSON object");
|
|
498
|
+
}
|
|
499
|
+
return parsed;
|
|
500
|
+
}
|
|
501
|
+
function cypherParams(raw) {
|
|
502
|
+
if (raw === void 0) return void 0;
|
|
503
|
+
let parsed;
|
|
504
|
+
try {
|
|
505
|
+
parsed = parseBigIntJSON(raw);
|
|
506
|
+
} catch {
|
|
507
|
+
throw new InputError("--params is not valid JSON.");
|
|
508
|
+
}
|
|
509
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
510
|
+
throw new InputError(`--params must be a JSON object, as in '{"floor": 100}'.`);
|
|
511
|
+
}
|
|
512
|
+
return parsed;
|
|
513
|
+
}
|
|
491
514
|
function readBody(opts) {
|
|
492
515
|
const raw = opts.bodyFile ? readFileSync(opts.bodyFile, "utf8") : opts.body;
|
|
493
516
|
if (!raw) throw new InputError("Provide --body '<json>' or --body-file <path>.");
|
|
@@ -500,19 +523,50 @@ function readBody(opts) {
|
|
|
500
523
|
|
|
501
524
|
// src/commands/auth.ts
|
|
502
525
|
import { Command } from "commander";
|
|
503
|
-
async function resolveAccount(
|
|
504
|
-
const
|
|
505
|
-
if (
|
|
526
|
+
async function resolveAccount(ctx, idToken) {
|
|
527
|
+
const claims = decodeJwt(idToken ?? ctx.token);
|
|
528
|
+
if (claims?.preferred_username) return claims.preferred_username;
|
|
529
|
+
if (!claims?.sub) return void 0;
|
|
506
530
|
try {
|
|
507
|
-
const u = await
|
|
508
|
-
|
|
509
|
-
sub
|
|
510
|
-
);
|
|
511
|
-
return u.account;
|
|
531
|
+
const u = await getMeSafe(ctx);
|
|
532
|
+
return u?.account;
|
|
512
533
|
} catch {
|
|
513
534
|
return void 0;
|
|
514
535
|
}
|
|
515
536
|
}
|
|
537
|
+
async function verifyLoginPlatform(ctx) {
|
|
538
|
+
await ensureCompatible(ctx, new URL(ctx.baseUrl));
|
|
539
|
+
}
|
|
540
|
+
function loginContext(baseUrl, token, insecure, options) {
|
|
541
|
+
const ctx = {
|
|
542
|
+
baseUrl: trimTrailingSlashes(baseUrl),
|
|
543
|
+
token,
|
|
544
|
+
insecure: Boolean(insecure),
|
|
545
|
+
...retryOptionsFrom(options)
|
|
546
|
+
};
|
|
547
|
+
configureVersionCheck(ctx, "login");
|
|
548
|
+
return ctx;
|
|
549
|
+
}
|
|
550
|
+
function warnEnvShadow(baseUrl) {
|
|
551
|
+
const notes = [];
|
|
552
|
+
const vars = [];
|
|
553
|
+
if (process.env.BKN_TOKEN) {
|
|
554
|
+
notes.push("BKN_TOKEN is set \u2014 other commands send it instead of this session's token.");
|
|
555
|
+
vars.push("BKN_TOKEN");
|
|
556
|
+
}
|
|
557
|
+
const envBase = process.env.BKN_BASE_URL;
|
|
558
|
+
if (envBase && baseUrl && trimTrailingSlashes(envBase) !== trimTrailingSlashes(baseUrl)) {
|
|
559
|
+
notes.push(
|
|
560
|
+
"BKN_BASE_URL is set to a different platform \u2014 other commands use it instead of this saved session."
|
|
561
|
+
);
|
|
562
|
+
vars.push("BKN_BASE_URL");
|
|
563
|
+
}
|
|
564
|
+
if (vars.length === 0) return;
|
|
565
|
+
process.stderr.write(
|
|
566
|
+
`warning: ${notes.join(" ")} To use the saved session: \`unset ${vars.join(" ")}\`
|
|
567
|
+
`
|
|
568
|
+
);
|
|
569
|
+
}
|
|
516
570
|
function renderSessions(items) {
|
|
517
571
|
const byPlatform = /* @__PURE__ */ new Map();
|
|
518
572
|
for (const it of items) {
|
|
@@ -543,9 +597,11 @@ function registerAuthLeaves(cmd) {
|
|
|
543
597
|
process.stdout.write(`Logged in to ${r.baseUrl ?? url} as ${r.username ?? r.userId}
|
|
544
598
|
`);
|
|
545
599
|
}
|
|
600
|
+
warnEnvShadow(r.baseUrl ?? url);
|
|
546
601
|
};
|
|
547
602
|
const token = opts.token ?? g.token;
|
|
548
603
|
if (token) {
|
|
604
|
+
await verifyLoginPlatform(loginContext(url, token, g.insecure, g));
|
|
549
605
|
report(attachToken(url, token, { insecure: g.insecure }));
|
|
550
606
|
return;
|
|
551
607
|
}
|
|
@@ -594,18 +650,16 @@ User code: ${userCode}
|
|
|
594
650
|
}
|
|
595
651
|
throw e;
|
|
596
652
|
}
|
|
653
|
+
const authenticatedContext = loginContext(url, tokens.accessToken, g.insecure, g);
|
|
654
|
+
await verifyLoginPlatform(authenticatedContext);
|
|
597
655
|
if (!account) {
|
|
598
|
-
account = await resolveAccount(
|
|
599
|
-
url,
|
|
600
|
-
tokens.accessToken,
|
|
601
|
-
Boolean(g.insecure),
|
|
602
|
-
tokens.idToken
|
|
603
|
-
);
|
|
656
|
+
account = await resolveAccount(authenticatedContext, tokens.idToken);
|
|
604
657
|
}
|
|
605
658
|
report(
|
|
606
659
|
attachToken(url, tokens.accessToken, {
|
|
607
660
|
refreshToken: tokens.refreshToken,
|
|
608
661
|
idToken: tokens.idToken,
|
|
662
|
+
expiresAt: tokens.expiresAt,
|
|
609
663
|
username: account,
|
|
610
664
|
insecure: g.insecure
|
|
611
665
|
})
|
|
@@ -620,25 +674,22 @@ User code: ${userCode}
|
|
|
620
674
|
process.stdout.write(`${token}
|
|
621
675
|
`);
|
|
622
676
|
});
|
|
623
|
-
cmd.command("whoami [url]").description("Show current user identity (from the token)").option("--no-lookup", "skip the backend identity
|
|
677
|
+
cmd.command("whoami [url]").description("Show current user identity (from the token)").option("--no-lookup", "skip the backend identity lookup (bkn-safe /me)").action(async (_url, opts, cmd2) => {
|
|
624
678
|
const g = cmd2.optsWithGlobals();
|
|
625
679
|
const me = whoami({ user: g.user });
|
|
626
680
|
if (opts.lookup !== false && me.baseUrl && me.sub) {
|
|
627
681
|
try {
|
|
628
|
-
const u = await
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
insecure: Boolean(g.insecure)
|
|
634
|
-
},
|
|
635
|
-
me.sub
|
|
636
|
-
);
|
|
682
|
+
const u = await getMeSafe({
|
|
683
|
+
baseUrl: me.baseUrl,
|
|
684
|
+
token: currentToken({ user: g.user }),
|
|
685
|
+
insecure: g.insecure ?? sessionInsecure({ user: g.user })
|
|
686
|
+
});
|
|
637
687
|
if (u.account) me.username = u.account;
|
|
638
688
|
if (u.name) me.name = u.name;
|
|
639
689
|
} catch {
|
|
640
690
|
}
|
|
641
691
|
}
|
|
692
|
+
warnEnvShadow(me.baseUrl);
|
|
642
693
|
const out = outputOptions(cmd2);
|
|
643
694
|
if (out.json || out.compact || out.full) {
|
|
644
695
|
printJson(me, out);
|
|
@@ -699,8 +750,9 @@ User code: ${userCode}
|
|
|
699
750
|
baseUrl: url ?? g.baseUrl,
|
|
700
751
|
token: g.token,
|
|
701
752
|
user: g.user,
|
|
702
|
-
|
|
703
|
-
|
|
753
|
+
insecure: g.insecure,
|
|
754
|
+
versionCheckMode: "cli",
|
|
755
|
+
...retryOptionsFrom(g)
|
|
704
756
|
});
|
|
705
757
|
const account = opts.account ?? await promptLine("Account: ");
|
|
706
758
|
const oldPassword = opts.oldPassword ?? await promptLine("Current password: ", true);
|
|
@@ -758,6 +810,24 @@ TOKENS
|
|
|
758
810
|
|
|
759
811
|
// src/commands/admin.ts
|
|
760
812
|
var int = (v) => Number.parseInt(v, 10);
|
|
813
|
+
var NEW_USER_PASSWORD_ENV = "BKN_NEW_USER_PASSWORD";
|
|
814
|
+
async function newUserPassword(opts) {
|
|
815
|
+
if (opts.password) return opts.password;
|
|
816
|
+
if (opts.promptPassword) {
|
|
817
|
+
const typed = await promptLine("Initial password: ", true);
|
|
818
|
+
if (typed) return typed;
|
|
819
|
+
throw new InputError("No password entered.");
|
|
820
|
+
}
|
|
821
|
+
const fromEnv = process.env[NEW_USER_PASSWORD_ENV];
|
|
822
|
+
if (fromEnv) return fromEnv;
|
|
823
|
+
throw new InputError(
|
|
824
|
+
`A new user needs an initial password: pass --password, --prompt-password, or set ${NEW_USER_PASSWORD_ENV}.`
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
function departmentIds(values) {
|
|
828
|
+
if (values === void 0) return void 0;
|
|
829
|
+
return values.flatMap((v) => v.split(",")).map((v) => v.trim()).filter((v) => v && v !== "-1");
|
|
830
|
+
}
|
|
761
831
|
var DEFAULT_RESET_PASSWORD = "openbkn";
|
|
762
832
|
async function importLicenseFile(cmd, file, receipt) {
|
|
763
833
|
const text = readFileSync2(file, "utf8");
|
|
@@ -769,10 +839,9 @@ function adminCommand() {
|
|
|
769
839
|
const admin = new Command2("admin").description("Orgs, users, roles, license, audit log");
|
|
770
840
|
registerAuthLeaves(admin.command("auth").description("Operator authentication"));
|
|
771
841
|
const org = admin.command("org").description("Departments and org structure");
|
|
772
|
-
org.command("list").description("List departments \u2192 {departments, total}").option("--
|
|
842
|
+
org.command("list").description("List departments \u2192 {departments, total}").option("--name <s>", "filter by name").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).action(async (opts, cmd) => {
|
|
773
843
|
printJson(
|
|
774
844
|
await clientFrom(cmd).admin.orgList({
|
|
775
|
-
role: opts.role,
|
|
776
845
|
name: opts.name,
|
|
777
846
|
limit: opts.limit,
|
|
778
847
|
offset: opts.offset
|
|
@@ -783,39 +852,37 @@ function adminCommand() {
|
|
|
783
852
|
org.command("get <id>").description("Get one department").action(async (id, _opts, cmd) => {
|
|
784
853
|
printJson(await clientFrom(cmd).admin.orgGet(id), outputOptions(cmd));
|
|
785
854
|
});
|
|
786
|
-
org.command("members <id>").description("List members of a department
|
|
855
|
+
org.command("members <id>").description("List direct members of a department \u2192 {users, total}").option("--limit <n>", "page size (default: all members)", int).option("--offset <n>", "page offset", int).action(async (id, opts, cmd) => {
|
|
787
856
|
printJson(
|
|
788
857
|
await clientFrom(cmd).admin.orgMembers(id, {
|
|
789
|
-
role: opts.role,
|
|
790
858
|
limit: opts.limit,
|
|
791
859
|
offset: opts.offset
|
|
792
860
|
}),
|
|
793
861
|
outputOptions(cmd)
|
|
794
862
|
);
|
|
795
863
|
});
|
|
796
|
-
org.command("create").description("Create a department").requiredOption("--name <s>", "department name").option("--parent <id>", "parent department id
|
|
864
|
+
org.command("create").description("Create a department").requiredOption("--name <s>", "department name").option("--parent <id>", "parent department id (omit for a root department)").option("--code <s>", "department code").option("--remark <s>", "remark").option("--email <s>", "email").option("--manager <id>", "manager user id").action(async (opts, cmd) => {
|
|
797
865
|
printJson(
|
|
798
866
|
await clientFrom(cmd).admin.orgCreate({
|
|
799
867
|
name: opts.name,
|
|
800
|
-
|
|
868
|
+
// "-1" was the ISF spelling of "no parent"; bkn-safe wants none.
|
|
869
|
+
parentId: opts.parent === "-1" ? void 0 : opts.parent,
|
|
801
870
|
code: opts.code,
|
|
802
871
|
remark: opts.remark,
|
|
803
872
|
email: opts.email,
|
|
804
|
-
managerID: opts.manager
|
|
805
|
-
status: opts.status
|
|
873
|
+
managerID: opts.manager
|
|
806
874
|
}),
|
|
807
875
|
outputOptions(cmd)
|
|
808
876
|
);
|
|
809
877
|
});
|
|
810
|
-
org.command("update <id>").description("Update a department (only provided fields change)").option("--name <s>", "new name").option("--code <s>", "department code").option("--remark <s>", "remark").option("--email <s>", "email").option("--manager <id>", "manager user id").
|
|
878
|
+
org.command("update <id>").description("Update a department (only provided fields change)").option("--name <s>", "new name").option("--code <s>", "department code").option("--remark <s>", "remark").option("--email <s>", "email").option("--manager <id>", "manager user id").action(async (id, opts, cmd) => {
|
|
811
879
|
printJson(
|
|
812
880
|
await clientFrom(cmd).admin.orgUpdate(id, {
|
|
813
881
|
name: opts.name,
|
|
814
882
|
code: opts.code,
|
|
815
883
|
remark: opts.remark,
|
|
816
884
|
email: opts.email,
|
|
817
|
-
managerID: opts.manager
|
|
818
|
-
status: opts.status
|
|
885
|
+
managerID: opts.manager
|
|
819
886
|
}),
|
|
820
887
|
outputOptions(cmd)
|
|
821
888
|
);
|
|
@@ -823,14 +890,14 @@ function adminCommand() {
|
|
|
823
890
|
org.command("delete <id>").description("Delete a department").action(async (id, _opts, cmd) => {
|
|
824
891
|
printJson(await clientFrom(cmd).admin.orgDelete(id), outputOptions(cmd));
|
|
825
892
|
});
|
|
826
|
-
org.command("tree").description("Print the department hierarchy").
|
|
827
|
-
const tree = await clientFrom(cmd).admin.orgTree(
|
|
893
|
+
org.command("tree").description("Print the department hierarchy").action(async (_opts, cmd) => {
|
|
894
|
+
const tree = await clientFrom(cmd).admin.orgTree();
|
|
828
895
|
const out = outputOptions(cmd);
|
|
829
896
|
if (out.json) printJson(tree, out);
|
|
830
897
|
else console.log(renderOrgTree(tree));
|
|
831
898
|
});
|
|
832
899
|
const user = admin.command("user").description("User management");
|
|
833
|
-
user.command("list").description("List users \u2192 {users, total}").option("--org <id>", "
|
|
900
|
+
user.command("list").description("List users \u2192 {users, total}").option("--org <id>", "only direct members of this department").option("--keyword <s>", "filter by name").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).action(async (opts, cmd) => {
|
|
834
901
|
printJson(
|
|
835
902
|
await clientFrom(cmd).admin.userList({
|
|
836
903
|
orgId: opts.org,
|
|
@@ -859,35 +926,27 @@ function adminCommand() {
|
|
|
859
926
|
user.command("roles <user>").description("List roles granted to a user").action(async (userId, _opts, cmd) => {
|
|
860
927
|
printJson(await clientFrom(cmd).admin.userRoles(userId), outputOptions(cmd));
|
|
861
928
|
});
|
|
862
|
-
user.command("create").description("Create a user (
|
|
929
|
+
user.command("create").description("Create a user with an explicit initial password (must change on first login)").requiredOption("--login <name>", "login name").option("--password <s>", `initial password (or set ${NEW_USER_PASSWORD_ENV})`).option("--prompt-password", "type the initial password interactively (input hidden)").option("--display-name <s>", "display name").option("--email <s>", "email").option("--department <id...>", "initial department id(s)").option("--tel <s>", "telephone").action(async (opts, cmd) => {
|
|
930
|
+
const password = await newUserPassword(opts);
|
|
863
931
|
printJson(
|
|
864
932
|
await clientFrom(cmd).admin.userCreate({
|
|
865
933
|
loginName: opts.login,
|
|
934
|
+
password,
|
|
866
935
|
displayName: opts.displayName,
|
|
867
936
|
email: opts.email,
|
|
868
|
-
departmentIds: opts.department
|
|
869
|
-
|
|
870
|
-
position: opts.position,
|
|
871
|
-
remark: opts.remark,
|
|
872
|
-
telNumber: opts.tel,
|
|
873
|
-
priority: opts.priority,
|
|
874
|
-
csfLevel: opts.csfLevel
|
|
937
|
+
departmentIds: departmentIds(opts.department),
|
|
938
|
+
telNumber: opts.tel
|
|
875
939
|
}),
|
|
876
940
|
outputOptions(cmd)
|
|
877
941
|
);
|
|
878
942
|
});
|
|
879
|
-
user.command("update <id>").description("Update a user (only provided fields change)").option("--display-name <s>", "display name").option("--email <s>", "email").option("--
|
|
943
|
+
user.command("update <id>").description("Update a user (only provided fields change)").option("--display-name <s>", "display name").option("--email <s>", "email").option("--tel <s>", "telephone").option("--department <id...>", "replace department membership with these id(s)").action(async (id, opts, cmd) => {
|
|
880
944
|
printJson(
|
|
881
945
|
await clientFrom(cmd).admin.userUpdate(id, {
|
|
882
946
|
displayName: opts.displayName,
|
|
883
947
|
email: opts.email,
|
|
884
|
-
code: opts.code,
|
|
885
|
-
position: opts.position,
|
|
886
|
-
remark: opts.remark,
|
|
887
948
|
telNumber: opts.tel,
|
|
888
|
-
|
|
889
|
-
priority: opts.priority,
|
|
890
|
-
csfLevel: opts.csfLevel
|
|
949
|
+
departmentIds: opts.department === void 0 ? void 0 : departmentIds(opts.department)
|
|
891
950
|
}),
|
|
892
951
|
outputOptions(cmd)
|
|
893
952
|
);
|
|
@@ -916,19 +975,24 @@ function adminCommand() {
|
|
|
916
975
|
);
|
|
917
976
|
});
|
|
918
977
|
const role = admin.command("role").description("Role management");
|
|
919
|
-
role.command("list").description("List roles \u2192 {roles}").option("--keyword <s>", "filter by keyword").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).option("--source <s>", "role source filter (business |
|
|
978
|
+
role.command("list").description("List roles \u2192 {roles, total}").option("--keyword <s>", "filter by keyword").option("--limit <n>", "page size", int, 100).option("--offset <n>", "page offset", int, 0).option("--source <s>", "role source filter (system | business | custom)").action(async (opts, cmd) => {
|
|
920
979
|
printJson(
|
|
921
|
-
await clientFrom(cmd).admin.roleList({
|
|
980
|
+
await clientFrom(cmd).admin.roleList({
|
|
981
|
+
keyword: opts.keyword,
|
|
982
|
+
limit: opts.limit,
|
|
983
|
+
offset: opts.offset,
|
|
984
|
+
source: opts.source
|
|
985
|
+
}),
|
|
922
986
|
outputOptions(cmd)
|
|
923
987
|
);
|
|
924
988
|
});
|
|
925
989
|
role.command("get <role>").description("Get a role by id").option("--view <mode>", "detail view mode").action(async (roleId, _opts, cmd) => {
|
|
926
990
|
printJson(await clientFrom(cmd).admin.roleGet(roleId), outputOptions(cmd));
|
|
927
991
|
});
|
|
928
|
-
role.command("members <role>").description("List members of a role
|
|
992
|
+
role.command("members <role>").description("List members of a role \u2192 {members, total}").option("--limit <n>", "page size (default: all members)", int).option("--offset <n>", "page offset", int).action(async (roleId, opts, cmd) => {
|
|
929
993
|
printJson(
|
|
930
994
|
await clientFrom(cmd).admin.roleMembers(roleId, {
|
|
931
|
-
|
|
995
|
+
offset: opts.offset,
|
|
932
996
|
limit: opts.limit
|
|
933
997
|
}),
|
|
934
998
|
outputOptions(cmd)
|
|
@@ -968,7 +1032,10 @@ function adminCommand() {
|
|
|
968
1032
|
["grant-perm", true],
|
|
969
1033
|
["revoke-perm", false]
|
|
970
1034
|
]) {
|
|
971
|
-
role.command(`${verb} <role>`).description(`${grant ? "Grant" : "Revoke"} a permission on a custom role (403 on built-in)`).requiredOption(
|
|
1035
|
+
role.command(`${verb} <role>`).description(`${grant ? "Grant" : "Revoke"} a permission on a custom role (403 on built-in)`).requiredOption(
|
|
1036
|
+
"--resource-type <t>",
|
|
1037
|
+
"resource type: knowledge_network|catalog|resource|tool_box|function|mcp|skill"
|
|
1038
|
+
).option("--resource-id <id>", "resource id ('*' = whole type)", "*").requiredOption("--operations <list>", "comma-separated operations").action(async (roleId, opts, cmd) => {
|
|
972
1039
|
printJson(
|
|
973
1040
|
await clientFrom(cmd).admin.rolePermission(
|
|
974
1041
|
roleId,
|
|
@@ -1003,8 +1070,8 @@ function adminCommand() {
|
|
|
1003
1070
|
const isLlm = kind === "llm";
|
|
1004
1071
|
const m = admin.command(kind).description(`${kind} management`);
|
|
1005
1072
|
const ns = isLlm ? "llm" : "small";
|
|
1006
|
-
const
|
|
1007
|
-
|
|
1073
|
+
const list2 = m.command("list").description(`List ${kind} models`).option("--name <s>", "filter by name").option("--page <n>", "page", int, 1).option("--size <n>", "page size", int, DEFAULT_LIST_LIMIT);
|
|
1074
|
+
list2.option("--type <t>", "model type filter").action(async (opts, cmd) => {
|
|
1008
1075
|
printJson(
|
|
1009
1076
|
await clientFrom(cmd).models[ns].list({
|
|
1010
1077
|
name: opts.name,
|
|
@@ -1080,18 +1147,34 @@ function adminCommand() {
|
|
|
1080
1147
|
).action(async (_opts, cmd) => {
|
|
1081
1148
|
printJson(await clientFrom(cmd).admin.licenseFingerprint(), outputOptions(cmd));
|
|
1082
1149
|
});
|
|
1083
|
-
admin.command("audit").description("Audit
|
|
1150
|
+
const audit = admin.command("audit").description("Audit trail: management mutations and token-gate refusals (bkn-safe)");
|
|
1151
|
+
audit.command("list").description("List audit log entries, newest first \u2192 {logs, total}").option("--actor-id <id>", "token subject id of the actor").option("--request-id <id>", "all rows written for one mutating HTTP request").option("--resource <noun>", "route noun, e.g. users, role-bindings, policies").option("--action <verb>", "business verb, e.g. create, grant, revoke, reset_password").option("--target-id <id>", "target id").option("--failed-only", "only refused and failed attempts (HTTP 4xx/5xx)").option("--from <time>", "created at or after this RFC 3339 timestamp (inclusive)").option("--to <time>", "created before this RFC 3339 timestamp (exclusive)").option("--before-id <id>", "keyset tiebreaker for rows sharing the --to timestamp").option("--offset <n>", "rows to skip", int).option("--limit <n>", `page size, 0..${AUDIT_LOG_MAX_LIMIT}`, int, DEFAULT_LIST_LIMIT).addOption(new Option("--start <time>", "alias of --from").hideHelp()).addOption(new Option("--end <time>", "alias of --to").hideHelp()).action(async (opts, cmd) => {
|
|
1152
|
+
if (opts.start !== void 0 && opts.from !== void 0) {
|
|
1153
|
+
throw new InputError("--start is an alias of --from; pass only one.");
|
|
1154
|
+
}
|
|
1155
|
+
if (opts.end !== void 0 && opts.to !== void 0) {
|
|
1156
|
+
throw new InputError("--end is an alias of --to; pass only one.");
|
|
1157
|
+
}
|
|
1084
1158
|
printJson(
|
|
1085
1159
|
await clientFrom(cmd).admin.auditList({
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1160
|
+
actorId: opts.actorId,
|
|
1161
|
+
requestId: opts.requestId,
|
|
1162
|
+
resource: opts.resource,
|
|
1163
|
+
action: opts.action,
|
|
1164
|
+
targetId: opts.targetId,
|
|
1165
|
+
failedOnly: Boolean(opts.failedOnly),
|
|
1166
|
+
from: opts.from ?? opts.start,
|
|
1167
|
+
to: opts.to ?? opts.end,
|
|
1168
|
+
beforeId: opts.beforeId,
|
|
1169
|
+
offset: opts.offset,
|
|
1170
|
+
limit: opts.limit
|
|
1091
1171
|
}),
|
|
1092
1172
|
outputOptions(cmd)
|
|
1093
1173
|
);
|
|
1094
1174
|
});
|
|
1175
|
+
audit.command("get <id>").description("Get one audit log entry").action(async (id, _opts, cmd) => {
|
|
1176
|
+
printJson(await clientFrom(cmd).admin.auditGet(id), outputOptions(cmd));
|
|
1177
|
+
});
|
|
1095
1178
|
const adminConfig = admin.command("config").description("Admin CLI config (active platform)");
|
|
1096
1179
|
adminConfig.command("show").description("Show the active platform").action((_opts, cmd) => {
|
|
1097
1180
|
printJson({ baseUrl: activePlatform() }, outputOptions(cmd));
|
|
@@ -1120,11 +1203,12 @@ function adminCommand() {
|
|
|
1120
1203
|
baseUrl: g.baseUrl,
|
|
1121
1204
|
token: g.token,
|
|
1122
1205
|
user: g.user,
|
|
1123
|
-
|
|
1124
|
-
|
|
1206
|
+
insecure: g.insecure,
|
|
1207
|
+
versionCheckMode: "cli",
|
|
1208
|
+
...retryOptionsFrom(g)
|
|
1125
1209
|
}),
|
|
1126
1210
|
url,
|
|
1127
|
-
{ method: opts.request, header: opts.header, data: opts.data
|
|
1211
|
+
{ method: opts.request, header: opts.header, data: opts.data }
|
|
1128
1212
|
);
|
|
1129
1213
|
const out = outputOptions(cmd);
|
|
1130
1214
|
try {
|
|
@@ -1218,129 +1302,155 @@ function appkeyCommand() {
|
|
|
1218
1302
|
|
|
1219
1303
|
// src/commands/bkn.ts
|
|
1220
1304
|
import { Command as Command4 } from "commander";
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
const
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1305
|
+
var int3 = (v) => Number.parseInt(v, 10);
|
|
1306
|
+
function rejectUnknownSearchOptions(cmd) {
|
|
1307
|
+
let root = cmd;
|
|
1308
|
+
while (root.parent) root = root.parent;
|
|
1309
|
+
const raw = root.rawArgs ?? [];
|
|
1310
|
+
const separator = raw.indexOf("--");
|
|
1311
|
+
const afterSeparator = separator < 0 ? [] : raw.slice(separator + 1);
|
|
1312
|
+
for (const arg of cmd.args) {
|
|
1313
|
+
if (/^--[A-Za-z]/.test(arg) && !afterSeparator.includes(arg)) {
|
|
1314
|
+
throw new InputError(
|
|
1315
|
+
`unknown option '${arg}' for bkn search (see --help); to search for text that starts with "--", put it after a -- separator`
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
if (cmd.args.length > 2) {
|
|
1320
|
+
throw new InputError(
|
|
1321
|
+
`bkn search takes <kn-id> <query>, received ${cmd.args.length} arguments; quote a multi-word query`
|
|
1322
|
+
);
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
var SYSTEM_PROPERTIES = ["_instance_id", "_instance_identity", "_display"];
|
|
1326
|
+
var DIRECTIONS = ["asc", "desc"];
|
|
1327
|
+
var NAME_OR_UPDATE_TIME = ["update_time", "name"];
|
|
1328
|
+
var SCHEDULE_SORTS = [
|
|
1329
|
+
"create_time",
|
|
1330
|
+
"update_time",
|
|
1331
|
+
"next_run_time",
|
|
1332
|
+
"last_run_time",
|
|
1333
|
+
"name"
|
|
1334
|
+
];
|
|
1335
|
+
var CAPABILITY_SORTS = ["create_time", "update_time"];
|
|
1336
|
+
var sortDirection = oneOf("--direction", DIRECTIONS);
|
|
1337
|
+
var IMPORT_MODES = ["normal", "overwrite", "ignore"];
|
|
1338
|
+
var BINDING_POLICIES = ["preserve", "detach"];
|
|
1339
|
+
function knListLimit(v) {
|
|
1340
|
+
if (v === "-1") return -1;
|
|
1341
|
+
const n = /^\d+$/.test(v) ? Number(v) : Number.NaN;
|
|
1342
|
+
if (!(n >= 1 && n <= 1e3)) {
|
|
1343
|
+
throw new InputError(`--limit must be an integer from 1 to 1000, or -1 for all (got '${v}')`);
|
|
1235
1344
|
}
|
|
1236
|
-
return
|
|
1345
|
+
return n;
|
|
1237
1346
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1347
|
+
var nonNegativeInt = (flag) => (v) => {
|
|
1348
|
+
const n = /^\d+$/.test(v) ? Number(v) : Number.NaN;
|
|
1349
|
+
if (!Number.isSafeInteger(n)) {
|
|
1350
|
+
throw new InputError(`${flag} must be a non-negative integer (got '${v}')`);
|
|
1351
|
+
}
|
|
1352
|
+
return n;
|
|
1353
|
+
};
|
|
1354
|
+
function actionLogKeyword(v) {
|
|
1355
|
+
if (v.length > 128) {
|
|
1356
|
+
throw new InputError(`--keyword must be at most 128 characters (got ${v.length})`);
|
|
1357
|
+
}
|
|
1358
|
+
return v;
|
|
1241
1359
|
}
|
|
1242
|
-
function
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
const cells = line.split("|").map((c) => c.trim()).filter(Boolean);
|
|
1251
|
-
if (cells.length < 2) continue;
|
|
1252
|
-
const [source, target] = cells;
|
|
1253
|
-
if (!source || !target) continue;
|
|
1254
|
-
if (/^source$/i.test(source) || /^-+$/.test(source)) continue;
|
|
1255
|
-
refs.push({ source, target });
|
|
1360
|
+
function writeModeFlags(cmd, withImportMode) {
|
|
1361
|
+
cmd.option("--no-strict-mode", "skip dependency validation (strict_mode=false)");
|
|
1362
|
+
if (withImportMode) {
|
|
1363
|
+
cmd.option(
|
|
1364
|
+
"--import-mode <mode>",
|
|
1365
|
+
"existing ids/names: normal (default, error) | overwrite | ignore",
|
|
1366
|
+
oneOf("--import-mode", IMPORT_MODES)
|
|
1367
|
+
);
|
|
1256
1368
|
}
|
|
1257
|
-
return
|
|
1369
|
+
return cmd;
|
|
1258
1370
|
}
|
|
1259
|
-
function
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1371
|
+
function writeModes(opts) {
|
|
1372
|
+
return {
|
|
1373
|
+
branch: opts.branch,
|
|
1374
|
+
strictMode: opts.strictMode === false ? false : void 0,
|
|
1375
|
+
importMode: opts.importMode
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1378
|
+
function systemProperties(value) {
|
|
1379
|
+
const list2 = csv(value);
|
|
1380
|
+
for (const p of list2 ?? []) oneOf("--exclude-system-properties", SYSTEM_PROPERTIES)(p);
|
|
1381
|
+
return list2;
|
|
1382
|
+
}
|
|
1383
|
+
var CAPABILITY_TYPES = ["skill", "function", "mcp_tool"];
|
|
1384
|
+
function capabilityEntries(opts) {
|
|
1385
|
+
const targets = [opts.skill, opts.box, opts.mcp].filter((v) => v !== void 0);
|
|
1386
|
+
if (targets.length !== 1) {
|
|
1387
|
+
throw new InputError(
|
|
1388
|
+
"Name exactly one of --skill <ids>, --box <box-id> or --mcp <mcp-id> to attach."
|
|
1389
|
+
);
|
|
1271
1390
|
}
|
|
1272
|
-
const
|
|
1273
|
-
if (
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
const fm = parseFrontmatter(readFileSync3(networkPath, "utf8"));
|
|
1277
|
-
if (!fm) errors.push("network.bkn has no frontmatter block.");
|
|
1278
|
-
else {
|
|
1279
|
-
if (fm.type !== "knowledge_network")
|
|
1280
|
-
errors.push(`network.bkn type must be 'knowledge_network', got '${fm.type ?? ""}'.`);
|
|
1281
|
-
if (!fm.id) errors.push("network.bkn is missing 'id'.");
|
|
1282
|
-
if (!fm.name) errors.push("network.bkn is missing 'name'.");
|
|
1391
|
+
const comment = opts.comment || void 0;
|
|
1392
|
+
if (opts.skill !== void 0) {
|
|
1393
|
+
if (opts.tool !== void 0 || opts.allTools) {
|
|
1394
|
+
throw new InputError("--tool and --all-tools go with --box or --mcp, not --skill.");
|
|
1283
1395
|
}
|
|
1396
|
+
const ids = csv(opts.skill) ?? [];
|
|
1397
|
+
if (ids.length === 0) throw new InputError("--skill needs at least one skill id.");
|
|
1398
|
+
return ids.map((id) => ({ capability_type: "skill", capability_id: id, comment }));
|
|
1284
1399
|
}
|
|
1285
|
-
const
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
errors.push(`${rel}: not a valid object_type (missing/wrong frontmatter type).`);
|
|
1292
|
-
continue;
|
|
1293
|
-
}
|
|
1294
|
-
if (!fm.id) errors.push(`${rel}: object_type missing 'id'.`);
|
|
1295
|
-
if (!fm.name) errors.push(`${rel}: object_type missing 'name'.`);
|
|
1296
|
-
if (fm.name && [...fm.name].length > BKN_OBJECT_NAME_MAX_LENGTH) {
|
|
1297
|
-
errors.push(
|
|
1298
|
-
`${rel}: object_type name exceeds ${BKN_OBJECT_NAME_MAX_LENGTH} codepoints ('${fm.name}').`
|
|
1299
|
-
);
|
|
1300
|
-
}
|
|
1301
|
-
if (fm.id) {
|
|
1302
|
-
if (otIds.has(fm.id)) errors.push(`Duplicate object_type id '${fm.id}'.`);
|
|
1303
|
-
otIds.add(fm.id);
|
|
1304
|
-
}
|
|
1400
|
+
const flag = opts.box !== void 0 ? "--box" : "--mcp";
|
|
1401
|
+
const owner = (opts.box ?? opts.mcp ?? "").trim();
|
|
1402
|
+
const type = opts.box !== void 0 ? "function" : "mcp_tool";
|
|
1403
|
+
if (!owner) throw new InputError(`${flag} needs an id.`);
|
|
1404
|
+
if (opts.tool !== void 0 && opts.allTools) {
|
|
1405
|
+
throw new InputError("Use --tool or --all-tools, not both.");
|
|
1305
1406
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1407
|
+
if (opts.allTools) return [{ capability_type: type, box_id: owner, all_tools: true, comment }];
|
|
1408
|
+
const tools = csv(opts.tool) ?? [];
|
|
1409
|
+
if (tools.length === 0) {
|
|
1410
|
+
throw new InputError(
|
|
1411
|
+
`${flag} binds tools, not the container: add --tool <ids> or --all-tools.`
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
return tools.map((tool) => ({
|
|
1415
|
+
capability_type: type,
|
|
1416
|
+
box_id: owner,
|
|
1417
|
+
capability_id: tool,
|
|
1418
|
+
comment
|
|
1419
|
+
}));
|
|
1420
|
+
}
|
|
1421
|
+
function warnUnboundCapabilities(result, declared) {
|
|
1422
|
+
if (declared.malformed) {
|
|
1423
|
+
process.stderr.write(
|
|
1424
|
+
`warning: network.bkn capabilities ${declared.malformed}; none of it was bound.
|
|
1425
|
+
`
|
|
1426
|
+
);
|
|
1427
|
+
}
|
|
1428
|
+
const report = result?.capabilities;
|
|
1429
|
+
const skipped = Array.isArray(report?.skipped) ? report.skipped.filter(
|
|
1430
|
+
(s) => typeof s === "object" && s !== null
|
|
1431
|
+
) : [];
|
|
1432
|
+
if (skipped.length === 0) return;
|
|
1433
|
+
const noun = skipped.length === 1 ? "capability was" : "capabilities were";
|
|
1434
|
+
process.stderr.write(`warning: ${skipped.length} declared ${noun} not bound:
|
|
1435
|
+
`);
|
|
1436
|
+
for (const skip of skipped) {
|
|
1437
|
+
const owner = skip.box_name ? `${skip.box_name} / ` : "";
|
|
1438
|
+
const name = skip.name || skip.declared_id || "(unnamed)";
|
|
1439
|
+
const detail = skip.detail ? ` \u2014 ${skip.detail}` : "";
|
|
1440
|
+
process.stderr.write(` ${skip.capability_type} ${owner}${name}: ${skip.reason}${detail}
|
|
1441
|
+
`);
|
|
1322
1442
|
}
|
|
1323
|
-
const cgFiles = bknFiles(join(dir, "concept_groups"));
|
|
1324
|
-
return {
|
|
1325
|
-
valid: errors.length === 0,
|
|
1326
|
-
dir,
|
|
1327
|
-
counts: {
|
|
1328
|
-
objectTypes: otFiles.length,
|
|
1329
|
-
relationTypes: rtFiles.length,
|
|
1330
|
-
conceptGroups: cgFiles.length
|
|
1331
|
-
},
|
|
1332
|
-
errors,
|
|
1333
|
-
warnings
|
|
1334
|
-
};
|
|
1335
1443
|
}
|
|
1336
|
-
|
|
1337
|
-
// src/commands/bkn.ts
|
|
1338
|
-
var int3 = (v) => Number.parseInt(v, 10);
|
|
1339
1444
|
function bknCommand() {
|
|
1340
1445
|
const bkn = new Command4("bkn").description(
|
|
1341
1446
|
"Knowledge networks: schema, metrics, search, import/export"
|
|
1342
1447
|
);
|
|
1343
|
-
bkn.command("list").description("List knowledge networks").option("--limit <n>", "page size",
|
|
1448
|
+
bkn.command("list").description("List knowledge networks").option("--limit <n>", "page size, 1\u20131000, or -1 for all", knListLimit, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int3, 0).option("--name-pattern <s>", "filter by name pattern").option("--tag <s>", "filter by tag").option(
|
|
1449
|
+
"--sort <field>",
|
|
1450
|
+
"update_time | name",
|
|
1451
|
+
oneOf("--sort", NAME_OR_UPDATE_TIME),
|
|
1452
|
+
"update_time"
|
|
1453
|
+
).option("--direction <dir>", "asc | desc", sortDirection, "desc").action(async (_opts, cmd) => {
|
|
1344
1454
|
const o = cmd.optsWithGlobals();
|
|
1345
1455
|
const data = await clientFrom(cmd).kn.list({
|
|
1346
1456
|
limit: o.limit,
|
|
@@ -1352,16 +1462,31 @@ function bknCommand() {
|
|
|
1352
1462
|
});
|
|
1353
1463
|
printJson(data, outputOptions(cmd));
|
|
1354
1464
|
});
|
|
1355
|
-
bkn.command("get <kn-id>").description("Get a knowledge network (use --stats or --export)").option("--stats", "include statistics").option("--export", "return the full export payload").
|
|
1465
|
+
bkn.command("get <kn-id>").description("Get a knowledge network (use --stats or --export)").option("--stats", "include statistics").option("--export", "return the full export payload").option("--branch <b>", "branch (default: main)").option(
|
|
1466
|
+
"--detail-level <level>",
|
|
1467
|
+
"full (default) | summary \u2014 sent as detail_level; the service applies it only with --export (openbkn-ai/bkn-foundry#1632)",
|
|
1468
|
+
oneOf("--detail-level", ["full", "summary"])
|
|
1469
|
+
).action(async (knId, opts, cmd) => {
|
|
1356
1470
|
const data = await clientFrom(cmd).kn.get(knId, {
|
|
1357
1471
|
stats: opts.stats,
|
|
1358
|
-
exportMode: opts.export
|
|
1472
|
+
exportMode: opts.export,
|
|
1473
|
+
branch: opts.branch,
|
|
1474
|
+
detailLevel: opts.detailLevel
|
|
1359
1475
|
});
|
|
1360
1476
|
printJson(data, outputOptions(cmd));
|
|
1361
1477
|
});
|
|
1362
|
-
bkn.command("search <kn-id> <query>").description(
|
|
1478
|
+
bkn.command("search <kn-id> <query>").allowUnknownOption().allowExcessArguments().description(
|
|
1363
1479
|
"Recall instances from a plain sentence \u2014 no object type or field names needed \u2192 {nodes, object_types}"
|
|
1364
|
-
).option("--object-types <ids>", "pin recall to these object-type ids (comma-separated)").option("--exclude-object-types <ids>", "drop these object-type ids (comma-separated)").option("--concept-groups <names>", "limit recall to these concept groups (comma-separated)").option(
|
|
1480
|
+
).option("--object-types <ids>", "pin recall to these object-type ids (comma-separated)").option("--exclude-object-types <ids>", "drop these object-type ids (comma-separated)").option("--concept-groups <names>", "limit recall to these concept groups (comma-separated)").option(
|
|
1481
|
+
"--max-object-types <n>",
|
|
1482
|
+
"positive count of object types that may take part",
|
|
1483
|
+
positiveInt("--max-object-types")
|
|
1484
|
+
).option(
|
|
1485
|
+
"--max-instances <n>",
|
|
1486
|
+
"positive count of instances per object type",
|
|
1487
|
+
positiveInt("--max-instances")
|
|
1488
|
+
).option("--rerank", "re-rank hits with a cross-encoder (needs a rerank model deployed)").option("--no-object-types-detail", "omit the object-type definitions that come with hits").action(async (knId, query, opts, cmd) => {
|
|
1489
|
+
rejectUnknownSearchOptions(cmd);
|
|
1365
1490
|
const data = await clientFrom(cmd).kn.search(knId, query, {
|
|
1366
1491
|
objectTypes: csv(opts.objectTypes),
|
|
1367
1492
|
excludeObjectTypes: csv(opts.excludeObjectTypes),
|
|
@@ -1380,36 +1505,59 @@ function bknCommand() {
|
|
|
1380
1505
|
];
|
|
1381
1506
|
for (const [name, listMethod, crud] of schemaGroups) {
|
|
1382
1507
|
const g = bkn.command(name).description(`${name} list/get/...`);
|
|
1383
|
-
g.command("list <kn-id>").description(`List ${name}s`).option("--branch <b>", "branch", "main").action(async (knId, opts, cmd) => {
|
|
1508
|
+
g.command("list <kn-id>").description(`List ${name}s`).option("--branch <b>", "branch", "main").option("--name-pattern <s>", "fuzzy name filter").option("--tag <s>", "exact tag filter").action(async (knId, opts, cmd) => {
|
|
1384
1509
|
printJson(
|
|
1385
|
-
await clientFrom(cmd).kn[listMethod](knId, {
|
|
1510
|
+
await clientFrom(cmd).kn[listMethod](knId, {
|
|
1511
|
+
branch: opts.branch,
|
|
1512
|
+
namePattern: opts.namePattern,
|
|
1513
|
+
tag: opts.tag
|
|
1514
|
+
}),
|
|
1386
1515
|
outputOptions(cmd)
|
|
1387
1516
|
);
|
|
1388
1517
|
});
|
|
1389
1518
|
if (crud) {
|
|
1390
|
-
g.command("get <kn-id> <id>").description(`Get ${name} \u2192 {entries}`).action(async (knId, id,
|
|
1391
|
-
printJson(
|
|
1519
|
+
g.command("get <kn-id> <id>").description(`Get ${name} \u2192 {entries}`).option("--branch <b>", "branch (default: main)").action(async (knId, id, opts, cmd) => {
|
|
1520
|
+
printJson(
|
|
1521
|
+
await clientFrom(cmd).kn[`${crud}Get`](knId, id, { branch: opts.branch }),
|
|
1522
|
+
outputOptions(cmd)
|
|
1523
|
+
);
|
|
1392
1524
|
});
|
|
1393
|
-
|
|
1394
|
-
"
|
|
1395
|
-
|
|
1396
|
-
|
|
1525
|
+
writeModeFlags(
|
|
1526
|
+
g.command("create <kn-id>").description(`Create ${name}s (--body / --body-file) \u2192 body is {entries:[\u2026]}`).option(
|
|
1527
|
+
"--body <json>",
|
|
1528
|
+
"body JSON {entries:[\u2026]} (a bare array is wrapped) \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1529
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)"),
|
|
1530
|
+
true
|
|
1531
|
+
).action(async (knId, opts, cmd) => {
|
|
1397
1532
|
printJson(
|
|
1398
|
-
await clientFrom(cmd).kn[`${crud}Create`](knId, readBody(opts)),
|
|
1533
|
+
await clientFrom(cmd).kn[`${crud}Create`](knId, readBody(opts), writeModes(opts)),
|
|
1399
1534
|
outputOptions(cmd)
|
|
1400
1535
|
);
|
|
1401
1536
|
});
|
|
1402
|
-
g.command("update <kn-id> <id>").description(`Update ${name} (--body / --body-file)`).option(
|
|
1537
|
+
g.command("update <kn-id> <id>").description(`Update ${name} (--body / --body-file); the body carries base_version`).option(
|
|
1403
1538
|
"--body <json>",
|
|
1404
|
-
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1405
|
-
).option("--body-file <path>", "read body JSON from a file").action(async (knId, id, opts, cmd) => {
|
|
1539
|
+
"body JSON, including base_version from `get` \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1540
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)").option("--no-strict-mode", "skip dependency validation (strict_mode=false)").action(async (knId, id, opts, cmd) => {
|
|
1406
1541
|
printJson(
|
|
1407
|
-
await clientFrom(cmd).kn[`${crud}Update`](knId, id, readBody(opts)
|
|
1542
|
+
await clientFrom(cmd).kn[`${crud}Update`](knId, id, readBody(opts), {
|
|
1543
|
+
branch: opts.branch,
|
|
1544
|
+
strictMode: opts.strictMode === false ? false : void 0
|
|
1545
|
+
}),
|
|
1408
1546
|
outputOptions(cmd)
|
|
1409
1547
|
);
|
|
1410
1548
|
});
|
|
1411
|
-
g.command("delete <kn-id> <id>").description(`Delete ${name}`).option("-y, --yes", "skip confirmation").
|
|
1412
|
-
|
|
1549
|
+
const del = g.command("delete <kn-id> <id>").description(`Delete ${name}`).option("-y, --yes", "skip confirmation").option("--branch <b>", "branch (default: main)");
|
|
1550
|
+
if (crud === "objectType") {
|
|
1551
|
+
del.option("--force", "delete even when a relation type still binds it (force_delete)");
|
|
1552
|
+
}
|
|
1553
|
+
del.action(async (knId, id, opts, cmd) => {
|
|
1554
|
+
printJson(
|
|
1555
|
+
await clientFrom(cmd).kn[`${crud}Delete`](knId, id, {
|
|
1556
|
+
branch: opts.branch,
|
|
1557
|
+
forceDelete: opts.force
|
|
1558
|
+
}),
|
|
1559
|
+
outputOptions(cmd)
|
|
1560
|
+
);
|
|
1413
1561
|
});
|
|
1414
1562
|
}
|
|
1415
1563
|
}
|
|
@@ -1417,23 +1565,36 @@ function bknCommand() {
|
|
|
1417
1565
|
actionType?.command("query <kn-id> <at-id>").description("Query an action type (--body / --body-file JSON)").option(
|
|
1418
1566
|
"--body <json>",
|
|
1419
1567
|
"query JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1420
|
-
).option("--body-file <path>", "read query JSON from a file").
|
|
1568
|
+
).option("--body-file <path>", "read query JSON from a file").option("--branch <b>", "branch (default: main)").option("--include-type-info", "include the action type definition").option(
|
|
1569
|
+
"--exclude-system-properties <list>",
|
|
1570
|
+
"drop system fields: _instance_id,_instance_identity,_display"
|
|
1571
|
+
).action(async (knId, atId, opts, cmd) => {
|
|
1572
|
+
const excludeSystemProperties = systemProperties(opts.excludeSystemProperties);
|
|
1421
1573
|
printJson(
|
|
1422
|
-
await clientFrom(cmd).kn.actionTypeQuery(knId, atId, readBody(opts)
|
|
1574
|
+
await clientFrom(cmd).kn.actionTypeQuery(knId, atId, readBody(opts), {
|
|
1575
|
+
branch: opts.branch,
|
|
1576
|
+
includeTypeInfo: opts.includeTypeInfo,
|
|
1577
|
+
excludeSystemProperties
|
|
1578
|
+
}),
|
|
1423
1579
|
outputOptions(cmd)
|
|
1424
1580
|
);
|
|
1425
1581
|
});
|
|
1426
1582
|
actionType?.command("execute <kn-id> <at-id>").description("Execute an action type (--body / --body-file envelope JSON)").option(
|
|
1427
1583
|
"--body <json>",
|
|
1428
1584
|
"execution envelope JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1429
|
-
).option("--body-file <path>", "read envelope JSON from a file").action(async (knId, atId, opts, cmd) => {
|
|
1585
|
+
).option("--body-file <path>", "read envelope JSON from a file").option("--branch <b>", "branch (default: main)").action(async (knId, atId, opts, cmd) => {
|
|
1430
1586
|
printJson(
|
|
1431
|
-
await clientFrom(cmd).kn.actionTypeExecute(knId, atId, readBody(opts)
|
|
1587
|
+
await clientFrom(cmd).kn.actionTypeExecute(knId, atId, readBody(opts), {
|
|
1588
|
+
branch: opts.branch
|
|
1589
|
+
}),
|
|
1432
1590
|
outputOptions(cmd)
|
|
1433
1591
|
);
|
|
1434
1592
|
});
|
|
1435
|
-
actionType?.command("get <kn-id> <at-id>").description("Get an action type").action(async (knId, atId,
|
|
1436
|
-
printJson(
|
|
1593
|
+
actionType?.command("get <kn-id> <at-id>").description("Get an action type").option("--branch <b>", "branch (default: main)").action(async (knId, atId, opts, cmd) => {
|
|
1594
|
+
printJson(
|
|
1595
|
+
await clientFrom(cmd).kn.actionTypeGet(knId, atId, { branch: opts.branch }),
|
|
1596
|
+
outputOptions(cmd)
|
|
1597
|
+
);
|
|
1437
1598
|
});
|
|
1438
1599
|
bkn.command("stats <kn-id>").description("Get knowledge-network statistics (alias for get --stats)").action(async (knId, _opts, cmd) => {
|
|
1439
1600
|
printJson(await clientFrom(cmd).kn.get(knId, { stats: true }), outputOptions(cmd));
|
|
@@ -1445,46 +1606,159 @@ function bknCommand() {
|
|
|
1445
1606
|
objectType?.command("query <kn-id> <ot-id>").description("Query instances of an object type (--body / --body-file JSON)").option(
|
|
1446
1607
|
"--body <json>",
|
|
1447
1608
|
"query JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1448
|
-
).option("--body-file <path>", "read query JSON from a file").
|
|
1609
|
+
).option("--body-file <path>", "read query JSON from a file").option("--branch <b>", "branch (default: main)").option("--include-type-info", "include the object type definition").option("--include-logic-params", "include the computation parameters of logic properties").option(
|
|
1610
|
+
"--exclude-system-properties <list>",
|
|
1611
|
+
"drop system fields: _instance_id,_instance_identity,_display"
|
|
1612
|
+
).option("--ignoring-store-cache", "skip the index and read the store directly").addHelpText(
|
|
1613
|
+
"after",
|
|
1614
|
+
`
|
|
1615
|
+
The first page sends {limit, condition?, sort?, need_total?, properties?}. How the next
|
|
1616
|
+
page is asked for depends on the deploy: one that includes foundry #1623 answers with
|
|
1617
|
+
paging.next_cursor (null on the last page) \u2014 resend the query with "cursor" set to it.
|
|
1618
|
+
An older deploy answers without paging \u2014 resend the query with "offset" instead.
|
|
1619
|
+
|
|
1620
|
+
openbkn bkn object-type query <kn-id> <ot-id> --body '{"limit": 20}'
|
|
1621
|
+
openbkn bkn object-type query <kn-id> <ot-id> --body '{"limit": 20, "cursor": "<next_cursor>"}'
|
|
1622
|
+
openbkn bkn object-type query <kn-id> <ot-id> --body '{"limit": 20, "offset": 20}' # older deploys`
|
|
1623
|
+
).action(async (knId, otId, opts, cmd) => {
|
|
1624
|
+
const excludeSystemProperties = systemProperties(opts.excludeSystemProperties);
|
|
1449
1625
|
printJson(
|
|
1450
|
-
await clientFrom(cmd).kn.objectTypeQuery(knId, otId, readBody(opts)
|
|
1626
|
+
await clientFrom(cmd).kn.objectTypeQuery(knId, otId, readBody(opts), {
|
|
1627
|
+
branch: opts.branch,
|
|
1628
|
+
includeTypeInfo: opts.includeTypeInfo,
|
|
1629
|
+
includeLogicParams: opts.includeLogicParams,
|
|
1630
|
+
excludeSystemProperties,
|
|
1631
|
+
ignoringStoreCache: opts.ignoringStoreCache
|
|
1632
|
+
}),
|
|
1451
1633
|
outputOptions(cmd)
|
|
1452
1634
|
);
|
|
1453
1635
|
});
|
|
1454
|
-
bkn.command("create <name>").description("Create an (empty) knowledge network").option("--branch <b>", "branch", "main").
|
|
1455
|
-
|
|
1636
|
+
bkn.command("create <name>").description("Create an (empty) knowledge network").option("--branch <b>", "branch, sent in both the query and the body", "main").option(
|
|
1637
|
+
"--import-mode <mode>",
|
|
1638
|
+
"an existing id/name: normal (default, error) | overwrite | ignore",
|
|
1639
|
+
oneOf("--import-mode", IMPORT_MODES)
|
|
1640
|
+
).option("--no-strict-mode", "skip dependency validation (strict_mode=false)").option(
|
|
1641
|
+
"--binding-policy <policy>",
|
|
1642
|
+
"environment-local bindings: preserve (default) | detach",
|
|
1643
|
+
oneOf("--binding-policy", BINDING_POLICIES)
|
|
1644
|
+
).action(async (name, opts, cmd) => {
|
|
1645
|
+
printJson(
|
|
1646
|
+
await clientFrom(cmd).kn.create({
|
|
1647
|
+
name,
|
|
1648
|
+
...writeModes(opts),
|
|
1649
|
+
bindingPolicy: opts.bindingPolicy
|
|
1650
|
+
}),
|
|
1651
|
+
outputOptions(cmd)
|
|
1652
|
+
);
|
|
1456
1653
|
});
|
|
1457
|
-
|
|
1458
|
-
"
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1654
|
+
writeModeFlags(
|
|
1655
|
+
bkn.command("update <kn-id>").description("Update a knowledge network (--body / --body-file)").option(
|
|
1656
|
+
"--body <json>",
|
|
1657
|
+
"update body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1658
|
+
).option("--body-file <path>", "read update body JSON from a file").option("--branch <b>", "branch (default: the body's branch, else main)"),
|
|
1659
|
+
true
|
|
1660
|
+
).action(async (knId, opts, cmd) => {
|
|
1661
|
+
printJson(
|
|
1662
|
+
await clientFrom(cmd).kn.update(knId, readBody(opts), writeModes(opts)),
|
|
1663
|
+
outputOptions(cmd)
|
|
1664
|
+
);
|
|
1462
1665
|
});
|
|
1463
|
-
bkn.command("delete <kn-id>").description("Delete a knowledge network").option("-y, --yes", "skip confirmation").action(async (knId,
|
|
1464
|
-
printJson(await clientFrom(cmd).kn.delete(knId), outputOptions(cmd));
|
|
1666
|
+
bkn.command("delete <kn-id>").description("Delete a knowledge network").option("-y, --yes", "skip confirmation").option("--branch <b>", "branch (default: main)").action(async (knId, opts, cmd) => {
|
|
1667
|
+
printJson(await clientFrom(cmd).kn.delete(knId, { branch: opts.branch }), outputOptions(cmd));
|
|
1465
1668
|
});
|
|
1466
1669
|
bkn.command("subgraph <kn-id>").description("Query a subgraph (--body / --body-file JSON)").option(
|
|
1467
1670
|
"--body <json>",
|
|
1468
1671
|
"subgraph query JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1469
|
-
).option("--body-file <path>", "read subgraph query JSON from a file").
|
|
1470
|
-
|
|
1672
|
+
).option("--body-file <path>", "read subgraph query JSON from a file").option(
|
|
1673
|
+
"--query-type <type>",
|
|
1674
|
+
"relation_path to follow given paths (default: explore from a start point)",
|
|
1675
|
+
oneOf("--query-type", ["", "relation_path"])
|
|
1676
|
+
).option("--branch <b>", "branch (default: main)").option("--include-logic-params", "include the computation parameters of logic properties").option(
|
|
1677
|
+
"--exclude-system-properties <list>",
|
|
1678
|
+
"drop system fields: _instance_id,_instance_identity,_display"
|
|
1679
|
+
).option("--ignoring-store-cache", "skip the index and read the store directly").action(async (knId, opts, cmd) => {
|
|
1680
|
+
const excludeSystemProperties = systemProperties(opts.excludeSystemProperties);
|
|
1681
|
+
printJson(
|
|
1682
|
+
await clientFrom(cmd).kn.subgraph(knId, readBody(opts), {
|
|
1683
|
+
queryType: opts.queryType,
|
|
1684
|
+
branch: opts.branch,
|
|
1685
|
+
includeLogicParams: opts.includeLogicParams,
|
|
1686
|
+
excludeSystemProperties,
|
|
1687
|
+
ignoringStoreCache: opts.ignoringStoreCache
|
|
1688
|
+
}),
|
|
1689
|
+
outputOptions(cmd)
|
|
1690
|
+
);
|
|
1471
1691
|
});
|
|
1472
|
-
const actionLog = bkn.command("action-log").description("Action logs \u2014 list/get/cancel; list pages with
|
|
1473
|
-
actionLog.command("list <kn-id>").description("List action logs").option(
|
|
1692
|
+
const actionLog = bkn.command("action-log").description("Action logs \u2014 list/get/cancel; list pages with --search-after");
|
|
1693
|
+
actionLog.command("list <kn-id>").description("List action logs").option(
|
|
1694
|
+
"--status <s>",
|
|
1695
|
+
"pending | running | completed | failed | cancelled",
|
|
1696
|
+
oneOf("--status", ["pending", "running", "completed", "failed", "cancelled"])
|
|
1697
|
+
).option("--action-type-id <id>", "filter by action type").option(
|
|
1698
|
+
"--trigger-type <t>",
|
|
1699
|
+
"manual | scheduled",
|
|
1700
|
+
oneOf("--trigger-type", ["manual", "scheduled"])
|
|
1701
|
+
).option(
|
|
1702
|
+
"--keyword <s>",
|
|
1703
|
+
"case-insensitive substring of the execution id (max 128 characters)",
|
|
1704
|
+
actionLogKeyword
|
|
1705
|
+
).option("--start-time-from <ms>", "start time lower bound, epoch milliseconds", int3).option("--start-time-to <ms>", "start time upper bound, epoch milliseconds", int3).option("--limit <n>", "page size, 1\u20131000", positiveInt("--limit", 1e3), DEFAULT_LIST_LIMIT).option(
|
|
1706
|
+
"--offset <n>",
|
|
1707
|
+
"page offset; not allowed with --search-after",
|
|
1708
|
+
nonNegativeInt("--offset")
|
|
1709
|
+
).option("--need-total", "also return total_count").option("--search-after <cursor>", "deep-paging cursor from the previous page (comma-joined)").action(async (knId, opts, cmd) => {
|
|
1710
|
+
if (opts.searchAfter !== void 0 && opts.offset !== void 0) {
|
|
1711
|
+
throw new InputError("--offset cannot be combined with --search-after; use one of them");
|
|
1712
|
+
}
|
|
1474
1713
|
printJson(
|
|
1475
1714
|
await clientFrom(cmd).kn.actionLogs(knId, {
|
|
1476
1715
|
status: opts.status,
|
|
1477
1716
|
actionTypeId: opts.actionTypeId,
|
|
1478
|
-
|
|
1717
|
+
triggerType: opts.triggerType,
|
|
1718
|
+
keyword: opts.keyword,
|
|
1719
|
+
startTimeFrom: opts.startTimeFrom,
|
|
1720
|
+
startTimeTo: opts.startTimeTo,
|
|
1721
|
+
limit: opts.limit,
|
|
1722
|
+
offset: opts.offset,
|
|
1723
|
+
needTotal: opts.needTotal,
|
|
1724
|
+
searchAfter: opts.searchAfter
|
|
1479
1725
|
}),
|
|
1480
1726
|
outputOptions(cmd)
|
|
1481
1727
|
);
|
|
1482
1728
|
});
|
|
1483
|
-
actionLog.command("get <kn-id> <log-id>").description("Get an action log").
|
|
1484
|
-
|
|
1729
|
+
actionLog.command("get <kn-id> <log-id>").description("Get an action log").option(
|
|
1730
|
+
"--results-limit <n>",
|
|
1731
|
+
"page size of the embedded results, 1\u20131000",
|
|
1732
|
+
positiveInt("--results-limit", 1e3)
|
|
1733
|
+
).option(
|
|
1734
|
+
"--results-offset <n>",
|
|
1735
|
+
"offset into the embedded results; offset + limit must not exceed 10000",
|
|
1736
|
+
nonNegativeInt("--results-offset")
|
|
1737
|
+
).option(
|
|
1738
|
+
"--results-status <s>",
|
|
1739
|
+
"success | failed",
|
|
1740
|
+
oneOf("--results-status", ["success", "failed"])
|
|
1741
|
+
).action(async (knId, logId, opts, cmd) => {
|
|
1742
|
+
const window = (opts.resultsOffset ?? 0) + (opts.resultsLimit ?? 100);
|
|
1743
|
+
if (opts.resultsOffset !== void 0 && window > 1e4) {
|
|
1744
|
+
throw new InputError(
|
|
1745
|
+
`--results-offset + --results-limit must not exceed 10000 (got ${window})`
|
|
1746
|
+
);
|
|
1747
|
+
}
|
|
1748
|
+
printJson(
|
|
1749
|
+
await clientFrom(cmd).kn.actionLog(knId, logId, {
|
|
1750
|
+
resultsLimit: opts.resultsLimit,
|
|
1751
|
+
resultsOffset: opts.resultsOffset,
|
|
1752
|
+
resultsStatus: opts.resultsStatus
|
|
1753
|
+
}),
|
|
1754
|
+
outputOptions(cmd)
|
|
1755
|
+
);
|
|
1485
1756
|
});
|
|
1486
|
-
actionLog.command("cancel <kn-id> <log-id>").description("Cancel a running action").action(async (knId, logId,
|
|
1487
|
-
printJson(
|
|
1757
|
+
actionLog.command("cancel <kn-id> <log-id>").description("Cancel a running action").option("--reason <text>", "why it was cancelled").action(async (knId, logId, opts, cmd) => {
|
|
1758
|
+
printJson(
|
|
1759
|
+
await clientFrom(cmd).kn.cancelActionLog(knId, logId, { reason: opts.reason }),
|
|
1760
|
+
outputOptions(cmd)
|
|
1761
|
+
);
|
|
1488
1762
|
});
|
|
1489
1763
|
bkn.command("action-execution <kn-id> <execution-id>").description("Get action execution status").action(async (knId, execId, _opts, cmd) => {
|
|
1490
1764
|
printJson(await clientFrom(cmd).kn.actionExecution(knId, execId), outputOptions(cmd));
|
|
@@ -1493,141 +1767,297 @@ function bknCommand() {
|
|
|
1493
1767
|
metric.command("query <kn-id> <metric-id>").description("Query a metric's data (--body / --body-file JSON)").option(
|
|
1494
1768
|
"--body <json>",
|
|
1495
1769
|
"query JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1496
|
-
).option("--body-file <path>", "read query JSON from a file").action(async (knId, metricId, opts, cmd) => {
|
|
1770
|
+
).option("--body-file <path>", "read query JSON from a file").option("--branch <b>", "branch (default: main)").option("--fill-null", "align trend series to every bucket, filling gaps with null").action(async (knId, metricId, opts, cmd) => {
|
|
1497
1771
|
printJson(
|
|
1498
|
-
await clientFrom(cmd).kn.metricQuery(knId, metricId, readBody(opts)
|
|
1772
|
+
await clientFrom(cmd).kn.metricQuery(knId, metricId, readBody(opts), {
|
|
1773
|
+
branch: opts.branch,
|
|
1774
|
+
fillNull: opts.fillNull
|
|
1775
|
+
}),
|
|
1499
1776
|
outputOptions(cmd)
|
|
1500
1777
|
);
|
|
1501
1778
|
});
|
|
1502
1779
|
metric.command("dry-run <kn-id>").description("Dry-run a metric definition (--body / --body-file JSON)").option(
|
|
1503
1780
|
"--body <json>",
|
|
1504
1781
|
"metric definition JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (ontology-query)"
|
|
1505
|
-
).option("--body-file <path>", "read metric definition JSON from a file").action(async (knId, opts, cmd) => {
|
|
1506
|
-
printJson(
|
|
1782
|
+
).option("--body-file <path>", "read metric definition JSON from a file").option("--branch <b>", "branch (default: main)").option("--fill-null", "align trend series to every bucket, filling gaps with null").action(async (knId, opts, cmd) => {
|
|
1783
|
+
printJson(
|
|
1784
|
+
await clientFrom(cmd).kn.metricDryRun(knId, readBody(opts), {
|
|
1785
|
+
branch: opts.branch,
|
|
1786
|
+
fillNull: opts.fillNull
|
|
1787
|
+
}),
|
|
1788
|
+
outputOptions(cmd)
|
|
1789
|
+
);
|
|
1507
1790
|
});
|
|
1508
|
-
metric.command("list <kn-id>").description("List metrics").action(async (knId,
|
|
1509
|
-
printJson(
|
|
1791
|
+
metric.command("list <kn-id>").description("List metrics").option("--branch <b>", "branch", "main").option("--name-pattern <s>", "fuzzy name filter").option("--tag <s>", "exact tag filter").action(async (knId, opts, cmd) => {
|
|
1792
|
+
printJson(
|
|
1793
|
+
await clientFrom(cmd).kn.metricList(knId, {
|
|
1794
|
+
branch: opts.branch,
|
|
1795
|
+
namePattern: opts.namePattern,
|
|
1796
|
+
tag: opts.tag
|
|
1797
|
+
}),
|
|
1798
|
+
outputOptions(cmd)
|
|
1799
|
+
);
|
|
1510
1800
|
});
|
|
1511
|
-
metric.command("get <kn-id> <metric-id>").description("Get a metric \u2192 {entries}, since the route takes a list of ids").action(async (knId, id,
|
|
1512
|
-
printJson(
|
|
1801
|
+
metric.command("get <kn-id> <metric-id>").description("Get a metric \u2192 {entries}, since the route takes a list of ids").option("--branch <b>", "branch (default: main)").action(async (knId, id, opts, cmd) => {
|
|
1802
|
+
printJson(
|
|
1803
|
+
await clientFrom(cmd).kn.metricGet(knId, id, { branch: opts.branch }),
|
|
1804
|
+
outputOptions(cmd)
|
|
1805
|
+
);
|
|
1513
1806
|
});
|
|
1514
|
-
|
|
1515
|
-
"
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1807
|
+
writeModeFlags(
|
|
1808
|
+
metric.command("create <kn-id>").description("Create metrics (--body / --body-file) \u2192 body is {entries:[\u2026]}").option(
|
|
1809
|
+
"--body <json>",
|
|
1810
|
+
"body JSON {entries:[\u2026]} (a bare array is wrapped) \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1811
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)"),
|
|
1812
|
+
true
|
|
1813
|
+
).action(async (knId, opts, cmd) => {
|
|
1814
|
+
printJson(
|
|
1815
|
+
await clientFrom(cmd).kn.metricCreate(knId, readBody(opts), writeModes(opts)),
|
|
1816
|
+
outputOptions(cmd)
|
|
1817
|
+
);
|
|
1519
1818
|
});
|
|
1520
|
-
|
|
1521
|
-
"
|
|
1522
|
-
|
|
1523
|
-
|
|
1819
|
+
writeModeFlags(
|
|
1820
|
+
metric.command("update <kn-id> <metric-id>").description("Update a metric (--body / --body-file)").option(
|
|
1821
|
+
"--body <json>",
|
|
1822
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1823
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)"),
|
|
1824
|
+
false
|
|
1825
|
+
).action(async (knId, id, opts, cmd) => {
|
|
1524
1826
|
printJson(
|
|
1525
|
-
await clientFrom(cmd).kn.metricUpdate(knId, id, readBody(opts)),
|
|
1827
|
+
await clientFrom(cmd).kn.metricUpdate(knId, id, readBody(opts), writeModes(opts)),
|
|
1526
1828
|
outputOptions(cmd)
|
|
1527
1829
|
);
|
|
1528
1830
|
});
|
|
1529
|
-
metric.command("delete <kn-id> <metric-id>").description("Delete a metric").action(async (knId, id,
|
|
1530
|
-
printJson(
|
|
1831
|
+
metric.command("delete <kn-id> <metric-id>").description("Delete a metric").option("--branch <b>", "branch (default: main)").action(async (knId, id, opts, cmd) => {
|
|
1832
|
+
printJson(
|
|
1833
|
+
await clientFrom(cmd).kn.metricDelete(knId, id, { branch: opts.branch }),
|
|
1834
|
+
outputOptions(cmd)
|
|
1835
|
+
);
|
|
1531
1836
|
});
|
|
1532
|
-
|
|
1533
|
-
"
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1837
|
+
writeModeFlags(
|
|
1838
|
+
metric.command("validate <kn-id>").description("Validate a metric definition (--body / --body-file)").option(
|
|
1839
|
+
"--body <json>",
|
|
1840
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1841
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)"),
|
|
1842
|
+
true
|
|
1843
|
+
).action(async (knId, opts, cmd) => {
|
|
1844
|
+
printJson(
|
|
1845
|
+
await clientFrom(cmd).kn.metricValidate(knId, readBody(opts), writeModes(opts)),
|
|
1846
|
+
outputOptions(cmd)
|
|
1847
|
+
);
|
|
1537
1848
|
});
|
|
1538
1849
|
const cg = bkn.command("concept-group").description("Concept groups \u2014 list/get");
|
|
1539
|
-
cg.command("list <kn-id>").description("List concept groups").action(async (knId,
|
|
1540
|
-
printJson(
|
|
1850
|
+
cg.command("list <kn-id>").description("List concept groups (all of them unless --limit is given)").option("--branch <b>", "branch (default: main)").option("--name-pattern <s>", "fuzzy name filter").option("--tag <s>", "exact tag filter").option("--sort <field>", "update_time | name", oneOf("--sort", NAME_OR_UPDATE_TIME)).option("--direction <dir>", "asc | desc", sortDirection).option("--offset <n>", "page offset", int3).option("--limit <n>", "page size (default: -1, all)", int3).action(async (knId, opts, cmd) => {
|
|
1851
|
+
printJson(
|
|
1852
|
+
await clientFrom(cmd).kn.conceptGroups(knId, {
|
|
1853
|
+
branch: opts.branch,
|
|
1854
|
+
namePattern: opts.namePattern,
|
|
1855
|
+
tag: opts.tag,
|
|
1856
|
+
sort: opts.sort,
|
|
1857
|
+
direction: opts.direction,
|
|
1858
|
+
offset: opts.offset,
|
|
1859
|
+
limit: opts.limit
|
|
1860
|
+
}),
|
|
1861
|
+
outputOptions(cmd)
|
|
1862
|
+
);
|
|
1541
1863
|
});
|
|
1542
|
-
cg.command("get <kn-id> <cg-id>").description("Get a concept group").action(async (knId, cgId,
|
|
1543
|
-
printJson(
|
|
1864
|
+
cg.command("get <kn-id> <cg-id>").description("Get a concept group").option("--branch <b>", "branch (default: main)").option("--stats", "include statistics").option("--mode <mode>", "response view mode (default view when omitted)").action(async (knId, cgId, opts, cmd) => {
|
|
1865
|
+
printJson(
|
|
1866
|
+
await clientFrom(cmd).kn.conceptGroup(knId, cgId, {
|
|
1867
|
+
branch: opts.branch,
|
|
1868
|
+
includeStatistics: opts.stats,
|
|
1869
|
+
mode: opts.mode
|
|
1870
|
+
}),
|
|
1871
|
+
outputOptions(cmd)
|
|
1872
|
+
);
|
|
1544
1873
|
});
|
|
1545
|
-
|
|
1546
|
-
"
|
|
1547
|
-
|
|
1548
|
-
|
|
1874
|
+
writeModeFlags(
|
|
1875
|
+
cg.command("create <kn-id>").description("Create a concept group (--body / --body-file)").option(
|
|
1876
|
+
"--body <json>",
|
|
1877
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1878
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)"),
|
|
1879
|
+
true
|
|
1880
|
+
).action(async (knId, opts, cmd) => {
|
|
1549
1881
|
printJson(
|
|
1550
|
-
await clientFrom(cmd).kn.conceptGroupCreate(knId, readBody(opts)),
|
|
1882
|
+
await clientFrom(cmd).kn.conceptGroupCreate(knId, readBody(opts), writeModes(opts)),
|
|
1551
1883
|
outputOptions(cmd)
|
|
1552
1884
|
);
|
|
1553
1885
|
});
|
|
1554
|
-
|
|
1555
|
-
"
|
|
1556
|
-
|
|
1557
|
-
|
|
1886
|
+
writeModeFlags(
|
|
1887
|
+
cg.command("update <kn-id> <cg-id>").description("Update a concept group (--body / --body-file)").option(
|
|
1888
|
+
"--body <json>",
|
|
1889
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1890
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)"),
|
|
1891
|
+
false
|
|
1892
|
+
).action(async (knId, cgId, opts, cmd) => {
|
|
1558
1893
|
printJson(
|
|
1559
|
-
await clientFrom(cmd).kn.conceptGroupUpdate(knId, cgId, readBody(opts)),
|
|
1894
|
+
await clientFrom(cmd).kn.conceptGroupUpdate(knId, cgId, readBody(opts), writeModes(opts)),
|
|
1560
1895
|
outputOptions(cmd)
|
|
1561
1896
|
);
|
|
1562
1897
|
});
|
|
1563
|
-
cg.command("delete <kn-id> <cg-id>").description("Delete a concept group").action(async (knId, cgId,
|
|
1564
|
-
printJson(
|
|
1898
|
+
cg.command("delete <kn-id> <cg-id>").description("Delete a concept group").option("--branch <b>", "branch (default: main)").action(async (knId, cgId, opts, cmd) => {
|
|
1899
|
+
printJson(
|
|
1900
|
+
await clientFrom(cmd).kn.conceptGroupDelete(knId, cgId, { branch: opts.branch }),
|
|
1901
|
+
outputOptions(cmd)
|
|
1902
|
+
);
|
|
1565
1903
|
});
|
|
1566
|
-
|
|
1567
|
-
"
|
|
1568
|
-
|
|
1569
|
-
|
|
1904
|
+
writeModeFlags(
|
|
1905
|
+
cg.command("add-members <kn-id> <cg-id>").description("Add object types to a concept group (--body / --body-file)").option(
|
|
1906
|
+
"--body <json>",
|
|
1907
|
+
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1908
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)"),
|
|
1909
|
+
false
|
|
1910
|
+
).action(async (knId, cgId, opts, cmd) => {
|
|
1570
1911
|
printJson(
|
|
1571
|
-
await clientFrom(cmd).kn.conceptGroupAddMembers(knId, cgId, readBody(opts)),
|
|
1912
|
+
await clientFrom(cmd).kn.conceptGroupAddMembers(knId, cgId, readBody(opts), writeModes(opts)),
|
|
1572
1913
|
outputOptions(cmd)
|
|
1573
1914
|
);
|
|
1574
1915
|
});
|
|
1575
|
-
cg.command("remove-members <kn-id> <cg-id> <ot-ids>").description("Remove object types (comma-joined ids) from a concept group").action(async (knId, cgId, otIds,
|
|
1916
|
+
cg.command("remove-members <kn-id> <cg-id> <ot-ids>").description("Remove object types (comma-joined ids) from a concept group").option("--branch <b>", "branch (default: main)").action(async (knId, cgId, otIds, opts, cmd) => {
|
|
1576
1917
|
printJson(
|
|
1577
|
-
await clientFrom(cmd).kn.conceptGroupRemoveMembers(knId, cgId, otIds
|
|
1918
|
+
await clientFrom(cmd).kn.conceptGroupRemoveMembers(knId, cgId, otIds, {
|
|
1919
|
+
branch: opts.branch
|
|
1920
|
+
}),
|
|
1578
1921
|
outputOptions(cmd)
|
|
1579
1922
|
);
|
|
1580
1923
|
});
|
|
1581
1924
|
const sched = bkn.command("action-schedule").description("Action schedules \u2014 list/get");
|
|
1582
|
-
sched.command("list <kn-id>").description("List action schedules").action(async (knId,
|
|
1583
|
-
printJson(
|
|
1925
|
+
sched.command("list <kn-id>").description("List action schedules (all of them unless --limit is given)").option("--branch <b>", "branch (default: main)").option("--name-pattern <s>", "fuzzy name filter").option("--action-type-id <id>", "filter by bound action type").option("--status <s>", "active | inactive", oneOf("--status", ["active", "inactive"])).option("--sort <field>", SCHEDULE_SORTS.join(" | "), oneOf("--sort", SCHEDULE_SORTS)).option("--direction <dir>", "asc | desc", sortDirection).option("--offset <n>", "page offset", int3).option("--limit <n>", "page size (default: -1, all)", int3).action(async (knId, opts, cmd) => {
|
|
1926
|
+
printJson(
|
|
1927
|
+
await clientFrom(cmd).kn.actionSchedules(knId, {
|
|
1928
|
+
branch: opts.branch,
|
|
1929
|
+
namePattern: opts.namePattern,
|
|
1930
|
+
actionTypeId: opts.actionTypeId,
|
|
1931
|
+
status: opts.status,
|
|
1932
|
+
sort: opts.sort,
|
|
1933
|
+
direction: opts.direction,
|
|
1934
|
+
offset: opts.offset,
|
|
1935
|
+
limit: opts.limit
|
|
1936
|
+
}),
|
|
1937
|
+
outputOptions(cmd)
|
|
1938
|
+
);
|
|
1584
1939
|
});
|
|
1585
|
-
sched.command("get <kn-id> <schedule-id>").description("Get an action schedule").action(async (knId, sId,
|
|
1586
|
-
printJson(
|
|
1940
|
+
sched.command("get <kn-id> <schedule-id>").description("Get an action schedule").option("--branch <b>", "branch (default: main)").action(async (knId, sId, opts, cmd) => {
|
|
1941
|
+
printJson(
|
|
1942
|
+
await clientFrom(cmd).kn.actionSchedule(knId, sId, { branch: opts.branch }),
|
|
1943
|
+
outputOptions(cmd)
|
|
1944
|
+
);
|
|
1587
1945
|
});
|
|
1588
1946
|
sched.command("create <kn-id>").description("Create an action schedule (--body / --body-file)").option(
|
|
1589
1947
|
"--body <json>",
|
|
1590
1948
|
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1591
|
-
).option("--body-file <path>", "read body JSON from a file").action(async (knId, opts, cmd) => {
|
|
1949
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)").action(async (knId, opts, cmd) => {
|
|
1592
1950
|
printJson(
|
|
1593
|
-
await clientFrom(cmd).kn.actionScheduleCreate(knId, readBody(opts)
|
|
1951
|
+
await clientFrom(cmd).kn.actionScheduleCreate(knId, readBody(opts), {
|
|
1952
|
+
branch: opts.branch
|
|
1953
|
+
}),
|
|
1594
1954
|
outputOptions(cmd)
|
|
1595
1955
|
);
|
|
1596
1956
|
});
|
|
1597
1957
|
sched.command("update <kn-id> <schedule-id>").description("Update an action schedule (--body / --body-file)").option(
|
|
1598
1958
|
"--body <json>",
|
|
1599
1959
|
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1600
|
-
).option("--body-file <path>", "read body JSON from a file").action(async (knId, sId, opts, cmd) => {
|
|
1960
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)").action(async (knId, sId, opts, cmd) => {
|
|
1601
1961
|
printJson(
|
|
1602
|
-
await clientFrom(cmd).kn.actionScheduleUpdate(knId, sId, readBody(opts)
|
|
1962
|
+
await clientFrom(cmd).kn.actionScheduleUpdate(knId, sId, readBody(opts), {
|
|
1963
|
+
branch: opts.branch
|
|
1964
|
+
}),
|
|
1603
1965
|
outputOptions(cmd)
|
|
1604
1966
|
);
|
|
1605
1967
|
});
|
|
1606
1968
|
sched.command("set-status <kn-id> <schedule-id>").description("Set an action schedule's status (--body / --body-file)").option(
|
|
1607
1969
|
"--body <json>",
|
|
1608
1970
|
"body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1609
|
-
).option("--body-file <path>", "read body JSON from a file").action(async (knId, sId, opts, cmd) => {
|
|
1971
|
+
).option("--body-file <path>", "read body JSON from a file").option("--branch <b>", "branch (default: main)").action(async (knId, sId, opts, cmd) => {
|
|
1610
1972
|
printJson(
|
|
1611
|
-
await clientFrom(cmd).kn.actionScheduleSetStatus(knId, sId, readBody(opts)
|
|
1973
|
+
await clientFrom(cmd).kn.actionScheduleSetStatus(knId, sId, readBody(opts), {
|
|
1974
|
+
branch: opts.branch
|
|
1975
|
+
}),
|
|
1612
1976
|
outputOptions(cmd)
|
|
1613
1977
|
);
|
|
1614
1978
|
});
|
|
1615
|
-
sched.command("delete <kn-id> <schedule-ids>").description("Delete action schedule(s) (comma-joined ids)").action(async (knId, ids,
|
|
1616
|
-
printJson(
|
|
1979
|
+
sched.command("delete <kn-id> <schedule-ids>").description("Delete action schedule(s) (comma-joined ids)").option("--branch <b>", "branch (default: main)").action(async (knId, ids, opts, cmd) => {
|
|
1980
|
+
printJson(
|
|
1981
|
+
await clientFrom(cmd).kn.actionScheduleDelete(knId, ids, { branch: opts.branch }),
|
|
1982
|
+
outputOptions(cmd)
|
|
1983
|
+
);
|
|
1617
1984
|
});
|
|
1618
|
-
bkn.command("
|
|
1619
|
-
|
|
1620
|
-
"
|
|
1621
|
-
|
|
1985
|
+
const capability = bkn.command("capability").description("Skills, tool box tools and MCP tools bound to a network \u2014 list/attach/detach");
|
|
1986
|
+
capability.command("list <kn-id>").description("List what the network has bound \u2192 {entries, boxes, total_count, \u2026}").option("--type <type>", "skill | function | mcp_tool").option("--box <box-id>", "only the tools of this tool box or MCP Server").option(
|
|
1987
|
+
"--metadata-type <kind>",
|
|
1988
|
+
"only function bindings whose tool box is openapi | function",
|
|
1989
|
+
oneOf("--metadata-type", ["openapi", "function"])
|
|
1990
|
+
).option("--with-detail", "also fill description and status (one extra call per skill)").option("--branch <name>", "knowledge network branch (default: main)").option("--limit <n>", "page size", int3).option("--offset <n>", "page offset", int3).option("--sort <field>", "create_time | update_time", oneOf("--sort", CAPABILITY_SORTS)).option("--direction <dir>", "asc | desc", sortDirection).action(async (knId, opts, cmd) => {
|
|
1991
|
+
if (opts.type && !CAPABILITY_TYPES.includes(opts.type)) {
|
|
1992
|
+
throw new InputError(`--type must be one of ${CAPABILITY_TYPES.join(", ")}.`);
|
|
1993
|
+
}
|
|
1622
1994
|
printJson(
|
|
1623
|
-
await clientFrom(cmd).kn.
|
|
1995
|
+
await clientFrom(cmd).kn.capabilityList(knId, {
|
|
1624
1996
|
branch: opts.branch,
|
|
1625
|
-
|
|
1626
|
-
|
|
1997
|
+
type: opts.type,
|
|
1998
|
+
boxId: opts.box,
|
|
1999
|
+
metadataType: opts.metadataType,
|
|
2000
|
+
withDetail: opts.withDetail,
|
|
2001
|
+
limit: opts.limit,
|
|
2002
|
+
offset: opts.offset,
|
|
2003
|
+
sort: opts.sort,
|
|
2004
|
+
direction: opts.direction
|
|
1627
2005
|
}),
|
|
1628
2006
|
outputOptions(cmd)
|
|
1629
2007
|
);
|
|
1630
2008
|
});
|
|
2009
|
+
capability.command("attach <kn-id>").description("Bind skills, tool box tools or MCP tools; binding one twice is a no-op").option("--skill <ids>", "skill ids (comma-separated)").option("--box <box-id>", "a tool box \u2014 name its tools with --tool, or take --all-tools").option("--mcp <mcp-id>", "an MCP Server \u2014 name its tools with --tool, or take --all-tools").option("--tool <ids>", "tool ids for --box, tool names for --mcp (comma-separated)").option("--all-tools", "every enabled tool the box or server holds now").option("--comment <text>", "note stored on each new binding").option("--branch <name>", "knowledge network branch (default: main)").addHelpText(
|
|
2010
|
+
"after",
|
|
2011
|
+
`
|
|
2012
|
+
A binding is always to a tool, never to a box. --all-tools is expanded when you run it
|
|
2013
|
+
into one binding per tool the box holds at that moment; a tool added to the box later is
|
|
2014
|
+
not bound until you attach it (\`capability list\` counts it under boxes[].unmounted_tools).
|
|
2015
|
+
|
|
2016
|
+
openbkn bkn capability attach <kn-id> --skill <skill-id>
|
|
2017
|
+
openbkn bkn capability attach <kn-id> --box <box-id> --tool <tool-id>[,<tool-id>]
|
|
2018
|
+
openbkn bkn capability attach <kn-id> --box <box-id> --all-tools
|
|
2019
|
+
openbkn bkn capability attach <kn-id> --mcp <mcp-id> --tool <tool-name>`
|
|
2020
|
+
).action(async (knId, opts, cmd) => {
|
|
2021
|
+
const entries = capabilityEntries(opts);
|
|
2022
|
+
printJson(
|
|
2023
|
+
await clientFrom(cmd).kn.capabilityAttach(knId, entries, { branch: opts.branch }),
|
|
2024
|
+
outputOptions(cmd)
|
|
2025
|
+
);
|
|
2026
|
+
});
|
|
2027
|
+
capability.command("detach <kn-id> <binding-ids>").description("Release bindings by id (comma-separated, from `capability list`)").option("--branch <name>", "knowledge network branch (default: main)").action(async (knId, ids, opts, cmd) => {
|
|
2028
|
+
const bindingIds = csv(ids) ?? [];
|
|
2029
|
+
if (bindingIds.length === 0) throw new InputError("Name at least one binding id.");
|
|
2030
|
+
await clientFrom(cmd).kn.capabilityDetach(knId, bindingIds, { branch: opts.branch });
|
|
2031
|
+
printJson(
|
|
2032
|
+
{ kn_id: knId, branch: opts.branch ?? "main", detached: bindingIds },
|
|
2033
|
+
outputOptions(cmd)
|
|
2034
|
+
);
|
|
2035
|
+
});
|
|
2036
|
+
bkn.command("push <directory>").description("Pack a BKN directory into a tar and import it as a knowledge network").option("--branch <name>", "target branch", "main").option(
|
|
2037
|
+
"--import-mode <mode>",
|
|
2038
|
+
"sent as import_mode: normal (default) | overwrite | ignore \u2014 0.1.5 deploys accept but do not apply it yet",
|
|
2039
|
+
oneOf("--import-mode", ["normal", "overwrite", "ignore"])
|
|
2040
|
+
).option(
|
|
2041
|
+
"--no-strict-mode",
|
|
2042
|
+
"send strict_mode=false (skip dependency checks) \u2014 0.1.5 deploys accept but do not apply it yet"
|
|
2043
|
+
).option(
|
|
2044
|
+
"--binding-policy <policy>",
|
|
2045
|
+
"environment-local bindings: preserve (default) | detach",
|
|
2046
|
+
oneOf("--binding-policy", ["preserve", "detach"])
|
|
2047
|
+
).action(async (dir, opts, cmd) => {
|
|
2048
|
+
const declared = validateBknDirectory(dir).capabilities;
|
|
2049
|
+
const result = await clientFrom(cmd).kn.push(dir, {
|
|
2050
|
+
branch: opts.branch,
|
|
2051
|
+
importMode: opts.importMode,
|
|
2052
|
+
strictMode: opts.strictMode === false ? false : void 0,
|
|
2053
|
+
bindingPolicy: opts.bindingPolicy,
|
|
2054
|
+
verifyIntegrity: true,
|
|
2055
|
+
onIntegrityWarning: (warning) => process.stderr.write(`warning: ${warning}
|
|
2056
|
+
`)
|
|
2057
|
+
});
|
|
2058
|
+
warnUnboundCapabilities(result, declared);
|
|
2059
|
+
printJson(result, outputOptions(cmd));
|
|
2060
|
+
});
|
|
1631
2061
|
bkn.command("pull <kn-id> [directory]").description("Download a knowledge network as a BKN tar and extract it locally").option("--branch <name>", "source branch", "main").action(async (knId, dir, opts, cmd) => {
|
|
1632
2062
|
printJson(
|
|
1633
2063
|
await clientFrom(cmd).kn.pull(knId, dir ?? knId, { branch: opts.branch }),
|
|
@@ -1637,31 +2067,69 @@ function bknCommand() {
|
|
|
1637
2067
|
bkn.command("relation-type-paths <kn-id>").description("Query relation-type paths between object types (--body / --body-file JSON)").option(
|
|
1638
2068
|
"--body <json>",
|
|
1639
2069
|
"request JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (bkn-backend)"
|
|
1640
|
-
).option("--body-file <path>", "read request JSON from a file").
|
|
2070
|
+
).option("--body-file <path>", "read request JSON from a file").option("--branch <b>", "branch (default: main)").addHelpText(
|
|
2071
|
+
"after",
|
|
2072
|
+
`
|
|
2073
|
+
The body needs source_object_type_id, direction (forward | backward | bidirectional) and
|
|
2074
|
+
path_length (1\u20133). The contract's enum spells the reverse direction \`reverse\`, but the
|
|
2075
|
+
backend refuses it with 400 InvalidParameter.Direction; use \`backward\`.
|
|
2076
|
+
|
|
2077
|
+
openbkn bkn relation-type-paths <kn-id> \\
|
|
2078
|
+
--body '{"source_object_type_id": "<ot-id>", "direction": "bidirectional", "path_length": 2}'`
|
|
2079
|
+
).action(async (knId, opts, cmd) => {
|
|
1641
2080
|
printJson(
|
|
1642
|
-
await clientFrom(cmd).kn.relationTypePaths(knId, readBody(opts)),
|
|
2081
|
+
await clientFrom(cmd).kn.relationTypePaths(knId, readBody(opts), { branch: opts.branch }),
|
|
1643
2082
|
outputOptions(cmd)
|
|
1644
2083
|
);
|
|
1645
2084
|
});
|
|
1646
|
-
bkn.command("
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
"
|
|
1651
|
-
"columns to vectorize per table (with --build): '<table>:<col>[+<col>...][,...]'"
|
|
2085
|
+
bkn.command("cypher <kn-id>").description(
|
|
2086
|
+
"Answer a read-only Cypher query over the network's model, outside any Trace session"
|
|
2087
|
+
).requiredOption(
|
|
2088
|
+
"--query <cypher>",
|
|
2089
|
+
"read-only Cypher: labels are object types, relationship types are relation types"
|
|
1652
2090
|
).option(
|
|
1653
|
-
"--
|
|
1654
|
-
|
|
1655
|
-
).option("--
|
|
2091
|
+
"--params <json>",
|
|
2092
|
+
`values for $name placeholders, as a JSON object: '{"floor": 100}'`
|
|
2093
|
+
).option("--branch <branch>", "knowledge network branch (default: main)").addHelpText(
|
|
2094
|
+
"after",
|
|
2095
|
+
`
|
|
2096
|
+
The compiler behind \`openbkn context run-cypher\`, called directly: the same subset,
|
|
2097
|
+
the same limits, the same refusals naming the construct and its position. Answers
|
|
2098
|
+
{columns, entries}; the generated SQL is never returned. Nothing is recorded in BKN
|
|
2099
|
+
Trace \u2014 use context run-cypher when the query is part of a conversation an agent
|
|
2100
|
+
should be able to account for.
|
|
2101
|
+
|
|
2102
|
+
openbkn bkn cypher <kn-id> \\
|
|
2103
|
+
--query "MATCH (c:customer)<-[:rel_order_customer]-(o:order) RETURN c.city AS city, count(*) AS orders"`
|
|
2104
|
+
).action(async (knId, opts, cmd) => {
|
|
2105
|
+
if (!opts.query.trim()) throw new InputError("--query must not be empty.");
|
|
2106
|
+
printJson(
|
|
2107
|
+
await clientFrom(cmd).kn.cypher(knId, opts.query, {
|
|
2108
|
+
branch: opts.branch,
|
|
2109
|
+
parameters: cypherParams(opts.params)
|
|
2110
|
+
}),
|
|
2111
|
+
outputOptions(cmd)
|
|
2112
|
+
);
|
|
2113
|
+
});
|
|
2114
|
+
bkn.command("resources").description("List BKN-backend resources (knowledge networks) \u2192 {entries, total_count}").option("--keyword <s>", "name keyword filter").option("--limit <n>", "page size", int3, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int3, 0).option("--sort <field>", "sort field (default: name)").option("--direction <dir>", "asc | desc", sortDirection).action(async (opts, cmd) => {
|
|
2115
|
+
printJson(
|
|
2116
|
+
await clientFrom(cmd).kn.bknResources({
|
|
2117
|
+
keyword: opts.keyword,
|
|
2118
|
+
limit: opts.limit,
|
|
2119
|
+
offset: opts.offset,
|
|
2120
|
+
sort: opts.sort,
|
|
2121
|
+
direction: opts.direction
|
|
2122
|
+
}),
|
|
2123
|
+
outputOptions(cmd)
|
|
2124
|
+
);
|
|
2125
|
+
});
|
|
2126
|
+
bkn.command("create-from-catalog <catalog-id>").description("Build a knowledge network from a Vega catalog's tables").requiredOption("--name <name>", "knowledge network name").option("--tables <list>", "comma-separated table names (default: all)").option("--pk-map <map>", "explicit primary keys: '<table>:<col>[,<table>:<col>...]'").option("--no-rollback", "keep a partially-created KN on failure").action(async (catalogId, opts, cmd) => {
|
|
1656
2127
|
printJson(
|
|
1657
2128
|
await clientFrom(cmd).kn.createFromCatalog({
|
|
1658
2129
|
catalogId,
|
|
1659
2130
|
name: opts.name,
|
|
1660
2131
|
tables: csv(opts.tables),
|
|
1661
2132
|
pkMap: opts.pkMap ? parsePkMap(opts.pkMap) : void 0,
|
|
1662
|
-
build: Boolean(opts.build),
|
|
1663
|
-
embeddingFields: opts.embeddingFields ? parseEmbeddingFields(opts.embeddingFields) : void 0,
|
|
1664
|
-
embeddingModel: opts.embeddingModel,
|
|
1665
2133
|
noRollback: opts.rollback === false,
|
|
1666
2134
|
onProgress: (m) => console.error(m)
|
|
1667
2135
|
}),
|
|
@@ -1680,6 +2148,7 @@ function bknCommand() {
|
|
|
1680
2148
|
"action-type",
|
|
1681
2149
|
"metric",
|
|
1682
2150
|
"concept-group",
|
|
2151
|
+
"capability",
|
|
1683
2152
|
"action-log",
|
|
1684
2153
|
"action-schedule"
|
|
1685
2154
|
],
|
|
@@ -1692,6 +2161,7 @@ function bknCommand() {
|
|
|
1692
2161
|
"search",
|
|
1693
2162
|
"subgraph",
|
|
1694
2163
|
"relation-type-paths",
|
|
2164
|
+
"cypher",
|
|
1695
2165
|
"resources",
|
|
1696
2166
|
"action-execution",
|
|
1697
2167
|
"validate"
|
|
@@ -1703,6 +2173,10 @@ function bknCommand() {
|
|
|
1703
2173
|
RUN: ["query", "dry-run", "validate"],
|
|
1704
2174
|
WRITE: ["create", "update", "delete"]
|
|
1705
2175
|
});
|
|
2176
|
+
groupChildren(capability, {
|
|
2177
|
+
READ: ["list"],
|
|
2178
|
+
WRITE: ["attach", "detach"]
|
|
2179
|
+
});
|
|
1706
2180
|
guide(
|
|
1707
2181
|
bkn,
|
|
1708
2182
|
`WHERE IDS COME FROM
|
|
@@ -1718,6 +2192,13 @@ SEARCH VS THE MCP SIDE
|
|
|
1718
2192
|
EDITING SCHEMA AS FILES
|
|
1719
2193
|
pull <kn-id> ./dir -> edit -> validate ./dir -> push ./dir
|
|
1720
2194
|
\`validate\` is offline and catches structure errors before the upload.
|
|
2195
|
+
network.bkn may declare the skills and tools the network depends on under
|
|
2196
|
+
\`capabilities:\`. push binds them by id, then by name; one this platform cannot
|
|
2197
|
+
resolve is skipped, not fatal, and push lists every skip on stderr.
|
|
2198
|
+
|
|
2199
|
+
CAPABILITIES
|
|
2200
|
+
\`capability list <kn-id>\` shows what a network has bound \u2014 the set Context Loader
|
|
2201
|
+
recalls skills and tools from; a network with nothing bound recalls nothing.
|
|
1721
2202
|
|
|
1722
2203
|
REQUEST BODIES
|
|
1723
2204
|
create/update take a definition; query/execute/dry-run take a query. Both are documented
|
|
@@ -1726,7 +2207,7 @@ REQUEST BODIES
|
|
|
1726
2207
|
|
|
1727
2208
|
CREATING FROM DATA
|
|
1728
2209
|
create-from-catalog <catalog-id> --name "<n>" builds a network from a Vega catalog,
|
|
1729
|
-
then \`openbkn vega
|
|
2210
|
+
then \`openbkn vega resource build <resource-id>\` produces the index. There is no
|
|
1730
2211
|
whole-network build.`
|
|
1731
2212
|
);
|
|
1732
2213
|
return group(bkn, "DATA & KNOWLEDGE");
|
|
@@ -1739,7 +2220,7 @@ function collect(value, prev) {
|
|
|
1739
2220
|
return prev;
|
|
1740
2221
|
}
|
|
1741
2222
|
function callCommand() {
|
|
1742
|
-
const cmd = new Command5("call").alias("curl").description("Call any platform API endpoint directly (auth added)").argument("<url>", "API path (e.g. /api/...) or absolute URL").option("-X, --request <method>", "HTTP method").option("-H, --header <header>", 'extra header "Name: value" (repeatable)', collect, []).option("-d, --data <body>", "request body (sets JSON content-type if unset)").option("--data-raw <body>", "alias for --data").option(
|
|
2223
|
+
const cmd = new Command5("call").alias("curl").description("Call any platform API endpoint directly (auth added)").argument("<url>", "API path (e.g. /api/...) or absolute URL on the current platform").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(
|
|
1743
2224
|
"-F, --form <field>",
|
|
1744
2225
|
"multipart field key=value or key=@file (repeatable)",
|
|
1745
2226
|
collect,
|
|
@@ -1751,8 +2232,9 @@ function callCommand() {
|
|
|
1751
2232
|
baseUrl: g.baseUrl,
|
|
1752
2233
|
token: g.token,
|
|
1753
2234
|
user: g.user,
|
|
1754
|
-
businessDomain: g.bizDomain,
|
|
1755
2235
|
insecure: g.insecure,
|
|
2236
|
+
versionCheckMode: "cli",
|
|
2237
|
+
...retryOptionsFrom(g),
|
|
1756
2238
|
...trace ? { trace } : {}
|
|
1757
2239
|
});
|
|
1758
2240
|
const res = await rawCall(ctx, url, {
|
|
@@ -1760,7 +2242,6 @@ function callCommand() {
|
|
|
1760
2242
|
header: opts.header,
|
|
1761
2243
|
data: opts.data ?? opts.dataRaw,
|
|
1762
2244
|
form: opts.form,
|
|
1763
|
-
businessDomain: g.bizDomain,
|
|
1764
2245
|
verbose: opts.verbose
|
|
1765
2246
|
});
|
|
1766
2247
|
const out = outputOptions(cmd2);
|
|
@@ -1785,69 +2266,42 @@ function callCommand() {
|
|
|
1785
2266
|
|
|
1786
2267
|
FINDING THE PATH
|
|
1787
2268
|
Every service's API is documented at https://openbkn-ai.github.io/bkn-foundry/ \u2014
|
|
1788
|
-
read the path and request body there rather than guessing.
|
|
1789
|
-
|
|
2269
|
+
read the path and request body there rather than guessing. Authentication and
|
|
2270
|
+
TLS flags are injected the same way as for any other command.`
|
|
1790
2271
|
);
|
|
1791
2272
|
return group(cmd, "RAW API");
|
|
1792
2273
|
}
|
|
1793
2274
|
|
|
1794
2275
|
// src/commands/config.ts
|
|
1795
2276
|
import { Command as Command6 } from "commander";
|
|
1796
|
-
function requireActive() {
|
|
1797
|
-
const baseUrl = activePlatform();
|
|
1798
|
-
if (!baseUrl) throw new InputError("No active platform. Run `openbkn auth login <url>` first.");
|
|
1799
|
-
return baseUrl;
|
|
1800
|
-
}
|
|
1801
2277
|
function configCommand() {
|
|
1802
|
-
const config = new Command6("config").description("Remember a platform URL
|
|
1803
|
-
config.command("show").description("Show the active platform
|
|
2278
|
+
const config = new Command6("config").description("Remember a platform URL");
|
|
2279
|
+
config.command("show").description("Show the active platform").action((_opts, cmd) => {
|
|
1804
2280
|
const baseUrl = activePlatform();
|
|
1805
|
-
printJson(
|
|
1806
|
-
{
|
|
1807
|
-
baseUrl,
|
|
1808
|
-
businessDomain: baseUrl ? readPlatformConfig(baseUrl).businessDomain : void 0
|
|
1809
|
-
},
|
|
1810
|
-
outputOptions(cmd)
|
|
1811
|
-
);
|
|
2281
|
+
printJson({ baseUrl }, outputOptions(cmd));
|
|
1812
2282
|
});
|
|
1813
|
-
config.command("set <key> <value>").description("Set a config value (baseUrl
|
|
2283
|
+
config.command("set <key> <value>").description("Set a config value (baseUrl)").action((key, value, _opts, cmd) => {
|
|
1814
2284
|
if (key === "baseUrl") {
|
|
1815
2285
|
setActivePlatform(trimTrailingSlashes(value));
|
|
1816
|
-
} else if (key === "businessDomain") {
|
|
1817
|
-
updatePlatformConfig(requireActive(), { businessDomain: value });
|
|
1818
2286
|
} else {
|
|
1819
|
-
throw new InputError(`Unknown config key: ${key} (expected baseUrl
|
|
2287
|
+
throw new InputError(`Unknown config key: ${key} (expected baseUrl)`);
|
|
1820
2288
|
}
|
|
1821
2289
|
printJson({ ok: true, key, value }, outputOptions(cmd));
|
|
1822
2290
|
});
|
|
1823
|
-
config
|
|
1824
|
-
const baseUrl = requireActive();
|
|
1825
|
-
updatePlatformConfig(baseUrl, { businessDomain: value });
|
|
1826
|
-
printJson({ baseUrl, businessDomain: value }, outputOptions(cmd));
|
|
1827
|
-
});
|
|
1828
|
-
config.command("list-bd").description("List business domains (requires login)").action(() => {
|
|
1829
|
-
throw new InputError("Not yet implemented \u2014 requires backend business-domains API.");
|
|
1830
|
-
});
|
|
1831
|
-
groupChildren(config, { READ: ["show", "list-bd"], WRITE: ["set", "set-bd"] });
|
|
2291
|
+
groupChildren(config, { READ: ["show"], WRITE: ["set"] });
|
|
1832
2292
|
return group(config, "SIGN IN & SETTINGS");
|
|
1833
2293
|
}
|
|
1834
2294
|
|
|
1835
2295
|
// src/commands/context.ts
|
|
1836
|
-
import { Command as Command7 } from "commander";
|
|
2296
|
+
import { Command as Command7, Option as Option2 } from "commander";
|
|
1837
2297
|
var int4 = (v) => Number.parseInt(v, 10);
|
|
2298
|
+
var list = (v) => v.split(",").map((part) => part.trim()).filter(Boolean);
|
|
1838
2299
|
var collectArg = (v, prev) => {
|
|
1839
2300
|
prev.push(v);
|
|
1840
2301
|
return prev;
|
|
1841
2302
|
};
|
|
1842
2303
|
function buildArgs(opts) {
|
|
1843
|
-
|
|
1844
|
-
if (opts.args) {
|
|
1845
|
-
try {
|
|
1846
|
-
out = parseBigIntJSON(opts.args);
|
|
1847
|
-
} catch {
|
|
1848
|
-
throw new InputError("--args must be valid JSON");
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
2304
|
+
const out = readJsonArgs(opts) ?? {};
|
|
1851
2305
|
for (const pair of opts.arg ?? []) {
|
|
1852
2306
|
const idx = pair.indexOf("=");
|
|
1853
2307
|
if (idx <= 0) throw new InputError(`--arg must be key=value (got: ${pair})`);
|
|
@@ -1882,20 +2336,34 @@ function contextCommand() {
|
|
|
1882
2336
|
const cmd = new Command7("context").description(
|
|
1883
2337
|
"Ask a network questions (the MCP interface agents use)"
|
|
1884
2338
|
);
|
|
1885
|
-
const jsonArgs = (
|
|
1886
|
-
if (!raw) throw new InputError("--args is required (run with --schema to see its shape)");
|
|
1887
|
-
try {
|
|
1888
|
-
return parseBigIntJSON(raw);
|
|
1889
|
-
} catch {
|
|
1890
|
-
throw new InputError("--args must be valid JSON");
|
|
1891
|
-
}
|
|
1892
|
-
};
|
|
2339
|
+
const jsonArgs = (opts) => readJsonArgs(opts, true);
|
|
1893
2340
|
cmd.command("search-schema <kn-id> <query>").description(
|
|
1894
2341
|
"Search object/relation/action/metric schemas \u2192 {object_types, relation_types, action_types, metric_types}"
|
|
1895
|
-
).option(
|
|
2342
|
+
).option(
|
|
2343
|
+
"--concept-groups <ids>",
|
|
2344
|
+
"comma-separated concept-group ids to confine recall to (ids from kn-detail)",
|
|
2345
|
+
list
|
|
2346
|
+
).option(
|
|
2347
|
+
"--only <kinds>",
|
|
2348
|
+
"return only these concept kinds, comma-separated: object,relation,action,metric",
|
|
2349
|
+
list
|
|
2350
|
+
).addOption(new Option2("--scope <kinds>", "alias of --only").argParser(list).hideHelp()).option("--max <n>", "max concepts per kind", int4).option(
|
|
2351
|
+
"--schema-brief",
|
|
2352
|
+
"trimmed schema: property name/type only (MCP tool default true; REST default false)"
|
|
2353
|
+
).option("--no-schema-brief", "full schema: adds property comments, primary keys and tags").option("--include-columns", "add each data property's physical column (needed for run-sql)").option("--rerank", "re-rank relation types (the server default)").option("--no-rerank", "skip relation-type re-ranking").option("--rerank-model <name>", "override the deploy's rerank model (operators only)").action(async (knId, query, opts, cmd2) => {
|
|
2354
|
+
if (opts.only && opts.scope) throw new InputError("--scope is an alias of --only; pass one");
|
|
2355
|
+
const kinds = opts.only ?? opts.scope;
|
|
2356
|
+
const scope = {
|
|
2357
|
+
...kinds ? scopeFromKinds(kinds) : {},
|
|
2358
|
+
...opts.conceptGroups?.length ? { conceptGroups: opts.conceptGroups } : {}
|
|
2359
|
+
};
|
|
1896
2360
|
const data = await clientFrom(cmd2).context.searchSchema(knId, query, {
|
|
1897
|
-
searchScope:
|
|
1898
|
-
maxConcepts: opts.max
|
|
2361
|
+
searchScope: Object.keys(scope).length > 0 ? scope : void 0,
|
|
2362
|
+
maxConcepts: opts.max,
|
|
2363
|
+
schemaBrief: opts.schemaBrief,
|
|
2364
|
+
enableRerank: opts.rerank,
|
|
2365
|
+
rerankModel: opts.rerankModel,
|
|
2366
|
+
includeColumns: opts.includeColumns
|
|
1899
2367
|
});
|
|
1900
2368
|
printJson(data, outputOptions(cmd2));
|
|
1901
2369
|
});
|
|
@@ -1903,21 +2371,37 @@ function contextCommand() {
|
|
|
1903
2371
|
`Query one object type's instances \u2014 \`--args '{"ot_id":"<id>","limit":10}'\` \u2192 {datas, total_count}`
|
|
1904
2372
|
).option(
|
|
1905
2373
|
"--args <json>",
|
|
1906
|
-
"tool arguments as JSON; kn_id is filled from <kn-id
|
|
1907
|
-
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2374
|
+
"tool arguments as JSON (- for stdin); kn_id is filled from <kn-id> unless given; --schema prints the shape"
|
|
2375
|
+
).option("--args-file <path>", "read tool arguments as JSON from a file (or - for stdin)").option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
1908
2376
|
if (opts.schema) return printToolSchema(cmd2, knId, "query_object_instance");
|
|
1909
|
-
const args = jsonArgs(opts
|
|
2377
|
+
const args = jsonArgs(opts);
|
|
1910
2378
|
printJson(await clientFrom(cmd2).context.queryObjectInstance(knId, args), outputOptions(cmd2));
|
|
1911
2379
|
});
|
|
1912
|
-
cmd.command("
|
|
2380
|
+
cmd.command("search-capabilities <kn-id>").description(
|
|
2381
|
+
"Rank every capability the network mounted: skills, functions, API tools, MCP tools"
|
|
2382
|
+
).option("--query <text>", "rank by relevance; omit to list in mount order").option("--types <list>", "comma-separated: skill,function,mcp_tool", list).option(
|
|
2383
|
+
"--metadata-types <list>",
|
|
2384
|
+
"comma-separated: openapi,function (splits function tools)",
|
|
2385
|
+
list
|
|
2386
|
+
).option("--owner-id <id>", "one toolbox or MCP server").option("--limit <n>", "max results (1-100)", int4).action(async (knId, opts, cmd2) => {
|
|
1913
2387
|
printJson(
|
|
1914
|
-
await clientFrom(cmd2).context.
|
|
2388
|
+
await clientFrom(cmd2).context.searchCapabilities(knId, {
|
|
2389
|
+
query: opts.query,
|
|
2390
|
+
types: opts.types,
|
|
2391
|
+
metadataTypes: opts.metadataTypes,
|
|
2392
|
+
ownerId: opts.ownerId,
|
|
2393
|
+
limit: opts.limit
|
|
2394
|
+
}),
|
|
1915
2395
|
outputOptions(cmd2)
|
|
1916
2396
|
);
|
|
1917
2397
|
});
|
|
1918
|
-
cmd.command("kn-detail <kn-id>").description("Get a KN's schema at a detail level (progressive: summary skeleton \u2192 drill down)").option(
|
|
1919
|
-
|
|
1920
|
-
|
|
2398
|
+
cmd.command("kn-detail <kn-id>").description("Get a KN's schema at a detail level (progressive: summary skeleton \u2192 drill down)").option(
|
|
2399
|
+
"--detail-level <level>",
|
|
2400
|
+
"summary (default) | full",
|
|
2401
|
+
oneOf("--detail-level", ["summary", "full"]),
|
|
2402
|
+
"summary"
|
|
2403
|
+
).action(async (knId, opts, cmd2) => {
|
|
2404
|
+
printJson(await clientFrom(cmd2).context.knDetail(knId, opts.detailLevel), outputOptions(cmd2));
|
|
1921
2405
|
});
|
|
1922
2406
|
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) => {
|
|
1923
2407
|
printJson(await clientFrom(cmd2).context.objectTypes(knId, ids), outputOptions(cmd2));
|
|
@@ -1994,6 +2478,51 @@ adds paging and --need-total but records nothing in Trace.`
|
|
|
1994
2478
|
if (opts.timeout !== void 0) args.query_timeout = opts.timeout;
|
|
1995
2479
|
printJson(await clientFrom(cmd2).context.toolCall(knId, "run_sql", args), outputOptions(cmd2));
|
|
1996
2480
|
});
|
|
2481
|
+
cmd.command("run-cypher <kn-id>").description(
|
|
2482
|
+
"Filter along a path and aggregate across object types with read-only Cypher over the model"
|
|
2483
|
+
).option(
|
|
2484
|
+
"--query <cypher>",
|
|
2485
|
+
"read-only Cypher: labels are object types, relationship types are relation types"
|
|
2486
|
+
).option(
|
|
2487
|
+
"--params <json>",
|
|
2488
|
+
`values for $name placeholders, as a JSON object: '{"floor": 100}'`
|
|
2489
|
+
).option("--branch <branch>", "knowledge network branch (default: main)").option("--schema", "print this tool's argument schema from the deploy instead of calling it").addHelpText(
|
|
2490
|
+
"after",
|
|
2491
|
+
`
|
|
2492
|
+
Everything is named the way the model names it \u2014 no resource id, no physical column:
|
|
2493
|
+
|
|
2494
|
+
openbkn context search-schema <kn-id> "<what you are after>" --json
|
|
2495
|
+
\u2192 object type and relation type ids or names, property names
|
|
2496
|
+
|
|
2497
|
+
openbkn context run-cypher <kn-id> \\
|
|
2498
|
+
--query "MATCH (o:order)-[:rel_order_item_order]->(i:order_item)
|
|
2499
|
+
WHERE o.status IN ['paid','shipped'] AND o.amount > \\$floor
|
|
2500
|
+
RETURN o.status AS status, count(*) AS orders ORDER BY orders DESC LIMIT 20" \\
|
|
2501
|
+
--params '{"floor": 100}'
|
|
2502
|
+
|
|
2503
|
+
Supported: several MATCH clauses and comma-separated paths; -[:R]->, <-[:R]- and
|
|
2504
|
+
undirected -[:R]-; WHERE with comparisons, IN, IS NULL, AND/OR/NOT; RETURN with
|
|
2505
|
+
aliases, DISTINCT and count/sum/avg/min/max (grouping by the other returned columns);
|
|
2506
|
+
ORDER BY, SKIP, LIMIT. Refused with the construct and its position: OPTIONAL MATCH,
|
|
2507
|
+
WITH, UNION, variable-length paths, functions and arithmetic, returning a whole node.
|
|
2508
|
+
A query holds at most 8 relationships and 9 nodes; without LIMIT it returns 1000 rows,
|
|
2509
|
+
and LIMIT may not exceed 10000.
|
|
2510
|
+
|
|
2511
|
+
What Cypher cannot say \u2014 CTEs, UNION, window functions \u2014 or a resource never modelled
|
|
2512
|
+
as an object type belongs in run-sql. The same query runs outside any Trace session
|
|
2513
|
+
through \`openbkn bkn cypher\`.`
|
|
2514
|
+
).action(async (knId, opts, cmd2) => {
|
|
2515
|
+
if (opts.schema) return printToolSchema(cmd2, knId, "run_cypher");
|
|
2516
|
+
if (!opts.query)
|
|
2517
|
+
throw new InputError("--query is required (or use --schema to see the shape)");
|
|
2518
|
+
printJson(
|
|
2519
|
+
await clientFrom(cmd2).context.runCypher(knId, opts.query, {
|
|
2520
|
+
branch: opts.branch,
|
|
2521
|
+
parameters: cypherParams(opts.params)
|
|
2522
|
+
}),
|
|
2523
|
+
outputOptions(cmd2)
|
|
2524
|
+
);
|
|
2525
|
+
});
|
|
1997
2526
|
cmd.command("explore-subgraph <kn-id> <object-type-id>").description("Follow relations outward from one object type without naming a path first").option("--hops <n>", "how many hops to walk, 1-3", (v) => Number.parseInt(v, 10)).option(
|
|
1998
2527
|
"--direction <d>",
|
|
1999
2528
|
"forward | backward | bidirectional \u2014 pick bidirectional when unsure how the relation reads",
|
|
@@ -2002,7 +2531,10 @@ adds paging and --need-total but records nothing in Trace.`
|
|
|
2002
2531
|
"--limit <n>",
|
|
2003
2532
|
"instances of the STARTING type, not paths or total objects",
|
|
2004
2533
|
(v) => Number.parseInt(v, 10)
|
|
2005
|
-
).option(
|
|
2534
|
+
).option(
|
|
2535
|
+
"--args <json>",
|
|
2536
|
+
"extra tool arguments merged in (condition, sort, offset \u2026; - for stdin)"
|
|
2537
|
+
).option("--args-file <path>", "read extra tool arguments as JSON from a file (or - for stdin)").option("--schema", "print this tool's argument schema from the deploy instead of calling it").addHelpText(
|
|
2006
2538
|
"after",
|
|
2007
2539
|
`
|
|
2008
2540
|
Use this when the topology is the question \u2014 "what does this supplier touch?" \u2014
|
|
@@ -2014,7 +2546,7 @@ Paths multiply with each hop, so start at 1 or 2.`
|
|
|
2014
2546
|
throw new InputError("--hops is required (or use --schema to see the shape)");
|
|
2015
2547
|
}
|
|
2016
2548
|
const args = {
|
|
2017
|
-
...
|
|
2549
|
+
...readJsonArgs(opts) ?? {},
|
|
2018
2550
|
source_object_type_id: objectTypeId,
|
|
2019
2551
|
direction: opts.direction,
|
|
2020
2552
|
path_length: opts.hops
|
|
@@ -2027,8 +2559,8 @@ Paths multiply with each hop, so start at 1 or 2.`
|
|
|
2027
2559
|
});
|
|
2028
2560
|
cmd.command("query-metric <kn-id> <metric-id>").description("Read a modelled metric through its own definition \u2014 do not restate it in SQL").option(
|
|
2029
2561
|
"--args <json>",
|
|
2030
|
-
"tool arguments: analysis_dimensions, time, condition, having, order_by"
|
|
2031
|
-
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").addHelpText(
|
|
2562
|
+
"tool arguments: analysis_dimensions, time, condition, having, order_by, limit, fill_null; - for stdin"
|
|
2563
|
+
).option("--args-file <path>", "read tool arguments as JSON from a file (or - for stdin)").option("--schema", "print this tool's argument schema from the deploy instead of calling it").addHelpText(
|
|
2032
2564
|
"after",
|
|
2033
2565
|
`
|
|
2034
2566
|
Metric ids come from an object type: \`context object-types <kn-id> <ot-id>\`
|
|
@@ -2036,7 +2568,7 @@ lists them under related_metrics. The definition owns the arithmetic, so
|
|
|
2036
2568
|
rewriting it with \`run-sql\` produces a number the platform will not agree with.`
|
|
2037
2569
|
).action(async (knId, metricId, opts, cmd2) => {
|
|
2038
2570
|
if (opts.schema) return printToolSchema(cmd2, knId, "query_metric");
|
|
2039
|
-
const args = { ...
|
|
2571
|
+
const args = { ...readJsonArgs(opts) ?? {}, metric_id: metricId };
|
|
2040
2572
|
printJson(
|
|
2041
2573
|
await clientFrom(cmd2).context.toolCall(knId, "query_metric", args),
|
|
2042
2574
|
outputOptions(cmd2)
|
|
@@ -2047,8 +2579,8 @@ rewriting it with \`run-sql\` produces a number the platform will not agree with
|
|
|
2047
2579
|
});
|
|
2048
2580
|
cmd.command("tool-call <kn-id> <name>").description("Call any MCP tool by name \u2014 current or future (use `tools` to discover)").option(
|
|
2049
2581
|
"--args <json>",
|
|
2050
|
-
"tool arguments as JSON; kn_id
|
|
2051
|
-
).option(
|
|
2582
|
+
"tool arguments as JSON (- for stdin); kn_id (for network-scoped tools) and response_format=json are filled unless given \u2014 input schema comes from `context tools <kn-id>`"
|
|
2583
|
+
).option("--args-file <path>", "read tool arguments as JSON from a file (or - for stdin)").option(
|
|
2052
2584
|
"--arg <key=value>",
|
|
2053
2585
|
"one argument (repeatable; value parsed as JSON, else string)",
|
|
2054
2586
|
collectArg,
|
|
@@ -2056,8 +2588,23 @@ rewriting it with \`run-sql\` produces a number the platform will not agree with
|
|
|
2056
2588
|
).option(
|
|
2057
2589
|
"--schema",
|
|
2058
2590
|
"print the named tool's argument schema from the deploy instead of calling it"
|
|
2059
|
-
).action(async (knId, name, opts, cmd2) => {
|
|
2591
|
+
).option("--receipt", "return the validated operation receipt (requires --json or --compact)").action(async (knId, name, opts, cmd2) => {
|
|
2592
|
+
if (opts.receipt && opts.schema) {
|
|
2593
|
+
throw new InputError("--receipt cannot be combined with --schema");
|
|
2594
|
+
}
|
|
2595
|
+
if (opts.receipt && !cmd2.optsWithGlobals().json && !cmd2.optsWithGlobals().compact) {
|
|
2596
|
+
throw new InputError("--receipt requires --json or --compact");
|
|
2597
|
+
}
|
|
2060
2598
|
if (opts.schema) return printToolSchema(cmd2, knId, name);
|
|
2599
|
+
if (opts.receipt) {
|
|
2600
|
+
const { value, receipt } = await clientFrom(cmd2).context.managedToolCall(
|
|
2601
|
+
knId,
|
|
2602
|
+
name,
|
|
2603
|
+
buildArgs(opts)
|
|
2604
|
+
);
|
|
2605
|
+
printJson({ value, bkn_receipt: receipt }, { ...outputOptions(cmd2), json: true });
|
|
2606
|
+
return;
|
|
2607
|
+
}
|
|
2061
2608
|
printJson(
|
|
2062
2609
|
await clientFrom(cmd2).context.toolCall(knId, name, buildArgs(opts)),
|
|
2063
2610
|
outputOptions(cmd2)
|
|
@@ -2065,7 +2612,7 @@ rewriting it with \`run-sql\` produces a number the platform will not agree with
|
|
|
2065
2612
|
});
|
|
2066
2613
|
cmd.command("call-method <kn-id> <method>").description(
|
|
2067
2614
|
"Call any MCP method by name (e.g. tools/list, resources/read) \u2014 current or future"
|
|
2068
|
-
).option("--args <json>", "method params as JSON
|
|
2615
|
+
).option("--args <json>", "method params as JSON; use - for stdin").option("--args-file <path>", "read method params as JSON from a file (or - for stdin)").option(
|
|
2069
2616
|
"--arg <key=value>",
|
|
2070
2617
|
"one param (repeatable; value parsed as JSON, else string)",
|
|
2071
2618
|
collectArg,
|
|
@@ -2088,49 +2635,36 @@ rewriting it with \`run-sql\` produces a number the platform will not agree with
|
|
|
2088
2635
|
cmd.command("prompts <kn-id>").description("List MCP prompts").action(async (knId, _opts, cmd2) => {
|
|
2089
2636
|
printJson(await clientFrom(cmd2).context.prompts(knId), outputOptions(cmd2));
|
|
2090
2637
|
});
|
|
2091
|
-
cmd.command("prompt <kn-id> <name>").description("Get one MCP prompt (--args JSON for prompt arguments)").option(
|
|
2092
|
-
|
|
2093
|
-
"prompt arguments as JSON \u2014 argument names come from `context prompts <kn-id>`"
|
|
2094
|
-
).action(async (knId, name, opts, cmd2) => {
|
|
2095
|
-
let args;
|
|
2096
|
-
if (opts.args) {
|
|
2097
|
-
try {
|
|
2098
|
-
args = parseBigIntJSON(opts.args);
|
|
2099
|
-
} catch {
|
|
2100
|
-
throw new InputError("--args must be valid JSON");
|
|
2101
|
-
}
|
|
2102
|
-
}
|
|
2638
|
+
cmd.command("prompt <kn-id> <name>").description("Get one MCP prompt (--args JSON for prompt arguments)").option("--args <json>", "prompt arguments as JSON; use - for stdin").option("--args-file <path>", "read prompt arguments as JSON from a file (or - for stdin)").action(async (knId, name, opts, cmd2) => {
|
|
2639
|
+
const args = readJsonArgs(opts);
|
|
2103
2640
|
printJson(await clientFrom(cmd2).context.prompt(knId, name, args), outputOptions(cmd2));
|
|
2104
2641
|
});
|
|
2105
2642
|
cmd.command("query-instance-subgraph <kn-id>").description("Query an instance subgraph across relation-type paths").option(
|
|
2106
2643
|
"--args <json>",
|
|
2107
|
-
"tool arguments as JSON; kn_id is filled from <kn-id
|
|
2108
|
-
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2644
|
+
"tool arguments as JSON (- for stdin); kn_id is filled from <kn-id> unless given; --schema prints the shape"
|
|
2645
|
+
).option("--args-file <path>", "read tool arguments as JSON from a file (or - for stdin)").option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2109
2646
|
if (opts.schema) return printToolSchema(cmd2, knId, "query_instance_subgraph");
|
|
2110
2647
|
printJson(
|
|
2111
|
-
await clientFrom(cmd2).context.queryInstanceSubgraph(knId, jsonArgs(opts
|
|
2648
|
+
await clientFrom(cmd2).context.queryInstanceSubgraph(knId, jsonArgs(opts)),
|
|
2112
2649
|
outputOptions(cmd2)
|
|
2113
2650
|
);
|
|
2114
2651
|
});
|
|
2115
2652
|
cmd.command("get-logic-properties <kn-id>").description("Compute logic-property values for instances").option(
|
|
2116
2653
|
"--args <json>",
|
|
2117
|
-
"tool arguments as JSON; kn_id is filled from <kn-id
|
|
2118
|
-
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2654
|
+
"tool arguments as JSON (- for stdin); kn_id is filled from <kn-id> unless given; --schema prints the shape"
|
|
2655
|
+
).option("--args-file <path>", "read tool arguments as JSON from a file (or - for stdin)").option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2119
2656
|
if (opts.schema) return printToolSchema(cmd2, knId, "get_logic_properties_values");
|
|
2120
2657
|
printJson(
|
|
2121
|
-
await clientFrom(cmd2).context.logicProperties(knId, jsonArgs(opts
|
|
2658
|
+
await clientFrom(cmd2).context.logicProperties(knId, jsonArgs(opts)),
|
|
2122
2659
|
outputOptions(cmd2)
|
|
2123
2660
|
);
|
|
2124
2661
|
});
|
|
2125
2662
|
cmd.command("get-action-info <kn-id>").description("Fetch action info / dynamic tools for an instance").option(
|
|
2126
2663
|
"--args <json>",
|
|
2127
|
-
"tool arguments as JSON; kn_id is filled from <kn-id
|
|
2128
|
-
).option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2664
|
+
"tool arguments as JSON (- for stdin); kn_id is filled from <kn-id> unless given; --schema prints the shape"
|
|
2665
|
+
).option("--args-file <path>", "read tool arguments as JSON from a file (or - for stdin)").option("--schema", "print this tool's argument schema from the deploy instead of calling it").action(async (knId, opts, cmd2) => {
|
|
2129
2666
|
if (opts.schema) return printToolSchema(cmd2, knId, "get_action_info");
|
|
2130
|
-
printJson(
|
|
2131
|
-
await clientFrom(cmd2).context.actionInfo(knId, jsonArgs(opts.args)),
|
|
2132
|
-
outputOptions(cmd2)
|
|
2133
|
-
);
|
|
2667
|
+
printJson(await clientFrom(cmd2).context.actionInfo(knId, jsonArgs(opts)), outputOptions(cmd2));
|
|
2134
2668
|
});
|
|
2135
2669
|
groupChildren(cmd, {
|
|
2136
2670
|
GROUPS: ["conversation"],
|
|
@@ -2146,11 +2680,12 @@ rewriting it with \`run-sql\` produces a number the platform will not agree with
|
|
|
2146
2680
|
"templates",
|
|
2147
2681
|
"prompts",
|
|
2148
2682
|
"prompt",
|
|
2149
|
-
"
|
|
2683
|
+
"search-capabilities"
|
|
2150
2684
|
],
|
|
2151
2685
|
RUN: [
|
|
2152
2686
|
"query-object-instance",
|
|
2153
2687
|
"run-sql",
|
|
2688
|
+
"run-cypher",
|
|
2154
2689
|
"explore-subgraph",
|
|
2155
2690
|
"query-metric",
|
|
2156
2691
|
"query-instance-subgraph",
|
|
@@ -2170,15 +2705,29 @@ rewriting it with \`run-sql\` produces a number the platform will not agree with
|
|
|
2170
2705
|
get-logic-properties / get-action-info computed values, runnable actions
|
|
2171
2706
|
|
|
2172
2707
|
PICKING THE RIGHT QUERY
|
|
2173
|
-
Aggregation, ranking, GROUP BY or joins are not query-object-instance
|
|
2174
|
-
|
|
2175
|
-
|
|
2708
|
+
Aggregation, ranking, GROUP BY or joins are not query-object-instance. When the question
|
|
2709
|
+
can be stated in object types and relation types \u2014 filter along a path, aggregate what
|
|
2710
|
+
it reaches \u2014 use \`run-cypher <kn-id>\`: model names only, no resource ids or physical
|
|
2711
|
+
columns. SQL through \`run-sql <kn-id>\` is for what the Cypher subset cannot say.
|
|
2712
|
+
Unknown topology is \`explore-subgraph <kn-id> <ot-id> --hops <n>\`, not a hand-built path.
|
|
2176
2713
|
|
|
2177
2714
|
THE SAME ID, FOUR NAMES
|
|
2178
2715
|
An object type's id is \`concept_id\` in search-schema output, \`id\` in kn-detail and
|
|
2179
2716
|
get_object_types, \`ot_id\` in query-object-instance arguments, and \`object_type_id\` on
|
|
2180
2717
|
an instance row. Same value throughout \u2014 carry it across, do not look it up again.
|
|
2181
2718
|
|
|
2719
|
+
QUERY ARGUMENTS
|
|
2720
|
+
query-object-instance rejects unknown argument keys before calling the platform. Combine
|
|
2721
|
+
conditions with condition.sub_conditions, not condition.conditions; vector search belongs in
|
|
2722
|
+
condition.operation=knn, not a top-level knn argument. Do not combine condition and filters:
|
|
2723
|
+
the platform ignores filters when condition is present. Page with cursor (the MCP tool's
|
|
2724
|
+
key) or offset, never both; search_after (the REST name) is passed through unchanged for a
|
|
2725
|
+
deploy that advertises it. Any kn_id in --args must match <kn-id>. For properties and condition.field,
|
|
2726
|
+
run object-types <kn-id> <ot-id> first to see the valid field names. Specifying properties
|
|
2727
|
+
also reads the object-type schema once and rejects unknown names before the query. --schema shows the
|
|
2728
|
+
argument shape advertised by this deploy. Every --args option also accepts --args-file <path>,
|
|
2729
|
+
while --args - reads JSON from stdin.
|
|
2730
|
+
|
|
2182
2731
|
RAW MCP
|
|
2183
2732
|
tools <kn-id> lists what this deploy advertises, with each tool's input schema.
|
|
2184
2733
|
tool-call / call-method reach anything the named commands above do not cover.`
|
|
@@ -2217,7 +2766,6 @@ var returns_default = {
|
|
|
2217
2766
|
"bkn list": ["entries", "total_count"],
|
|
2218
2767
|
"bkn get": [
|
|
2219
2768
|
"branch",
|
|
2220
|
-
"business_domain",
|
|
2221
2769
|
"color",
|
|
2222
2770
|
"comment",
|
|
2223
2771
|
"create_time",
|
|
@@ -2239,7 +2787,6 @@ var returns_default = {
|
|
|
2239
2787
|
"bkn action-type get": ["entries"],
|
|
2240
2788
|
"bkn stats": [
|
|
2241
2789
|
"branch",
|
|
2242
|
-
"business_domain",
|
|
2243
2790
|
"color",
|
|
2244
2791
|
"comment",
|
|
2245
2792
|
"create_time",
|
|
@@ -2400,7 +2947,6 @@ var returns_default = {
|
|
|
2400
2947
|
],
|
|
2401
2948
|
"skill list": ["data", "has_next", "has_prev", "page", "page_size", "total", "total_pages"],
|
|
2402
2949
|
"skill get": [
|
|
2403
|
-
"business_domain_id",
|
|
2404
2950
|
"category",
|
|
2405
2951
|
"category_name",
|
|
2406
2952
|
"create_time",
|
|
@@ -2416,7 +2962,6 @@ var returns_default = {
|
|
|
2416
2962
|
],
|
|
2417
2963
|
"skill market": ["data", "has_next", "has_prev", "page", "page_size", "total", "total_pages"],
|
|
2418
2964
|
"skill market-get": [
|
|
2419
|
-
"business_domain_id",
|
|
2420
2965
|
"category",
|
|
2421
2966
|
"category_name",
|
|
2422
2967
|
"create_time",
|
|
@@ -2437,8 +2982,8 @@ var returns_default = {
|
|
|
2437
2982
|
"skill names": ["entries"],
|
|
2438
2983
|
"skill history": "array",
|
|
2439
2984
|
"toolbox list": ["data", "has_next", "has_prev", "page", "page_size", "total", "total_pages"],
|
|
2440
|
-
"
|
|
2441
|
-
"
|
|
2985
|
+
"sandbox deps": ["dependencies", "session_id"],
|
|
2986
|
+
"sandbox template": ["code_template", "template_type"],
|
|
2442
2987
|
"trace graph": [
|
|
2443
2988
|
"data",
|
|
2444
2989
|
"duration_nano",
|
|
@@ -2572,7 +3117,7 @@ var returns_default = {
|
|
|
2572
3117
|
"updated_at"
|
|
2573
3118
|
],
|
|
2574
3119
|
"admin user roles": ["roles"],
|
|
2575
|
-
"admin role list": ["roles"],
|
|
3120
|
+
"admin role list": ["roles", "total"],
|
|
2576
3121
|
"admin role get": [
|
|
2577
3122
|
"built_in",
|
|
2578
3123
|
"created_at",
|
|
@@ -2631,7 +3176,7 @@ var SERVICE_PROBES = [
|
|
|
2631
3176
|
{ service: "vega-backend", path: "/api/vega-backend/v1/catalogs?limit=1" },
|
|
2632
3177
|
{
|
|
2633
3178
|
service: "agent-operator-integration",
|
|
2634
|
-
path: "/api/agent-operator-integration/v1/tool-box/list?page=1&
|
|
3179
|
+
path: "/api/agent-operator-integration/v1/tool-box/list?page=1&page_size=1"
|
|
2635
3180
|
},
|
|
2636
3181
|
{ service: "agent-observability", path: "/api/agent-observability/v1/conversations?limit=1" },
|
|
2637
3182
|
{ service: "mf-model-manager", path: "/api/mf-model-manager/v1/llm/list" },
|
|
@@ -2644,7 +3189,7 @@ var COMMAND_SERVICE = [
|
|
|
2644
3189
|
[/^resource\b/, "vega-backend"],
|
|
2645
3190
|
[/^context\b/, "agent-retrieval"],
|
|
2646
3191
|
[/^trace\b/, "agent-observability"],
|
|
2647
|
-
[/^(skill|toolbox|tool|function)\b/, "agent-operator-integration"],
|
|
3192
|
+
[/^(skill|mcp|sandbox|toolbox|tool|function|api)\b/, "agent-operator-integration"],
|
|
2648
3193
|
[/^model\b/, "mf-model-manager"],
|
|
2649
3194
|
[/^(auth|appkey)\b/, "safe"],
|
|
2650
3195
|
[/^admin (llm|small-model)\b/, "mf-model-manager"],
|
|
@@ -2656,10 +3201,11 @@ var COMMAND_TOOL = {
|
|
|
2656
3201
|
"context query-instance-subgraph": "query_instance_subgraph",
|
|
2657
3202
|
"context explore-subgraph": "explore_subgraph",
|
|
2658
3203
|
"context run-sql": "run_sql",
|
|
3204
|
+
"context run-cypher": "run_cypher",
|
|
2659
3205
|
"context query-metric": "query_metric",
|
|
2660
3206
|
"context get-logic-properties": "get_logic_properties_values",
|
|
2661
3207
|
"context get-action-info": "get_action_info",
|
|
2662
|
-
"context
|
|
3208
|
+
"context search-capabilities": "search_capabilities",
|
|
2663
3209
|
"context kn-detail": "get_kn_detail",
|
|
2664
3210
|
"context object-types": "get_object_types",
|
|
2665
3211
|
"context relation-types": "get_relation_types"
|
|
@@ -2714,6 +3260,7 @@ var ID_SOURCES = {
|
|
|
2714
3260
|
"at-id": "openbkn bkn action-type list <kn-id>",
|
|
2715
3261
|
"metric-id": "openbkn bkn metric list <kn-id>",
|
|
2716
3262
|
"skill-id": "openbkn skill list",
|
|
3263
|
+
"mcp-id": "openbkn mcp list",
|
|
2717
3264
|
"box-id": "openbkn toolbox list",
|
|
2718
3265
|
"tool-id": "openbkn tool list --toolbox <box-id>",
|
|
2719
3266
|
"conversation-id": "openbkn trace conversations list",
|
|
@@ -2727,8 +3274,7 @@ var ID_SOURCES = {
|
|
|
2727
3274
|
"conversation-ids": "openbkn trace conversations list",
|
|
2728
3275
|
"model-ids": "openbkn model llm list",
|
|
2729
3276
|
"tool-ids": "openbkn tool list --toolbox <box-id>",
|
|
2730
|
-
"document-
|
|
2731
|
-
"document-ids": "openbkn vega resource document-get <resource-id> <document-id>",
|
|
3277
|
+
"document-ids": "openbkn vega resource document-get <resource-id> <document-ids...>",
|
|
2732
3278
|
// Named entities, wherever they appear; the overrides below cover the cases
|
|
2733
3279
|
// where the same word means something else.
|
|
2734
3280
|
role: "openbkn admin role list",
|
|
@@ -2750,12 +3296,15 @@ var GROUP_ID_SOURCES = [
|
|
|
2750
3296
|
[/^vega discover-schedule\b/, "openbkn vega discover-schedule list"],
|
|
2751
3297
|
[/^vega discover-task\b/, "openbkn vega discover-task list"],
|
|
2752
3298
|
[/^vega semantic-task\b/, "openbkn vega semantic-task list"],
|
|
2753
|
-
[/^vega
|
|
3299
|
+
[/^vega build-task\b/, "openbkn vega build-task list"],
|
|
2754
3300
|
[/^bkn action-schedule\b/, "openbkn bkn action-schedule list <kn-id>"],
|
|
2755
3301
|
[/^vega connector-type\b/, "openbkn vega connector-type list"],
|
|
2756
3302
|
[/^resource\b/, "openbkn resource list"],
|
|
2757
3303
|
[/^skill\b/, "openbkn skill list"],
|
|
3304
|
+
[/^mcp\b/, "openbkn mcp list"],
|
|
2758
3305
|
[/^toolbox\b/, "openbkn toolbox list"],
|
|
3306
|
+
[/^function\b/, "openbkn function list --toolbox <box-id>"],
|
|
3307
|
+
[/^api\b/, "openbkn api list --toolbox <box-id>"],
|
|
2759
3308
|
[/^tool\b/, "openbkn tool list --toolbox <box-id>"],
|
|
2760
3309
|
[/^appkey\b/, "openbkn appkey list"],
|
|
2761
3310
|
[/^admin org\b/, "openbkn admin org list"],
|
|
@@ -2764,6 +3313,7 @@ var GROUP_ID_SOURCES = [
|
|
|
2764
3313
|
[/^admin role\b/, "openbkn admin role list"],
|
|
2765
3314
|
[/^admin llm\b/, "openbkn admin llm list"],
|
|
2766
3315
|
[/^admin small-model\b/, "openbkn admin small-model list"],
|
|
3316
|
+
[/^admin audit\b/, "openbkn admin audit list"],
|
|
2767
3317
|
[/^model llm\b/, "openbkn model llm list"],
|
|
2768
3318
|
[/^model small\b/, "openbkn model small list"],
|
|
2769
3319
|
[/^bkn object-type\b/, "openbkn bkn object-type list <kn-id>"],
|
|
@@ -2776,13 +3326,15 @@ var GROUP_ID_SOURCES = [
|
|
|
2776
3326
|
function sourceOf(argName, path, isLast) {
|
|
2777
3327
|
const override = ARGUMENT_OVERRIDES[`${path.join(" ")}|${argName}`];
|
|
2778
3328
|
if (override !== void 0) return override ?? void 0;
|
|
3329
|
+
const parent = path.slice(0, -1).join(" ");
|
|
3330
|
+
const groupSource = GROUP_ID_SOURCES.find(([re]) => re.test(parent))?.[1];
|
|
3331
|
+
if (/^tool-ids?$/i.test(argName) && groupSource) return groupSource;
|
|
2779
3332
|
const byName = ID_SOURCES[argName];
|
|
2780
3333
|
if (byName) return byName;
|
|
2781
3334
|
if (!isLast) return void 0;
|
|
2782
3335
|
const generic = /^(id|ids|cg-id|modelid|role|user|schedule-id|schedule-ids|task-id|log-id)$/i.test(argName);
|
|
2783
3336
|
if (!generic) return void 0;
|
|
2784
|
-
|
|
2785
|
-
return GROUP_ID_SOURCES.find(([re]) => re.test(parent))?.[1];
|
|
3337
|
+
return groupSource;
|
|
2786
3338
|
}
|
|
2787
3339
|
function describeOption(opt) {
|
|
2788
3340
|
return {
|
|
@@ -2813,7 +3365,7 @@ function describeNode(cmd, parentPath, depth) {
|
|
|
2813
3365
|
};
|
|
2814
3366
|
if (depth <= 0) return children.length ? { ...skeleton, hasCommands: true } : skeleton;
|
|
2815
3367
|
const aliases = cmd.aliases();
|
|
2816
|
-
const options = cmd.options.filter((o) => o.long !== "--help");
|
|
3368
|
+
const options = cmd.options.filter((o) => o.long !== "--help" && !o.hidden);
|
|
2817
3369
|
return {
|
|
2818
3370
|
...skeleton,
|
|
2819
3371
|
...aliases.length ? { aliases } : {},
|
|
@@ -2849,8 +3401,8 @@ var FIELD_MEANINGS = {
|
|
|
2849
3401
|
guide: "prose the command's own --help prints under its command list",
|
|
2850
3402
|
commands: "nested commands"
|
|
2851
3403
|
};
|
|
2852
|
-
function
|
|
2853
|
-
let node =
|
|
3404
|
+
function resolve(program, path) {
|
|
3405
|
+
let node = program;
|
|
2854
3406
|
for (const name of path) {
|
|
2855
3407
|
const child = node.commands.find((c) => c.name() === name || c.aliases().includes(name));
|
|
2856
3408
|
if (!child) throw new InputError(`no such command: ${path.join(" ")}`);
|
|
@@ -2858,29 +3410,29 @@ function resolve2(program2, path) {
|
|
|
2858
3410
|
}
|
|
2859
3411
|
return node;
|
|
2860
3412
|
}
|
|
2861
|
-
function describeCommandTree(
|
|
3413
|
+
function describeCommandTree(program, opts = {}) {
|
|
2862
3414
|
activeProbe = opts.probe;
|
|
2863
3415
|
const depth = opts.depth === void 0 ? Number.MAX_SAFE_INTEGER : opts.depth - 1;
|
|
2864
3416
|
if (opts.path?.length) {
|
|
2865
3417
|
return {
|
|
2866
3418
|
sections: SECTION_MEANINGS,
|
|
2867
3419
|
fields: FIELD_MEANINGS,
|
|
2868
|
-
...describeNode(
|
|
3420
|
+
...describeNode(resolve(program, opts.path), opts.path.slice(0, -1), depth + 1)
|
|
2869
3421
|
};
|
|
2870
3422
|
}
|
|
2871
|
-
const top =
|
|
3423
|
+
const top = program.commands.filter(
|
|
2872
3424
|
(c) => !c.name().startsWith("help") && c.name() !== "describe"
|
|
2873
3425
|
);
|
|
2874
3426
|
return {
|
|
2875
|
-
name:
|
|
2876
|
-
version:
|
|
2877
|
-
summary:
|
|
3427
|
+
name: program.name(),
|
|
3428
|
+
version: program.version(),
|
|
3429
|
+
summary: program.description(),
|
|
2878
3430
|
sections: SECTION_MEANINGS,
|
|
2879
3431
|
fields: FIELD_MEANINGS,
|
|
2880
3432
|
...opts.probe ? { probe: opts.probe } : {},
|
|
2881
3433
|
commands: top.map((cmd) => describeNode(cmd, [], depth)),
|
|
2882
|
-
globalOptions:
|
|
2883
|
-
guide: guideOf(
|
|
3434
|
+
globalOptions: program.options.filter((o) => o.long !== "--help").map(describeOption),
|
|
3435
|
+
guide: guideOf(program)
|
|
2884
3436
|
};
|
|
2885
3437
|
}
|
|
2886
3438
|
function rows(node, indent = "") {
|
|
@@ -2922,14 +3474,14 @@ function renderText(tree) {
|
|
|
2922
3474
|
}
|
|
2923
3475
|
return out.join("\n");
|
|
2924
3476
|
}
|
|
2925
|
-
function describeCommand(
|
|
3477
|
+
function describeCommand(program) {
|
|
2926
3478
|
const cmd = new Command8("describe").description("Print the command tree \u2014 paths, sections, flags (--json for the data)").argument("[command...]", "only this subtree, e.g. `describe bkn metric`").option(
|
|
2927
3479
|
"--depth <n>",
|
|
2928
3480
|
"how many levels to walk (1 = this level only)",
|
|
2929
3481
|
(v) => Number.parseInt(v, 10)
|
|
2930
3482
|
).option("--pretty", "indent the JSON instead of packing it onto one line").option("--probe", "ask this deploy which commands it can answer (read-only, ~7 requests)").action(async (path, opts, self) => {
|
|
2931
3483
|
const probe = opts.probe ? await probeDeploy(self, (/* @__PURE__ */ new Date()).toISOString()) : void 0;
|
|
2932
|
-
const tree = describeCommandTree(
|
|
3484
|
+
const tree = describeCommandTree(program, { path, depth: opts.depth, probe });
|
|
2933
3485
|
const out = outputOptions(self);
|
|
2934
3486
|
if (!out.json && !out.compact && !opts.pretty) {
|
|
2935
3487
|
process.stdout.write(`${renderText(tree)}
|
|
@@ -2942,12 +3494,11 @@ function describeCommand(program2) {
|
|
|
2942
3494
|
}
|
|
2943
3495
|
|
|
2944
3496
|
// src/commands/function.ts
|
|
2945
|
-
import { readFileSync as
|
|
3497
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
2946
3498
|
import { Command as Command9 } from "commander";
|
|
2947
|
-
var int5 = (v) => Number.parseInt(v, 10);
|
|
2948
3499
|
function readCode(file) {
|
|
2949
3500
|
try {
|
|
2950
|
-
return
|
|
3501
|
+
return readFileSync3(file === "-" ? 0 : file, "utf8");
|
|
2951
3502
|
} catch (err) {
|
|
2952
3503
|
throw new InputError(
|
|
2953
3504
|
`Cannot read ${file === "-" ? "stdin" : file}: ${err instanceof Error ? err.message : err}`
|
|
@@ -2969,8 +3520,21 @@ function parseJsonOption(raw, label) {
|
|
|
2969
3520
|
throw new InputError(`--${label} must be valid JSON`);
|
|
2970
3521
|
}
|
|
2971
3522
|
}
|
|
2972
|
-
function
|
|
2973
|
-
|
|
3523
|
+
function parseJsonObjectOption(raw, label) {
|
|
3524
|
+
const parsed = parseJsonOption(raw, label);
|
|
3525
|
+
if (parsed === void 0) return void 0;
|
|
3526
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
3527
|
+
throw new InputError(`--${label} must be a JSON object`);
|
|
3528
|
+
}
|
|
3529
|
+
return parsed;
|
|
3530
|
+
}
|
|
3531
|
+
function definitionFlags(c, includeType = true, flagSet = "all") {
|
|
3532
|
+
if (flagSet === "openapi-import") return c;
|
|
3533
|
+
if (flagSet === "openapi-update") {
|
|
3534
|
+
return c.option("--name <n>", "tool name; required, update replaces the tool").option("--description <d>", "what it does; required, update replaces the tool");
|
|
3535
|
+
}
|
|
3536
|
+
const flags = c.option("--name <n>", "name; required when the definition is a function").option("--description <d>", "what it does \u2014 the model reads this to decide when to call it").option("--inputs <json>", "input parameters: [{name,type,required,description}]").option("--outputs <json>", "output parameters, same shape as --inputs").option("--dep <name@version>", "package to install before running (repeatable)", collectDep).option("--index-url <url>", "package index to install from");
|
|
3537
|
+
return includeType ? flags.option("--type <t>", "function | openapi", "function") : flags;
|
|
2974
3538
|
}
|
|
2975
3539
|
function parameterList(raw, label) {
|
|
2976
3540
|
const parsed = parseJsonOption(raw, label);
|
|
@@ -2990,18 +3554,41 @@ function functionDefinitionFrom(file, opts) {
|
|
|
2990
3554
|
dependenciesUrl: opts.indexUrl
|
|
2991
3555
|
};
|
|
2992
3556
|
}
|
|
2993
|
-
function
|
|
2994
|
-
|
|
3557
|
+
function generationType(value) {
|
|
3558
|
+
return oneOf("type", FunctionAiGenerationType)(value);
|
|
3559
|
+
}
|
|
3560
|
+
function generationRequestFrom(type, opts) {
|
|
3561
|
+
const inputs = parameterList(opts.inputs, "inputs");
|
|
3562
|
+
const outputs = parameterList(opts.outputs, "outputs");
|
|
3563
|
+
if (type === "python_function_generator") {
|
|
3564
|
+
if (!opts.query?.trim()) {
|
|
3565
|
+
throw new InputError("--query is required for python_function_generator");
|
|
3566
|
+
}
|
|
3567
|
+
if (opts.code !== void 0) {
|
|
3568
|
+
throw new InputError("--code only applies to metadata_param_generator");
|
|
3569
|
+
}
|
|
3570
|
+
return { query: opts.query, inputs, outputs };
|
|
3571
|
+
}
|
|
3572
|
+
if (opts.query !== void 0) {
|
|
3573
|
+
throw new InputError("--query only applies to python_function_generator");
|
|
3574
|
+
}
|
|
3575
|
+
if (!opts.code) {
|
|
3576
|
+
throw new InputError("--code <file> is required for metadata_param_generator");
|
|
3577
|
+
}
|
|
3578
|
+
return { code: readCode(opts.code), inputs, outputs };
|
|
3579
|
+
}
|
|
3580
|
+
function sandboxCommand() {
|
|
3581
|
+
const cmd = new Command9("sandbox").description(
|
|
2995
3582
|
"Sandbox functions: run Python on the platform without registering anything"
|
|
2996
3583
|
);
|
|
2997
|
-
cmd.command("run <file>").description("Run a file (or `-` for stdin) in the sandbox; exits non-zero when the code does").option("--event <json>", "the single argument handler() receives", "{}").option("--timeout <s>", "sandbox timeout in seconds",
|
|
3584
|
+
cmd.command("run <file>").description("Run a file (or `-` for stdin) in the sandbox; exits non-zero when the code does").option("--event <json>", "the single argument handler() receives", "{}").option("--timeout <s>", "sandbox timeout in seconds", positiveInt("--timeout")).option("--dep <name@version>", "install a package first (repeatable)", collectDep).option("--index-url <url>", "package index to install from (default PyPI)").option(
|
|
2998
3585
|
"--pass-token",
|
|
2999
3586
|
"put your credential in the sandbox's BKN_TOKEN so `sandbox_sdk.bkn` calls BKN as you"
|
|
3000
3587
|
).action(async (file, opts, cmd2) => {
|
|
3001
3588
|
const client = clientFrom(cmd2);
|
|
3002
3589
|
const result = await client.functions.run({
|
|
3003
3590
|
code: readCode(file),
|
|
3004
|
-
event:
|
|
3591
|
+
event: parseJsonObjectOption(opts.event, "event") ?? {},
|
|
3005
3592
|
timeout: opts.timeout,
|
|
3006
3593
|
dependencies: opts.dep,
|
|
3007
3594
|
dependenciesUrl: opts.indexUrl,
|
|
@@ -3032,12 +3619,38 @@ function functionCommand() {
|
|
|
3032
3619
|
outputOptions(cmd2)
|
|
3033
3620
|
);
|
|
3034
3621
|
});
|
|
3035
|
-
cmd.command("template").description("The handler() skeleton to start from").option(
|
|
3622
|
+
cmd.command("template").description("The handler() skeleton to start from").option(
|
|
3623
|
+
"--type <t>",
|
|
3624
|
+
"template type (python)",
|
|
3625
|
+
oneOf("--type", FUNCTION_TEMPLATE_TYPES),
|
|
3626
|
+
"python"
|
|
3627
|
+
).action(async (opts, cmd2) => {
|
|
3036
3628
|
printJson(await clientFrom(cmd2).functions.template(opts.type), outputOptions(cmd2));
|
|
3037
3629
|
});
|
|
3630
|
+
cmd.command("generate <type>").description("Generate function code or parameter metadata with the platform's default LLM").option("--query <text>", "natural-language request (python_function_generator)").option("--code <file>", "existing code to analyse (metadata_param_generator; `-` reads stdin)").option("--inputs <json>", "known input parameters to constrain generation").option("--outputs <json>", "known output parameters to constrain generation").option(
|
|
3631
|
+
"--timeout <s>",
|
|
3632
|
+
"seconds to wait for the model (default 300; a default ingress answers 504 at 60)",
|
|
3633
|
+
positiveInt("--timeout")
|
|
3634
|
+
).action(async (type, opts, cmd2) => {
|
|
3635
|
+
const direction = generationType(type);
|
|
3636
|
+
printJson(
|
|
3637
|
+
await clientFrom(cmd2).functions.generate(
|
|
3638
|
+
direction,
|
|
3639
|
+
generationRequestFrom(direction, opts),
|
|
3640
|
+
opts.timeout === void 0 ? {} : { timeoutMs: opts.timeout * 1e3 }
|
|
3641
|
+
),
|
|
3642
|
+
outputOptions(cmd2)
|
|
3643
|
+
);
|
|
3644
|
+
});
|
|
3645
|
+
cmd.command("prompt <type>").description("Read the prompt template used for one Function AI generation direction").action(async (type, _opts, cmd2) => {
|
|
3646
|
+
printJson(
|
|
3647
|
+
await clientFrom(cmd2).functions.promptTemplate(generationType(type)),
|
|
3648
|
+
outputOptions(cmd2)
|
|
3649
|
+
);
|
|
3650
|
+
});
|
|
3038
3651
|
groupChildren(cmd, {
|
|
3039
|
-
READ: ["deps", "versions", "template"],
|
|
3040
|
-
RUN: ["run", "infer-schema"]
|
|
3652
|
+
READ: ["deps", "versions", "template", "prompt"],
|
|
3653
|
+
RUN: ["run", "infer-schema", "generate"]
|
|
3041
3654
|
});
|
|
3042
3655
|
guide(
|
|
3043
3656
|
cmd,
|
|
@@ -3048,7 +3661,7 @@ function functionCommand() {
|
|
|
3048
3661
|
return {"sum": event.get("a", 0) + event.get("b", 0)}
|
|
3049
3662
|
|
|
3050
3663
|
\`--event\` is that argument, the return value comes back as \`result\`, and
|
|
3051
|
-
\`print\` output as \`stdout\`. \`
|
|
3664
|
+
\`print\` output as \`stdout\`. \`sandbox template\` prints the skeleton.
|
|
3052
3665
|
|
|
3053
3666
|
READING THE ANSWER
|
|
3054
3667
|
Code that raises still answers HTTP 200 \u2014 \`exit_code\` is the verdict and the
|
|
@@ -3061,24 +3674,168 @@ function functionCommand() {
|
|
|
3061
3674
|
--pass-token puts it in BKN_TOKEN so that code runs as you.
|
|
3062
3675
|
|
|
3063
3676
|
ORDER OF WORK
|
|
3064
|
-
|
|
3065
|
-
|
|
3677
|
+
sandbox deps what is already importable
|
|
3678
|
+
sandbox run ./add.py --event ... iterate here; nothing is kept
|
|
3679
|
+
sandbox generate python_function_generator --query "..."
|
|
3680
|
+
draft a handler with the platform model
|
|
3066
3681
|
toolbox create --type function a box to keep it in
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3682
|
+
function create ./add.py --toolbox the same code, now a registered Function Tool
|
|
3683
|
+
function debug <tool-id> --toolbox try it before enabling or publishing
|
|
3684
|
+
function enable <tool-id> --toolbox
|
|
3685
|
+
a tool is off until enabled
|
|
3686
|
+
toolbox publish <box-id> execute needs a published box
|
|
3687
|
+
function execute <tool-id> --toolbox
|
|
3688
|
+
the call agents make
|
|
3689
|
+
|
|
3690
|
+
LONG JOBS
|
|
3691
|
+
A registered function called through the toolbox is cut at about 30s whatever
|
|
3692
|
+
its --timeout, and answers 200 with result: null. Keep long work on
|
|
3693
|
+
\`sandbox run\`, which waits for the sandbox's own limit. The ingress still
|
|
3694
|
+
answers 504 when its read timeout passes: 60s by default, unless the deploy
|
|
3695
|
+
raises proxy-read-timeout.`
|
|
3696
|
+
);
|
|
3697
|
+
return group(cmd, "TOOLS & SKILLS");
|
|
3698
|
+
}
|
|
3699
|
+
|
|
3700
|
+
// src/commands/mcp.ts
|
|
3701
|
+
import { Command as Command10, Option as Option3 } from "commander";
|
|
3702
|
+
var REDACTED = "<redacted>";
|
|
3703
|
+
var SECRET_NAME = /(^|[-_.])(authorization|auth|cookie|token|api[-_]?key|apikey|secret|pass|password|passwd|pwd|credentials?|private[-_]?key|access[-_]?key([-_]?id)?|secret[-_]?key|ak|sk)$/i;
|
|
3704
|
+
var SCHEMA_KEYS = /* @__PURE__ */ new Set(["inputSchema", "input_schema", "outputSchema", "output_schema"]);
|
|
3705
|
+
function redactUrl(value) {
|
|
3706
|
+
let url;
|
|
3707
|
+
try {
|
|
3708
|
+
url = new URL(value);
|
|
3709
|
+
} catch {
|
|
3710
|
+
return value;
|
|
3711
|
+
}
|
|
3712
|
+
let changed = false;
|
|
3713
|
+
if (url.password) {
|
|
3714
|
+
url.password = REDACTED;
|
|
3715
|
+
changed = true;
|
|
3716
|
+
}
|
|
3717
|
+
for (const name of [...url.searchParams.keys()]) {
|
|
3718
|
+
if (SECRET_NAME.test(name)) {
|
|
3719
|
+
url.searchParams.set(name, REDACTED);
|
|
3720
|
+
changed = true;
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
return changed ? url.toString() : value;
|
|
3724
|
+
}
|
|
3725
|
+
function redactArgs(args) {
|
|
3726
|
+
return args.map((arg, i) => {
|
|
3727
|
+
if (typeof arg !== "string") return arg;
|
|
3728
|
+
const assigned = /^(-{0,2})([^=\s]+)=(.*)$/.exec(arg);
|
|
3729
|
+
if (assigned?.[2] && SECRET_NAME.test(assigned[2])) {
|
|
3730
|
+
return `${assigned[1]}${assigned[2]}=${REDACTED}`;
|
|
3731
|
+
}
|
|
3732
|
+
const previous = args[i - 1];
|
|
3733
|
+
if (typeof previous === "string" && /^--?[^=\s]+$/.test(previous)) {
|
|
3734
|
+
if (SECRET_NAME.test(previous.replace(/^-+/, ""))) return REDACTED;
|
|
3735
|
+
}
|
|
3736
|
+
return arg;
|
|
3737
|
+
});
|
|
3738
|
+
}
|
|
3739
|
+
function maskValues(value) {
|
|
3740
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
3741
|
+
return Object.fromEntries(Object.keys(value).map((key) => [key, REDACTED]));
|
|
3742
|
+
}
|
|
3743
|
+
function redactMcpOutput(value) {
|
|
3744
|
+
if (Array.isArray(value)) return value.map(redactMcpOutput);
|
|
3745
|
+
if (!value || typeof value !== "object") return value;
|
|
3746
|
+
return Object.fromEntries(
|
|
3747
|
+
Object.entries(value).map(([key, item]) => {
|
|
3748
|
+
if (SCHEMA_KEYS.has(key)) return [key, item];
|
|
3749
|
+
if (key === "headers" || key === "env") return [key, maskValues(item)];
|
|
3750
|
+
if (key === "args" && Array.isArray(item)) return [key, redactArgs(item)];
|
|
3751
|
+
if (typeof item === "string" && /url$/i.test(key)) return [key, redactUrl(item)];
|
|
3752
|
+
if (item !== null && typeof item !== "object" && SECRET_NAME.test(key)) {
|
|
3753
|
+
return [key, REDACTED];
|
|
3754
|
+
}
|
|
3755
|
+
return [key, redactMcpOutput(item)];
|
|
3756
|
+
})
|
|
3757
|
+
);
|
|
3758
|
+
}
|
|
3759
|
+
function mcpCommand() {
|
|
3760
|
+
const cmd = new Command10("mcp").description(
|
|
3761
|
+
"Registered MCP Servers: inspect their configuration and discover their tools"
|
|
3762
|
+
);
|
|
3763
|
+
cmd.command("list").description("List MCP Servers you can access").option("--name <text>", "filter by name").option("--source <text>", "filter by source").option("--category <text>", "filter by category").option("--status <status>", "filter by status (unpublish|published|offline|editing)").option("--create-user <text>", "filter by creator").option("--internal", "show only internal servers").addOption(
|
|
3764
|
+
new Option3("--mode <mode>", "filter by connection mode").choices([
|
|
3765
|
+
"sse",
|
|
3766
|
+
"stream",
|
|
3767
|
+
"stdio_uv",
|
|
3768
|
+
"stdio_npx"
|
|
3769
|
+
])
|
|
3770
|
+
).addOption(
|
|
3771
|
+
new Option3("--sort-by <field>", "sort field").choices(["update_time", "create_time", "name"])
|
|
3772
|
+
).addOption(new Option3("--sort-order <order>", "sort direction").choices(["asc", "desc"])).option(
|
|
3773
|
+
"--limit <n>",
|
|
3774
|
+
"page size (1-100)",
|
|
3775
|
+
positiveInt("--limit", MAX_PAGE_SIZE),
|
|
3776
|
+
DEFAULT_LIST_LIMIT
|
|
3777
|
+
).option("--page <n>", "page (1-based)", positiveInt("--page"), 1).option("--all", "return every accessible server (ignores --limit/--page defaults)").action(async (opts, command) => {
|
|
3778
|
+
const paging = (flag) => opts.all && command.getOptionValueSource(flag) === "default" ? void 0 : opts[flag];
|
|
3779
|
+
printJson(
|
|
3780
|
+
redactMcpOutput(
|
|
3781
|
+
await clientFrom(command).mcp.list({
|
|
3782
|
+
page: paging("page"),
|
|
3783
|
+
pageSize: paging("limit"),
|
|
3784
|
+
sortBy: opts.sortBy,
|
|
3785
|
+
sortOrder: opts.sortOrder,
|
|
3786
|
+
name: opts.name,
|
|
3787
|
+
source: opts.source,
|
|
3788
|
+
category: opts.category,
|
|
3789
|
+
status: opts.status,
|
|
3790
|
+
createUser: opts.createUser,
|
|
3791
|
+
isInternal: opts.internal || void 0,
|
|
3792
|
+
mode: opts.mode,
|
|
3793
|
+
all: opts.all || void 0
|
|
3794
|
+
})
|
|
3795
|
+
),
|
|
3796
|
+
outputOptions(command)
|
|
3797
|
+
);
|
|
3798
|
+
});
|
|
3799
|
+
cmd.command("get <mcp-id>").description("Read one MCP Server's configuration and platform connection addresses").action(async (mcpId, _opts, command) => {
|
|
3800
|
+
printJson(redactMcpOutput(await clientFrom(command).mcp.get(mcpId)), outputOptions(command));
|
|
3801
|
+
});
|
|
3802
|
+
cmd.command("tools <mcp-id>").description("List the MCP protocol tools a registered server advertises; does not invoke one").option("--draft", "list the tools of the draft configuration (needs view permission)").action(async (mcpId, opts, command) => {
|
|
3803
|
+
printJson(
|
|
3804
|
+
redactMcpOutput(
|
|
3805
|
+
await clientFrom(command).mcp.tools(mcpId, { draft: opts.draft || void 0 })
|
|
3806
|
+
),
|
|
3807
|
+
outputOptions(command)
|
|
3808
|
+
);
|
|
3809
|
+
});
|
|
3810
|
+
groupChildren(cmd, { READ: ["list", "get", "tools"] });
|
|
3811
|
+
guide(
|
|
3812
|
+
cmd,
|
|
3813
|
+
`WHAT THIS READS
|
|
3814
|
+
These are registered MCP Servers in the execution factory, not Context Loader's
|
|
3815
|
+
agent-facing MCP retrieval interface. \`mcp get\` includes the platform connection
|
|
3816
|
+
addresses; \`mcp tools\` only discovers the remote tool schemas and does not call one.
|
|
3817
|
+
|
|
3818
|
+
ORDER OF WORK
|
|
3819
|
+
mcp list choose an accessible server
|
|
3820
|
+
mcp get <mcp-id> inspect its configuration and connection addresses
|
|
3821
|
+
mcp tools <mcp-id> inspect tool names and input schemas
|
|
3822
|
+
|
|
3823
|
+
CREDENTIALS
|
|
3824
|
+
Output masks header and env values, secrets in launch args and URLs, and
|
|
3825
|
+
credential-named fields. Tool input schemas are printed as advertised.`
|
|
3070
3826
|
);
|
|
3071
3827
|
return group(cmd, "TOOLS & SKILLS");
|
|
3072
3828
|
}
|
|
3073
3829
|
|
|
3074
3830
|
// src/commands/model.ts
|
|
3075
|
-
import { Command as
|
|
3076
|
-
var
|
|
3831
|
+
import { Command as Command11 } from "commander";
|
|
3832
|
+
var int5 = (v) => Number.parseInt(v, 10);
|
|
3077
3833
|
async function resolveLlmModelName(client, model) {
|
|
3078
3834
|
if (!/^\d+$/.test(model)) return model;
|
|
3079
3835
|
const detail = await client.models.llm.get(model);
|
|
3080
|
-
|
|
3081
|
-
|
|
3836
|
+
const name = detail?.model_name ?? detail?.data?.model_name;
|
|
3837
|
+
if (!name) throw new InputError(`No LLM found with id ${model}.`);
|
|
3838
|
+
return name;
|
|
3082
3839
|
}
|
|
3083
3840
|
function addManagementCommands(parent, kind) {
|
|
3084
3841
|
parent.command("add").description("Register a model (definition JSON via --body / --body-file)").option(
|
|
@@ -3093,6 +3850,14 @@ function addManagementCommands(parent, kind) {
|
|
|
3093
3850
|
).option("--body-file <path>", "read model definition JSON from a file").action(async (opts, cmd) => {
|
|
3094
3851
|
printJson(await clientFrom(cmd).models[kind].edit(readBody(opts)), outputOptions(cmd));
|
|
3095
3852
|
});
|
|
3853
|
+
if (kind === "llm") {
|
|
3854
|
+
parent.commands.find((c) => c.name() === "edit")?.addHelpText(
|
|
3855
|
+
"after",
|
|
3856
|
+
`
|
|
3857
|
+
Send the full definition, including "quota" (true | false): some platform
|
|
3858
|
+
versions answer an edit without it with HTTP 500 ModelFactory.Mydb.DataBase.ParameterError.`
|
|
3859
|
+
);
|
|
3860
|
+
}
|
|
3096
3861
|
parent.command("delete <model-ids>").description("Delete model(s) (comma-joined ids)").action(async (ids, _o, cmd) => {
|
|
3097
3862
|
printJson(await clientFrom(cmd).models[kind].delete(csv(ids) ?? []), outputOptions(cmd));
|
|
3098
3863
|
});
|
|
@@ -3104,11 +3869,11 @@ function addManagementCommands(parent, kind) {
|
|
|
3104
3869
|
});
|
|
3105
3870
|
}
|
|
3106
3871
|
function modelCommand() {
|
|
3107
|
-
const model = new
|
|
3872
|
+
const model = new Command11("model").description(
|
|
3108
3873
|
"Large and small models: chat, embeddings, rerank, defaults"
|
|
3109
3874
|
);
|
|
3110
3875
|
const llm = model.command("llm").description("Large language models");
|
|
3111
|
-
llm.command("list").description("List LLM models \u2192 {data, count}").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size",
|
|
3876
|
+
llm.command("list").description("List LLM models \u2192 {data, count}").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size", int5, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int5, 1).action(async (opts, cmd) => {
|
|
3112
3877
|
printJson(
|
|
3113
3878
|
await clientFrom(cmd).models.llm.list({
|
|
3114
3879
|
name: opts.name,
|
|
@@ -3141,7 +3906,7 @@ function modelCommand() {
|
|
|
3141
3906
|
});
|
|
3142
3907
|
addManagementCommands(llm, "llm");
|
|
3143
3908
|
const small = model.command("small").description("Small models (embedding / reranker)");
|
|
3144
|
-
small.command("list").description("List small models \u2192 {data, count}").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size",
|
|
3909
|
+
small.command("list").description("List small models \u2192 {data, count}").option("--name <s>", "filter by name").option("--type <t>", "model type filter").option("--limit <n>", "page size", int5, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int5, 1).action(async (opts, cmd) => {
|
|
3145
3910
|
printJson(
|
|
3146
3911
|
await clientFrom(cmd).models.small.list({
|
|
3147
3912
|
name: opts.name,
|
|
@@ -3203,24 +3968,152 @@ Examples:
|
|
|
3203
3968
|
}
|
|
3204
3969
|
|
|
3205
3970
|
// src/commands/resource.ts
|
|
3206
|
-
import { Command as
|
|
3207
|
-
var
|
|
3971
|
+
import { Command as Command12 } from "commander";
|
|
3972
|
+
var int6 = (flag) => (v) => {
|
|
3973
|
+
if (!/^-?\d+$/.test(v)) throw new InputError(`${flag} must be an integer (got '${v}')`);
|
|
3974
|
+
const n = Number(v);
|
|
3975
|
+
if (!Number.isSafeInteger(n)) throw new InputError(`${flag} must be an integer (got '${v}')`);
|
|
3976
|
+
return n;
|
|
3977
|
+
};
|
|
3978
|
+
var nonNegativeInt2 = (flag) => (v) => {
|
|
3979
|
+
const n = int6(flag)(v);
|
|
3980
|
+
if (n < 0) throw new InputError(`${flag} must be 0 or greater (got '${v}')`);
|
|
3981
|
+
return n;
|
|
3982
|
+
};
|
|
3983
|
+
var keepAliveSec = (v) => {
|
|
3984
|
+
const n = int6("--keep-alive-sec")(v);
|
|
3985
|
+
if (n < 60 || n > 3600) {
|
|
3986
|
+
throw new InputError(`--keep-alive-sec must be an integer from 60 to 3600 (got '${v}')`);
|
|
3987
|
+
}
|
|
3988
|
+
return n;
|
|
3989
|
+
};
|
|
3990
|
+
var SORT_FIELDS = ["name", "create_time", "update_time"];
|
|
3991
|
+
var DIRECTIONS2 = ["asc", "desc"];
|
|
3992
|
+
function addResourceListOptions(cmd, categoryFlag) {
|
|
3993
|
+
const alias = categoryFlag === "--category" ? "--type" : "--category";
|
|
3994
|
+
return cmd.option("--catalog-id <id>", "filter by catalog id").option("--name <name>", "filter by name").option(
|
|
3995
|
+
`${categoryFlag} <category>`,
|
|
3996
|
+
`resource category: ${ResourceCategory.options.join(" | ")}`,
|
|
3997
|
+
oneOf(categoryFlag, ResourceCategory.options)
|
|
3998
|
+
).option(
|
|
3999
|
+
`${alias} <category>`,
|
|
4000
|
+
`alias of ${categoryFlag}`,
|
|
4001
|
+
oneOf(alias, ResourceCategory.options)
|
|
4002
|
+
).option(
|
|
4003
|
+
"--status <status>",
|
|
4004
|
+
`filter by status: ${ResourceStatus.options.join(" | ")}`,
|
|
4005
|
+
oneOf("--status", ResourceStatus.options)
|
|
4006
|
+
).option(
|
|
4007
|
+
"--enabled <bool>",
|
|
4008
|
+
"filter by enabled state: true | false",
|
|
4009
|
+
oneOf("--enabled", ["true", "false"])
|
|
4010
|
+
).option("--last-discover-status <status>", "filter by latest discovery status").option("--schema <name>", "filter by source schema").option("--limit <n>", "page size", int6("--limit"), DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", nonNegativeInt2("--offset"), 0).option(
|
|
4011
|
+
"--sort <field>",
|
|
4012
|
+
`sort field: ${SORT_FIELDS.join(" | ")}`,
|
|
4013
|
+
oneOf("--sort", SORT_FIELDS)
|
|
4014
|
+
).option(
|
|
4015
|
+
"--direction <dir>",
|
|
4016
|
+
`sort direction: ${DIRECTIONS2.join(" | ")}`,
|
|
4017
|
+
oneOf("--direction", DIRECTIONS2)
|
|
4018
|
+
);
|
|
4019
|
+
}
|
|
4020
|
+
function resourceListOptionsFrom(opts) {
|
|
4021
|
+
return {
|
|
4022
|
+
catalogId: opts.catalogId,
|
|
4023
|
+
name: opts.name,
|
|
4024
|
+
category: opts.category ?? opts.type,
|
|
4025
|
+
status: opts.status,
|
|
4026
|
+
enabled: opts.enabled === void 0 ? void 0 : opts.enabled === "true",
|
|
4027
|
+
lastDiscoverStatus: opts.lastDiscoverStatus,
|
|
4028
|
+
schema: opts.schema,
|
|
4029
|
+
limit: opts.limit,
|
|
4030
|
+
offset: opts.offset,
|
|
4031
|
+
sort: opts.sort,
|
|
4032
|
+
direction: opts.direction
|
|
4033
|
+
};
|
|
4034
|
+
}
|
|
4035
|
+
function addResourceQueryOptions(cmd) {
|
|
4036
|
+
return cmd.option("--limit <n>", "row limit", int6("--limit")).option("--offset <n>", "row offset", nonNegativeInt2("--offset")).option(
|
|
4037
|
+
"--paging-mode <mode>",
|
|
4038
|
+
"paging mode: single | cursor",
|
|
4039
|
+
oneOf("--paging-mode", ["single", "cursor"])
|
|
4040
|
+
).option("--keep-alive-sec <s>", "cursor keep-alive in seconds (60\u20133600)", keepAliveSec).option("--cursor <cursor>", "opaque cursor returned by the previous page").option("--need-total", "include total count").option("--filter <json>", "Vega filter_condition JSON object").option("--sort <field:dir,...>", "sort fields, e.g. create_time:desc,id:asc").option("--output-fields <f1,f2>", "comma-separated fields to return").option(
|
|
4041
|
+
"--binary-mode <mode>",
|
|
4042
|
+
"Binary fields as metadata (byte length, default) | content (Base64)",
|
|
4043
|
+
oneOf("--binary-mode", ["metadata", "content"])
|
|
4044
|
+
).option("--ignore-local-index", "read a table's source even when a local index is available");
|
|
4045
|
+
}
|
|
4046
|
+
function parseFilter(raw) {
|
|
4047
|
+
let parsed;
|
|
4048
|
+
try {
|
|
4049
|
+
parsed = parseBigIntJSON(raw);
|
|
4050
|
+
} catch {
|
|
4051
|
+
throw new InputError("--filter must be valid JSON");
|
|
4052
|
+
}
|
|
4053
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
4054
|
+
throw new InputError("--filter must be a JSON object");
|
|
4055
|
+
}
|
|
4056
|
+
return parsed;
|
|
4057
|
+
}
|
|
4058
|
+
function parseSort(raw) {
|
|
4059
|
+
const items = csv(raw) ?? [];
|
|
4060
|
+
if (items.length === 0) throw new InputError("--sort must name at least one field");
|
|
4061
|
+
return items.map((item) => {
|
|
4062
|
+
const at = item.lastIndexOf(":");
|
|
4063
|
+
const field = at === -1 ? item : item.slice(0, at);
|
|
4064
|
+
const direction = at === -1 ? "asc" : item.slice(at + 1);
|
|
4065
|
+
if (!field || direction !== "asc" && direction !== "desc") {
|
|
4066
|
+
throw new InputError(`--sort entries must be field[:asc|desc] (got '${item}')`);
|
|
4067
|
+
}
|
|
4068
|
+
return { field, direction };
|
|
4069
|
+
});
|
|
4070
|
+
}
|
|
4071
|
+
function resourceQueryOptionsFrom(opts, defaultLimit) {
|
|
4072
|
+
if (opts.cursor) {
|
|
4073
|
+
const initialOnly = [
|
|
4074
|
+
["--limit", opts.limit],
|
|
4075
|
+
["--offset", opts.offset],
|
|
4076
|
+
["--paging-mode", opts.pagingMode],
|
|
4077
|
+
["--keep-alive-sec", opts.keepAliveSec],
|
|
4078
|
+
["--filter", opts.filter],
|
|
4079
|
+
["--sort", opts.sort],
|
|
4080
|
+
["--output-fields", opts.outputFields],
|
|
4081
|
+
["--binary-mode", opts.binaryMode],
|
|
4082
|
+
["--ignore-local-index", opts.ignoreLocalIndex]
|
|
4083
|
+
].filter(([, value]) => value !== void 0);
|
|
4084
|
+
if (initialOnly.length > 0) {
|
|
4085
|
+
throw new InputError(
|
|
4086
|
+
`--cursor cannot be combined with initial-query options (${initialOnly.map(([flag]) => flag).join(", ")})`
|
|
4087
|
+
);
|
|
4088
|
+
}
|
|
4089
|
+
return {
|
|
4090
|
+
cursor: opts.cursor,
|
|
4091
|
+
...opts.needTotal ? { needTotal: true } : {}
|
|
4092
|
+
};
|
|
4093
|
+
}
|
|
4094
|
+
return {
|
|
4095
|
+
limit: opts.limit ?? defaultLimit,
|
|
4096
|
+
offset: opts.offset ?? 0,
|
|
4097
|
+
pagingMode: opts.pagingMode,
|
|
4098
|
+
keepAliveSec: opts.keepAliveSec,
|
|
4099
|
+
needTotal: opts.needTotal ? true : void 0,
|
|
4100
|
+
...opts.filter !== void 0 ? { filterCondition: parseFilter(opts.filter) } : {},
|
|
4101
|
+
...opts.sort !== void 0 ? { sort: parseSort(opts.sort) } : {},
|
|
4102
|
+
...opts.outputFields !== void 0 ? { outputFields: csv(opts.outputFields) ?? [] } : {},
|
|
4103
|
+
...opts.binaryMode !== void 0 ? { binaryMode: opts.binaryMode } : {},
|
|
4104
|
+
...opts.ignoreLocalIndex ? { ignoreLocalIndex: true } : {}
|
|
4105
|
+
};
|
|
4106
|
+
}
|
|
3208
4107
|
function resourceCommand() {
|
|
3209
|
-
const cmd = new
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
schema: opts.schema,
|
|
3216
|
-
limit: opts.limit,
|
|
3217
|
-
offset: opts.offset,
|
|
3218
|
-
sort: opts.sort,
|
|
3219
|
-
direction: opts.direction
|
|
3220
|
-
});
|
|
4108
|
+
const cmd = new Command12("resource").alias("res").description("Tables and views behind a network: find, inspect, sample, enable, disable");
|
|
4109
|
+
addResourceListOptions(
|
|
4110
|
+
cmd.command("list").description("List resources under a catalog"),
|
|
4111
|
+
"--category"
|
|
4112
|
+
).action(async (opts, cmd2) => {
|
|
4113
|
+
const data = await clientFrom(cmd2).resource.list(resourceListOptionsFrom(opts));
|
|
3221
4114
|
printJson(data, outputOptions(cmd2));
|
|
3222
4115
|
});
|
|
3223
|
-
cmd.command("find").description("Search resources by name, fuzzy unless --exact \u2192 a bare array, not an envelope").requiredOption("--name <name>", "resource name to search").option("--exact", "exact name match").option("--catalog-id <id>", "limit to a catalog").option("--limit <n>", "rows to scan before filtering",
|
|
4116
|
+
cmd.command("find").description("Search resources by name, fuzzy unless --exact \u2192 a bare array, not an envelope").requiredOption("--name <name>", "resource name to search").option("--exact", "exact name match").option("--catalog-id <id>", "limit to a catalog").option("--limit <n>", "rows to scan before filtering", int6("--limit"), DEFAULT_LIST_LIMIT).action(async (opts, cmd2) => {
|
|
3224
4117
|
const data = await clientFrom(cmd2).resource.find(opts.name, {
|
|
3225
4118
|
exact: opts.exact,
|
|
3226
4119
|
catalogId: opts.catalogId,
|
|
@@ -3238,15 +4131,13 @@ function resourceCommand() {
|
|
|
3238
4131
|
printJson(result, outputOptions(cmd2));
|
|
3239
4132
|
});
|
|
3240
4133
|
}
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
needTotal: opts.needTotal
|
|
3249
|
-
});
|
|
4134
|
+
addResourceQueryOptions(
|
|
4135
|
+
cmd.command("query <id>").description(`Fetch data rows from a resource (default limit ${DEFAULT_QUERY_LIMIT})`)
|
|
4136
|
+
).action(async (id, opts, cmd2) => {
|
|
4137
|
+
const data = await clientFrom(cmd2).resource.query(
|
|
4138
|
+
id,
|
|
4139
|
+
resourceQueryOptionsFrom(opts, DEFAULT_QUERY_LIMIT)
|
|
4140
|
+
);
|
|
3250
4141
|
printJson(data, outputOptions(cmd2));
|
|
3251
4142
|
});
|
|
3252
4143
|
cmd.command("delete <id>").description("Delete a resource").option("-y, --yes", "skip confirmation").action(async (id, _opts, cmd2) => {
|
|
@@ -3261,18 +4152,7 @@ function resourceCommand() {
|
|
|
3261
4152
|
}
|
|
3262
4153
|
|
|
3263
4154
|
// src/commands/skill.ts
|
|
3264
|
-
import { Command as
|
|
3265
|
-
var int8 = (v) => Number.parseInt(v, 10);
|
|
3266
|
-
var positiveInt = (flag) => (v) => {
|
|
3267
|
-
if (!/^\d+$/.test(v)) {
|
|
3268
|
-
throw new InputError(`${flag} must be a positive integer (got '${v}')`);
|
|
3269
|
-
}
|
|
3270
|
-
const n = Number.parseInt(v, 10);
|
|
3271
|
-
if (!Number.isSafeInteger(n) || n <= 0) {
|
|
3272
|
-
throw new InputError(`${flag} must be a positive integer (got '${v}')`);
|
|
3273
|
-
}
|
|
3274
|
-
return n;
|
|
3275
|
-
};
|
|
4155
|
+
import { Command as Command13 } from "commander";
|
|
3276
4156
|
var MOCKED_EXIT_CODE = 125;
|
|
3277
4157
|
function sandboxExitCode(result) {
|
|
3278
4158
|
if (result?.mocked) return MOCKED_EXIT_CODE;
|
|
@@ -3280,31 +4160,70 @@ function sandboxExitCode(result) {
|
|
|
3280
4160
|
if (!Number.isSafeInteger(code) || code < 0) return 1;
|
|
3281
4161
|
return code > 255 ? 1 : code;
|
|
3282
4162
|
}
|
|
3283
|
-
|
|
4163
|
+
function metadataBody(body) {
|
|
4164
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) {
|
|
4165
|
+
throw new InputError("update-metadata body must be a JSON object");
|
|
4166
|
+
}
|
|
4167
|
+
const b = body;
|
|
4168
|
+
const missing = ["name", "description", "category"].filter(
|
|
4169
|
+
(k) => typeof b[k] !== "string" || b[k].length === 0
|
|
4170
|
+
);
|
|
4171
|
+
if (missing.length > 0) {
|
|
4172
|
+
throw new InputError(
|
|
4173
|
+
`update-metadata replaces the metadata: ${missing.join(", ")} ${missing.length === 1 ? "is" : "are"} required (non-empty string)`
|
|
4174
|
+
);
|
|
4175
|
+
}
|
|
4176
|
+
if (b.source !== void 0 && !SKILL_SOURCES.includes(b.source)) {
|
|
4177
|
+
throw new InputError(
|
|
4178
|
+
`source must be one of: ${SKILL_SOURCES.join(" | ")} (got ${JSON.stringify(b.source)})`
|
|
4179
|
+
);
|
|
4180
|
+
}
|
|
4181
|
+
const ext = b.extend_info;
|
|
4182
|
+
if (ext !== void 0 && (ext === null || typeof ext !== "object" || Array.isArray(ext))) {
|
|
4183
|
+
throw new InputError("extend_info must be a JSON object");
|
|
4184
|
+
}
|
|
4185
|
+
return b;
|
|
4186
|
+
}
|
|
3284
4187
|
function checkSource(source) {
|
|
3285
4188
|
if (source === void 0 || SKILL_SOURCES.includes(source)) return source;
|
|
3286
4189
|
throw new InputError(`--source must be one of: ${SKILL_SOURCES.join(" | ")} (got '${source}')`);
|
|
3287
4190
|
}
|
|
3288
4191
|
var draftOption = (c) => c.option("--draft", "read the draft (management) version instead of the published one");
|
|
3289
4192
|
function skillCommand() {
|
|
3290
|
-
const cmd = new
|
|
4193
|
+
const cmd = new Command13("skill").description(
|
|
3291
4194
|
"Skill packages (SKILL.md + files) agents load on demand"
|
|
3292
4195
|
);
|
|
3293
|
-
const listOpts = (c) => c.option("--name <s>", "filter by name").option("--
|
|
4196
|
+
const listOpts = (c) => c.option("--name <s>", "filter by name").option("--category <s>", "filter by category").option("--create-user <s>", "filter by creator").option(
|
|
4197
|
+
"--sort-by <f>",
|
|
4198
|
+
"create_time | update_time | name (service default update_time)",
|
|
4199
|
+
oneOf("--sort-by", ["create_time", "update_time", "name"])
|
|
4200
|
+
).option("--sort-order <o>", "asc | desc", oneOf("--sort-order", ["asc", "desc"])).option(
|
|
4201
|
+
"--limit <n>",
|
|
4202
|
+
`page size, 1-${MAX_PAGE_SIZE}`,
|
|
4203
|
+
positiveInt("--limit", MAX_PAGE_SIZE),
|
|
4204
|
+
DEFAULT_LIST_LIMIT
|
|
4205
|
+
).option("--page <n>", "page (1-based)", positiveInt("--page"), 1).option("--all", "return every skill, ignoring page size");
|
|
4206
|
+
const listFilters = (opts) => ({
|
|
4207
|
+
name: opts.name,
|
|
4208
|
+
category: opts.category,
|
|
4209
|
+
createUser: opts.createUser,
|
|
4210
|
+
sortBy: opts.sortBy,
|
|
4211
|
+
sortOrder: opts.sortOrder,
|
|
4212
|
+
pageSize: opts.limit,
|
|
4213
|
+
page: opts.page,
|
|
4214
|
+
all: opts.all
|
|
4215
|
+
});
|
|
3294
4216
|
listOpts(
|
|
3295
4217
|
cmd.command("list").description(
|
|
3296
4218
|
"List skills \u2192 {data, total, page, page_size, has_next}; the id to reuse is `skill_id`"
|
|
3297
4219
|
)
|
|
3298
|
-
).option(
|
|
4220
|
+
).option(
|
|
4221
|
+
"--status <s>",
|
|
4222
|
+
"unpublish | published | offline | editing",
|
|
4223
|
+
oneOf("--status", ["unpublish", "published", "offline", "editing"])
|
|
4224
|
+
).action(async (opts, cmd2) => {
|
|
3299
4225
|
printJson(
|
|
3300
|
-
await clientFrom(cmd2).skills.list({
|
|
3301
|
-
name: opts.name,
|
|
3302
|
-
source: opts.source,
|
|
3303
|
-
status: opts.status,
|
|
3304
|
-
createUser: opts.createUser,
|
|
3305
|
-
pageSize: opts.limit,
|
|
3306
|
-
page: opts.page
|
|
3307
|
-
}),
|
|
4226
|
+
await clientFrom(cmd2).skills.list({ ...listFilters(opts), status: opts.status }),
|
|
3308
4227
|
outputOptions(cmd2)
|
|
3309
4228
|
);
|
|
3310
4229
|
});
|
|
@@ -3314,15 +4233,7 @@ function skillCommand() {
|
|
|
3314
4233
|
listOpts(
|
|
3315
4234
|
cmd.command("market").description("Browse the skill market \u2192 {data, total, page, has_next}")
|
|
3316
4235
|
).action(async (opts, cmd2) => {
|
|
3317
|
-
printJson(
|
|
3318
|
-
await clientFrom(cmd2).skills.market({
|
|
3319
|
-
name: opts.name,
|
|
3320
|
-
source: opts.source,
|
|
3321
|
-
pageSize: opts.limit,
|
|
3322
|
-
page: opts.page
|
|
3323
|
-
}),
|
|
3324
|
-
outputOptions(cmd2)
|
|
3325
|
-
);
|
|
4236
|
+
printJson(await clientFrom(cmd2).skills.market(listFilters(opts)), outputOptions(cmd2));
|
|
3326
4237
|
});
|
|
3327
4238
|
cmd.command("market-get <skill-id>").description("Get a market skill by id").action(async (id, _opts, cmd2) => {
|
|
3328
4239
|
printJson(await clientFrom(cmd2).skills.marketGet(id), outputOptions(cmd2));
|
|
@@ -3425,17 +4336,16 @@ ${files.length} files, ${bytes} B
|
|
|
3425
4336
|
cmd.command("history <skill-id>").description("Show a skill's version history").action(async (id, _opts, cmd2) => {
|
|
3426
4337
|
printJson(await clientFrom(cmd2).skills.history(id), outputOptions(cmd2));
|
|
3427
4338
|
});
|
|
3428
|
-
cmd.command("set-status <skill-id> <status>").description(
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
outputOptions(cmd2)
|
|
3432
|
-
);
|
|
4339
|
+
cmd.command("set-status <skill-id> <status>").description(`Publish or take down a skill: ${SKILL_STATUSES.join(" | ")}`).action(async (id, status2, _opts, cmd2) => {
|
|
4340
|
+
const target = oneOf("<status>", SKILL_STATUSES)(status2);
|
|
4341
|
+
printJson(await clientFrom(cmd2).skills.setStatus(id, target), outputOptions(cmd2));
|
|
3433
4342
|
});
|
|
3434
|
-
cmd.command("register <directory>").description("Zip a local skill directory and register it").option("--source <s>", `source tag: ${SKILL_SOURCES.join(" | ")}`, "custom").option("--extend-info <json>", "extra metadata as JSON").action(async (dir, opts, cmd2) => {
|
|
4343
|
+
cmd.command("register <directory>").description("Zip a local skill directory and register it").option("--source <s>", `source tag: ${SKILL_SOURCES.join(" | ")}`, "custom").option("--category <s>", "category (service default other_category)").option("--extend-info <json>", "extra metadata as JSON").action(async (dir, opts, cmd2) => {
|
|
3435
4344
|
const extendInfo = opts.extendInfo ? parseBigIntJSON(opts.extendInfo) : void 0;
|
|
3436
4345
|
printJson(
|
|
3437
4346
|
await clientFrom(cmd2).skills.register(dir, {
|
|
3438
4347
|
source: checkSource(opts.source),
|
|
4348
|
+
category: opts.category,
|
|
3439
4349
|
extendInfo
|
|
3440
4350
|
}),
|
|
3441
4351
|
outputOptions(cmd2)
|
|
@@ -3450,22 +4360,26 @@ ${files.length} files, ${bytes} B
|
|
|
3450
4360
|
cmd.command("install <skill-id> [directory]").description("Download a skill archive and extract it locally").action(async (skillId, dir, _o, cmd2) => {
|
|
3451
4361
|
printJson(await clientFrom(cmd2).skills.install(skillId, dir), outputOptions(cmd2));
|
|
3452
4362
|
});
|
|
3453
|
-
cmd.command("update-metadata <skill-id>").description(
|
|
4363
|
+
cmd.command("update-metadata <skill-id>").description(
|
|
4364
|
+
"Replace a skill's metadata (--body / --body-file JSON: name, description, category required)"
|
|
4365
|
+
).option(
|
|
3454
4366
|
"--body <json>",
|
|
3455
|
-
"
|
|
4367
|
+
"{name, description, category, source?: custom|internal, extend_info?} \u2014 a full overwrite"
|
|
3456
4368
|
).option("--body-file <path>", "read metadata JSON from a file").action(async (skillId, opts, cmd2) => {
|
|
3457
4369
|
printJson(
|
|
3458
|
-
await clientFrom(cmd2).skills.updateMetadata(skillId, readBody(opts)),
|
|
4370
|
+
await clientFrom(cmd2).skills.updateMetadata(skillId, metadataBody(readBody(opts))),
|
|
3459
4371
|
outputOptions(cmd2)
|
|
3460
4372
|
);
|
|
3461
4373
|
});
|
|
3462
4374
|
cmd.command("update-package <skill-id> <directory>").description("Replace a skill's package from a local directory").action(async (skillId, dir, _o, cmd2) => {
|
|
3463
4375
|
printJson(await clientFrom(cmd2).skills.updatePackage(skillId, dir), outputOptions(cmd2));
|
|
3464
4376
|
});
|
|
3465
|
-
cmd.command("republish <skill-id>").description(
|
|
4377
|
+
cmd.command("republish <skill-id>").description(
|
|
4378
|
+
"Copy a historical version back into the draft (publishes nothing; see publish-history)"
|
|
4379
|
+
).requiredOption("--version <v>", "historical version to restore into the draft").action(async (skillId, opts, cmd2) => {
|
|
3466
4380
|
printJson(await clientFrom(cmd2).skills.republish(skillId, opts.version), outputOptions(cmd2));
|
|
3467
4381
|
});
|
|
3468
|
-
cmd.command("publish-history <skill-id>").description("Publish a historical skill version").requiredOption("--version <v>", "version to publish").action(async (skillId, opts, cmd2) => {
|
|
4382
|
+
cmd.command("publish-history <skill-id>").description("Publish a historical skill version directly").requiredOption("--version <v>", "version to publish").action(async (skillId, opts, cmd2) => {
|
|
3469
4383
|
printJson(
|
|
3470
4384
|
await clientFrom(cmd2).skills.publishHistory(skillId, opts.version),
|
|
3471
4385
|
outputOptions(cmd2)
|
|
@@ -3506,30 +4420,87 @@ PUBLISHED VS DRAFT
|
|
|
3506
4420
|
|
|
3507
4421
|
AUTHORING
|
|
3508
4422
|
register <dir> zips and registers; update-package replaces the files; update-metadata
|
|
3509
|
-
changes only the metadata
|
|
4423
|
+
changes only the metadata (a full overwrite: name, description, category required).
|
|
4424
|
+
set-status publishes or takes down the current version. republish copies a historical
|
|
4425
|
+
version back into the draft and publishes nothing; publish-history publishes one.`
|
|
3510
4426
|
);
|
|
3511
4427
|
return group(cmd, "TOOLS & SKILLS");
|
|
3512
4428
|
}
|
|
3513
4429
|
|
|
3514
4430
|
// src/commands/toolbox.ts
|
|
3515
|
-
import { Command as
|
|
4431
|
+
import { Command as Command14, Option as Option4 } from "commander";
|
|
3516
4432
|
import yaml from "js-yaml";
|
|
3517
|
-
var
|
|
4433
|
+
var SORT_ORDERS = ["asc", "desc"];
|
|
4434
|
+
var TOOLBOX_STATUSES = ["unpublish", "published", "offline"];
|
|
4435
|
+
function toolCallFailed(result) {
|
|
4436
|
+
if (!result || typeof result !== "object") return false;
|
|
4437
|
+
const { status_code: status2, error } = result;
|
|
4438
|
+
if (typeof status2 === "number" && status2 >= 400) return true;
|
|
4439
|
+
return typeof error === "string" ? error.length > 0 : error !== void 0 && error !== null;
|
|
4440
|
+
}
|
|
4441
|
+
function pathParams(parsed) {
|
|
4442
|
+
if (parsed === void 0) return void 0;
|
|
4443
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
4444
|
+
if (typeof v !== "string") {
|
|
4445
|
+
throw new InputError(
|
|
4446
|
+
`--path values must be strings (path parameter '${k}' is ${v === null ? "null" : Array.isArray(v) ? "an array" : typeof v})`
|
|
4447
|
+
);
|
|
4448
|
+
}
|
|
4449
|
+
}
|
|
4450
|
+
return parsed;
|
|
4451
|
+
}
|
|
4452
|
+
function globalParameterOption(raw) {
|
|
4453
|
+
const parsed = parseJsonObjectOption(raw, "global-parameter");
|
|
4454
|
+
if (parsed === void 0) return void 0;
|
|
4455
|
+
for (const k of ["name", "description", "in", "type"]) {
|
|
4456
|
+
if (typeof parsed[k] !== "string" || !parsed[k]) {
|
|
4457
|
+
throw new InputError(`--global-parameter needs a non-empty string '${k}'`);
|
|
4458
|
+
}
|
|
4459
|
+
}
|
|
4460
|
+
return parsed;
|
|
4461
|
+
}
|
|
3518
4462
|
function toolboxCommand() {
|
|
3519
|
-
const cmd = new
|
|
3520
|
-
cmd.command("list").description("List toolboxes").option("--
|
|
4463
|
+
const cmd = new Command14("toolbox").description("Toolboxes: group tools into one publishable box");
|
|
4464
|
+
cmd.command("list").description("List toolboxes \u2192 {data, total, page, page_size, has_next}; the id is `box_id`").option("--name <s>", "filter by toolbox name").addOption(new Option4("--keyword <s>", "deprecated: use --name").hideHelp()).option("--status <s>", "unpublish | published | offline", oneOf("--status", TOOLBOX_STATUSES)).option("--category <s>", "filter by category").option(
|
|
4465
|
+
"--metadata-type <t>",
|
|
4466
|
+
"openapi | function",
|
|
4467
|
+
oneOf("--metadata-type", ["openapi", "function"])
|
|
4468
|
+
).option("--create-user <s>", "filter by creator").option("--release-user <s>", "filter by publisher").option(
|
|
4469
|
+
"--sort-by <f>",
|
|
4470
|
+
"create_time | update_time | name (service default update_time)",
|
|
4471
|
+
oneOf("--sort-by", ["create_time", "update_time", "name"])
|
|
4472
|
+
).option("--sort-order <o>", "asc | desc", oneOf("--sort-order", SORT_ORDERS)).option(
|
|
4473
|
+
"--limit <n>",
|
|
4474
|
+
`page size, 1-${MAX_PAGE_SIZE}`,
|
|
4475
|
+
positiveInt("--limit", MAX_PAGE_SIZE),
|
|
4476
|
+
DEFAULT_LIST_LIMIT
|
|
4477
|
+
).option("--page <n>", "page (1-based)", positiveInt("--page"), 1).option("--all", "return every toolbox, ignoring page size").addOption(new Option4("--offset <n>", "removed: use --page").hideHelp()).action(async (opts, cmd2) => {
|
|
4478
|
+
if (opts.offset !== void 0) {
|
|
4479
|
+
throw new InputError("--offset is not supported: the service pages by --page (1-based)");
|
|
4480
|
+
}
|
|
4481
|
+
if (opts.keyword !== void 0 && opts.name !== void 0) {
|
|
4482
|
+
throw new InputError("--keyword is a deprecated alias of --name; pass only --name");
|
|
4483
|
+
}
|
|
3521
4484
|
printJson(
|
|
3522
4485
|
await clientFrom(cmd2).toolboxes.list({
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
4486
|
+
name: opts.name ?? opts.keyword,
|
|
4487
|
+
status: opts.status,
|
|
4488
|
+
category: opts.category,
|
|
4489
|
+
metadataType: opts.metadataType,
|
|
4490
|
+
createUser: opts.createUser,
|
|
4491
|
+
releaseUser: opts.releaseUser,
|
|
4492
|
+
sortBy: opts.sortBy,
|
|
4493
|
+
sortOrder: opts.sortOrder,
|
|
4494
|
+
pageSize: opts.limit,
|
|
4495
|
+
page: opts.page,
|
|
4496
|
+
all: opts.all
|
|
3526
4497
|
}),
|
|
3527
4498
|
outputOptions(cmd2)
|
|
3528
4499
|
);
|
|
3529
4500
|
});
|
|
3530
4501
|
cmd.command("create").description(
|
|
3531
4502
|
"Create a toolbox \u2014 openapi proxies to a service, function holds platform functions"
|
|
3532
|
-
).requiredOption("--name <name>", "toolbox name").option("--service-url <url>", "where an openapi box proxies its tools; required for that type").option("--type <t>", "openapi | function", "openapi").option("--description <d>", "description").action(async (opts, cmd2) => {
|
|
4503
|
+
).requiredOption("--name <name>", "toolbox name").option("--service-url <url>", "where an openapi box proxies its tools; required for that type").option("--type <t>", "openapi | function", "openapi").option("--description <d>", "description").option("--category <c>", "box category (service default other_category)").action(async (opts, cmd2) => {
|
|
3533
4504
|
if (opts.type !== "openapi" && opts.type !== "function") {
|
|
3534
4505
|
throw new InputError("--type must be openapi or function");
|
|
3535
4506
|
}
|
|
@@ -3541,7 +4512,8 @@ function toolboxCommand() {
|
|
|
3541
4512
|
name: opts.name,
|
|
3542
4513
|
serviceUrl: opts.serviceUrl,
|
|
3543
4514
|
description: opts.description,
|
|
3544
|
-
metadataType: opts.type
|
|
4515
|
+
metadataType: opts.type,
|
|
4516
|
+
category: opts.category
|
|
3545
4517
|
}),
|
|
3546
4518
|
outputOptions(cmd2)
|
|
3547
4519
|
);
|
|
@@ -3549,20 +4521,37 @@ function toolboxCommand() {
|
|
|
3549
4521
|
cmd.command("publish <box-id>").description("Publish a toolbox").action(async (id, _opts, cmd2) => {
|
|
3550
4522
|
printJson(await clientFrom(cmd2).toolboxes.publish(id), outputOptions(cmd2));
|
|
3551
4523
|
});
|
|
3552
|
-
cmd.command("unpublish <box-id>").description("
|
|
4524
|
+
cmd.command("unpublish <box-id>").description("Take a published toolbox down (status=offline)").action(async (id, _opts, cmd2) => {
|
|
3553
4525
|
printJson(await clientFrom(cmd2).toolboxes.unpublish(id), outputOptions(cmd2));
|
|
3554
4526
|
});
|
|
3555
4527
|
cmd.command("delete <box-id>").description("Delete a toolbox").option("-y, --yes", "skip confirmation").action(async (id, _opts, cmd2) => {
|
|
3556
4528
|
printJson(await clientFrom(cmd2).toolboxes.delete(id), outputOptions(cmd2));
|
|
3557
4529
|
});
|
|
3558
|
-
cmd.command("export <box-id>").description("Export a toolbox config to a local .adp file").requiredOption("-o, --out <file>", "output .adp path").option(
|
|
4530
|
+
cmd.command("export <box-id>").description("Export a toolbox config to a local .adp file").requiredOption("-o, --out <file>", "output .adp path").option(
|
|
4531
|
+
"--type <t>",
|
|
4532
|
+
"impex type: toolbox | mcp | operator",
|
|
4533
|
+
oneOf("--type", IMPEX_TYPES),
|
|
4534
|
+
"toolbox"
|
|
4535
|
+
).action(async (boxId, opts, cmd2) => {
|
|
3559
4536
|
printJson(
|
|
3560
4537
|
await clientFrom(cmd2).toolboxes.export(boxId, opts.out, opts.type),
|
|
3561
4538
|
outputOptions(cmd2)
|
|
3562
4539
|
);
|
|
3563
4540
|
});
|
|
3564
|
-
cmd.command("import <file>").description("Import a toolbox config from a local .adp file").option(
|
|
3565
|
-
|
|
4541
|
+
cmd.command("import <file>").description("Import a toolbox config from a local .adp file").option(
|
|
4542
|
+
"--type <t>",
|
|
4543
|
+
"impex type: toolbox | mcp | operator",
|
|
4544
|
+
oneOf("--type", IMPEX_TYPES),
|
|
4545
|
+
"toolbox"
|
|
4546
|
+
).option(
|
|
4547
|
+
"--mode <m>",
|
|
4548
|
+
"create (fail if it exists; service default) | upsert (update if it exists)",
|
|
4549
|
+
oneOf("--mode", ["create", "upsert"])
|
|
4550
|
+
).action(async (file, opts, cmd2) => {
|
|
4551
|
+
printJson(
|
|
4552
|
+
await clientFrom(cmd2).toolboxes.import(file, opts.type, opts.mode),
|
|
4553
|
+
outputOptions(cmd2)
|
|
4554
|
+
);
|
|
3566
4555
|
});
|
|
3567
4556
|
groupChildren(cmd, {
|
|
3568
4557
|
READ: ["list", "export"],
|
|
@@ -3575,41 +4564,81 @@ function toolboxCommand() {
|
|
|
3575
4564
|
--type function its tools are platform functions, no service URL to give
|
|
3576
4565
|
|
|
3577
4566
|
ORDER OF WORK
|
|
3578
|
-
toolbox create --name "<n>" an empty box,
|
|
4567
|
+
toolbox create --name "<n>" an empty box, not yet published
|
|
3579
4568
|
tool create ./add.py --toolbox a function tool, or --type openapi for a spec
|
|
4569
|
+
tool debug <tool-id> call it while building, before enable/publish
|
|
3580
4570
|
tool enable <tool-ids...> a tool is off until enabled
|
|
3581
|
-
toolbox publish <box-id>
|
|
3582
|
-
tool execute <tool-id> call an enabled tool
|
|
3583
|
-
tool debug <tool-id> call one that is not, while building it
|
|
4571
|
+
toolbox publish <box-id> execute needs a published box
|
|
4572
|
+
tool execute <tool-id> call an enabled tool in a published box
|
|
3584
4573
|
|
|
3585
|
-
|
|
3586
|
-
an unpublished box
|
|
4574
|
+
Both gates apply to \`execute\`: the tool must be enabled and the box published \u2014
|
|
4575
|
+
an unpublished or offline box answers 400 ToolNotAvailable. \`debug\` skips both.
|
|
3587
4576
|
|
|
3588
4577
|
export / import move a whole box between deploys as an .adp file.`
|
|
3589
4578
|
);
|
|
3590
4579
|
return group(cmd, "TOOLS & SKILLS");
|
|
3591
4580
|
}
|
|
3592
4581
|
function toolCommand() {
|
|
3593
|
-
|
|
3594
|
-
|
|
4582
|
+
return buildToolCommand({ name: "tool", createCommand: "create", includeUpload: true });
|
|
4583
|
+
}
|
|
4584
|
+
function functionToolCommand() {
|
|
4585
|
+
return buildToolCommand({
|
|
4586
|
+
name: "function",
|
|
4587
|
+
metadataType: "function",
|
|
4588
|
+
createCommand: "create",
|
|
4589
|
+
includeUpload: false
|
|
4590
|
+
});
|
|
4591
|
+
}
|
|
4592
|
+
function apiToolCommand() {
|
|
4593
|
+
return buildToolCommand({
|
|
4594
|
+
name: "api",
|
|
4595
|
+
metadataType: "openapi",
|
|
4596
|
+
createCommand: "import",
|
|
4597
|
+
includeUpload: false
|
|
4598
|
+
});
|
|
4599
|
+
}
|
|
4600
|
+
function buildToolCommand(config) {
|
|
4601
|
+
const kind = config.metadataType;
|
|
4602
|
+
const kindName = kind === "function" ? "Function Tools" : kind === "openapi" ? "OpenAPI Tools" : "Tools";
|
|
4603
|
+
const cmd = new Command14(config.name).description(
|
|
4604
|
+
kind ? `${kindName} in a toolbox: add one, enable it, and call it` : "Advanced tools in a box: add one from code or a spec, enable it, call it"
|
|
3595
4605
|
);
|
|
3596
|
-
cmd.command("list").description("List tools in a toolbox").requiredOption("--toolbox <box-id>", "toolbox id").option(
|
|
4606
|
+
cmd.command("list").description(kind ? `List ${kindName.toLowerCase()} in a toolbox` : "List tools in a toolbox").requiredOption("--toolbox <box-id>", "toolbox id").option(
|
|
4607
|
+
"--limit <n>",
|
|
4608
|
+
`page size, 1-${MAX_PAGE_SIZE} (backend default 10)`,
|
|
4609
|
+
positiveInt("--limit", MAX_PAGE_SIZE)
|
|
4610
|
+
).option("--page <n>", "page (1-based; backend default 1)", positiveInt("--page")).option("--all", "return every tool, ignoring page size").option("--name <s>", "filter by tool name").option(
|
|
4611
|
+
"--status <s>",
|
|
4612
|
+
"enabled | disabled",
|
|
4613
|
+
oneOf("--status", ["enabled", "disabled"])
|
|
4614
|
+
).option(
|
|
4615
|
+
"--sort-by <f>",
|
|
4616
|
+
"create_time | update_time | tool_name (service default create_time)",
|
|
4617
|
+
oneOf("--sort-by", ["create_time", "update_time", "tool_name"])
|
|
4618
|
+
).option("--sort-order <o>", "asc | desc", oneOf("--sort-order", SORT_ORDERS)).option("--user-id <id>", "filter by creator").action(async (opts, cmd2) => {
|
|
3597
4619
|
printJson(
|
|
3598
4620
|
await clientFrom(cmd2).toolboxes.tools(opts.toolbox, {
|
|
3599
4621
|
page: opts.page,
|
|
3600
4622
|
pageSize: opts.limit,
|
|
3601
|
-
all: opts.all
|
|
4623
|
+
all: opts.all,
|
|
4624
|
+
name: opts.name,
|
|
4625
|
+
status: opts.status,
|
|
4626
|
+
sortBy: opts.sortBy,
|
|
4627
|
+
sortOrder: opts.sortOrder,
|
|
4628
|
+
userId: opts.userId
|
|
3602
4629
|
}),
|
|
3603
4630
|
outputOptions(cmd2)
|
|
3604
4631
|
);
|
|
3605
4632
|
});
|
|
3606
|
-
cmd.command("enable <tool-ids...>").description("Enable one or more tools").requiredOption("--toolbox <box-id>", "toolbox id").action(async (toolIds, opts, cmd2) => {
|
|
4633
|
+
cmd.command("enable <tool-ids...>").description(kind ? `Enable one or more ${kindName.toLowerCase()}` : "Enable one or more tools").requiredOption("--toolbox <box-id>", "toolbox id").action(async (toolIds, opts, cmd2) => {
|
|
3607
4634
|
printJson(
|
|
3608
4635
|
await clientFrom(cmd2).toolboxes.setToolStatus(opts.toolbox, toolIds, "enabled"),
|
|
3609
4636
|
outputOptions(cmd2)
|
|
3610
4637
|
);
|
|
3611
4638
|
});
|
|
3612
|
-
cmd.command("disable <tool-ids...>").description(
|
|
4639
|
+
cmd.command("disable <tool-ids...>").description(
|
|
4640
|
+
kind ? `Disable one or more ${kindName.toLowerCase()}` : "Disable one or more tools"
|
|
4641
|
+
).requiredOption("--toolbox <box-id>", "toolbox id").action(async (toolIds, opts, cmd2) => {
|
|
3613
4642
|
printJson(
|
|
3614
4643
|
await clientFrom(cmd2).toolboxes.setToolStatus(opts.toolbox, toolIds, "disabled"),
|
|
3615
4644
|
outputOptions(cmd2)
|
|
@@ -3618,40 +4647,65 @@ function toolCommand() {
|
|
|
3618
4647
|
const invokeOpts = (c) => c.requiredOption("--toolbox <box-id>", "toolbox id").option(
|
|
3619
4648
|
"--body <json>",
|
|
3620
4649
|
"request body JSON \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (execution-factory)"
|
|
3621
|
-
).option("--header <json>", "headers map JSON").option("--query <json>", "query params JSON").option("--path <json>", "path params JSON").option(
|
|
4650
|
+
).option("--header <json>", "headers map JSON").option("--query <json>", "query params JSON").option("--path <json>", "path params JSON").option(
|
|
4651
|
+
"--timeout <s>",
|
|
4652
|
+
"per-call timeout seconds; the client waits this long plus a margin (sandbox max when omitted)",
|
|
4653
|
+
positiveInt("--timeout")
|
|
4654
|
+
);
|
|
3622
4655
|
const parseJson = (s, label) => {
|
|
3623
|
-
if (
|
|
4656
|
+
if (s === void 0) return void 0;
|
|
4657
|
+
let parsed;
|
|
3624
4658
|
try {
|
|
3625
|
-
|
|
4659
|
+
parsed = parseBigIntJSON(s);
|
|
3626
4660
|
} catch {
|
|
3627
4661
|
throw new InputError(`--${label} must be valid JSON`);
|
|
3628
4662
|
}
|
|
4663
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4664
|
+
throw new InputError(`--${label} must be a JSON object`);
|
|
4665
|
+
}
|
|
4666
|
+
return parsed;
|
|
3629
4667
|
};
|
|
3630
4668
|
const buildEnvelope = (opts) => ({
|
|
3631
4669
|
body: opts.body ? parseBigIntJSON(opts.body) : void 0,
|
|
3632
4670
|
header: parseJson(opts.header, "header"),
|
|
3633
4671
|
query: parseJson(opts.query, "query"),
|
|
3634
|
-
path: parseJson(opts.path, "path"),
|
|
4672
|
+
path: pathParams(parseJson(opts.path, "path")),
|
|
3635
4673
|
timeout: opts.timeout ? Number(opts.timeout) : void 0
|
|
3636
4674
|
});
|
|
3637
|
-
invokeOpts(cmd.command("execute <tool-id>").description("Invoke an enabled tool")).action(
|
|
3638
|
-
async (toolId, opts, cmd2) => {
|
|
3639
|
-
printJson(
|
|
3640
|
-
await clientFrom(cmd2).toolboxes.execute(opts.toolbox, toolId, buildEnvelope(opts)),
|
|
3641
|
-
outputOptions(cmd2)
|
|
3642
|
-
);
|
|
3643
|
-
}
|
|
3644
|
-
);
|
|
3645
4675
|
invokeOpts(
|
|
3646
|
-
cmd.command("
|
|
4676
|
+
cmd.command("execute <tool-id>").description(
|
|
4677
|
+
kind ? `Invoke an enabled ${kindName.slice(0, -1)} in a published toolbox` : "Invoke an enabled tool in a published toolbox"
|
|
4678
|
+
)
|
|
3647
4679
|
).action(async (toolId, opts, cmd2) => {
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
4680
|
+
const result = await clientFrom(cmd2).toolboxes.execute(
|
|
4681
|
+
opts.toolbox,
|
|
4682
|
+
toolId,
|
|
4683
|
+
buildEnvelope(opts)
|
|
3651
4684
|
);
|
|
4685
|
+
printJson(result, outputOptions(cmd2));
|
|
4686
|
+
if (toolCallFailed(result)) process.exitCode = 1;
|
|
4687
|
+
});
|
|
4688
|
+
invokeOpts(
|
|
4689
|
+
cmd.command("debug <tool-id>").description(
|
|
4690
|
+
kind ? `Invoke a ${kindName.slice(0, -1)} before it is enabled or its toolbox published` : "Invoke a tool before it is enabled or its toolbox published"
|
|
4691
|
+
)
|
|
4692
|
+
).action(async (toolId, opts, cmd2) => {
|
|
4693
|
+
const result = await clientFrom(cmd2).toolboxes.debug(opts.toolbox, toolId, buildEnvelope(opts));
|
|
4694
|
+
printJson(result, outputOptions(cmd2));
|
|
4695
|
+
if (toolCallFailed(result)) process.exitCode = 1;
|
|
4696
|
+
});
|
|
4697
|
+
const commonToolFields = (opts) => ({
|
|
4698
|
+
useRule: opts.useRule,
|
|
4699
|
+
globalParameters: globalParameterOption(opts.globalParameter),
|
|
4700
|
+
extendInfo: parseJsonObjectOption(opts.extendInfo, "extend-info")
|
|
3652
4701
|
});
|
|
4702
|
+
const toolExtraFlags = (c) => c.option("--use-rule <s>", "usage rule carried onto the tool").option(
|
|
4703
|
+
"--global-parameter <json>",
|
|
4704
|
+
"one parameter fixed onto every call: {name,description,in,type,required?,value?}"
|
|
4705
|
+
).option("--extend-info <json>", "extra metadata as a JSON object");
|
|
3653
4706
|
const toolFrom = (file, opts) => {
|
|
3654
|
-
|
|
4707
|
+
const metadataType = kind ?? opts.type;
|
|
4708
|
+
if (metadataType === "openapi") {
|
|
3655
4709
|
let data;
|
|
3656
4710
|
try {
|
|
3657
4711
|
data = yaml.load(readCode(file));
|
|
@@ -3660,19 +4714,23 @@ function toolCommand() {
|
|
|
3660
4714
|
`${file} is not valid JSON or YAML: ${err instanceof Error ? err.message : err}`
|
|
3661
4715
|
);
|
|
3662
4716
|
}
|
|
3663
|
-
return { metadataType: "openapi", data,
|
|
4717
|
+
return { metadataType: "openapi", data, ...commonToolFields(opts) };
|
|
3664
4718
|
}
|
|
3665
|
-
if (
|
|
4719
|
+
if (metadataType !== "function") throw new InputError("--type must be function or openapi");
|
|
3666
4720
|
return {
|
|
3667
4721
|
metadataType: "function",
|
|
3668
4722
|
function: functionDefinitionFrom(file, opts),
|
|
3669
|
-
|
|
4723
|
+
...commonToolFields(opts)
|
|
3670
4724
|
};
|
|
3671
4725
|
};
|
|
3672
4726
|
definitionFlags(
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
4727
|
+
toolExtraFlags(
|
|
4728
|
+
cmd.command(`${config.createCommand} <file>`).description(
|
|
4729
|
+
kind === "function" ? "Register a Function Tool from code" : kind === "openapi" ? "Import OpenAPI Tools from a JSON or YAML specification" : "Create a tool from code (or a spec)"
|
|
4730
|
+
).requiredOption("--toolbox <box-id>", "target toolbox id")
|
|
4731
|
+
),
|
|
4732
|
+
!kind,
|
|
4733
|
+
kind === "openapi" ? "openapi-import" : "all"
|
|
3676
4734
|
).action(async (file, opts, cmd2) => {
|
|
3677
4735
|
const result = await clientFrom(cmd2).toolboxes.createTool(
|
|
3678
4736
|
opts.toolbox,
|
|
@@ -3681,11 +4739,19 @@ function toolCommand() {
|
|
|
3681
4739
|
printJson(result, outputOptions(cmd2));
|
|
3682
4740
|
if (result?.failure_count) process.exitCode = 1;
|
|
3683
4741
|
});
|
|
3684
|
-
cmd.command("get <tool-id>").description(
|
|
4742
|
+
cmd.command("get <tool-id>").description(
|
|
4743
|
+
kind ? `One ${kindName.slice(0, -1)} in full: metadata, parameters, usage rule` : "One tool in full: metadata, parameters, usage rule"
|
|
4744
|
+
).requiredOption("--toolbox <box-id>", "toolbox id").action(async (toolId, opts, cmd2) => {
|
|
3685
4745
|
printJson(await clientFrom(cmd2).toolboxes.getTool(opts.toolbox, toolId), outputOptions(cmd2));
|
|
3686
4746
|
});
|
|
3687
4747
|
definitionFlags(
|
|
3688
|
-
|
|
4748
|
+
toolExtraFlags(
|
|
4749
|
+
cmd.command("update <tool-id> <file>").description(
|
|
4750
|
+
kind ? `Replace a ${kindName.slice(0, -1)} definition; the id survives and an enabled tool stays enabled` : "Replace a tool's definition; the id survives and an enabled tool stays enabled"
|
|
4751
|
+
).requiredOption("--toolbox <box-id>", "toolbox id")
|
|
4752
|
+
),
|
|
4753
|
+
!kind,
|
|
4754
|
+
kind === "openapi" ? "openapi-update" : "all"
|
|
3689
4755
|
).action(async (toolId, file, opts, cmd2) => {
|
|
3690
4756
|
if (!opts.name || !opts.description) {
|
|
3691
4757
|
throw new InputError(
|
|
@@ -3701,32 +4767,72 @@ function toolCommand() {
|
|
|
3701
4767
|
outputOptions(cmd2)
|
|
3702
4768
|
);
|
|
3703
4769
|
});
|
|
3704
|
-
cmd.command("delete <tool-ids...>").description(
|
|
4770
|
+
cmd.command("delete <tool-ids...>").description(
|
|
4771
|
+
kind ? `Delete ${kindName.toLowerCase()} from a toolbox` : "Delete tools from a toolbox"
|
|
4772
|
+
).requiredOption("--toolbox <box-id>", "toolbox id").option("-y, --yes", "skip confirmation").action(async (toolIds, opts, cmd2) => {
|
|
3705
4773
|
printJson(
|
|
3706
4774
|
await clientFrom(cmd2).toolboxes.deleteTools(opts.toolbox, toolIds),
|
|
3707
4775
|
outputOptions(cmd2)
|
|
3708
4776
|
);
|
|
3709
4777
|
});
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
4778
|
+
if (config.includeUpload) {
|
|
4779
|
+
cmd.command("upload <file>").description("Add tools from an OpenAPI file \u2014 `tool create` is the same endpoint, as JSON").requiredOption("--toolbox <id>", "target toolbox id").option(
|
|
4780
|
+
"--metadata-type <t>",
|
|
4781
|
+
"openapi | function",
|
|
4782
|
+
oneOf("--metadata-type", TOOL_METADATA_TYPES),
|
|
4783
|
+
"openapi"
|
|
4784
|
+
).action(async (file, opts, cmd2) => {
|
|
4785
|
+
printJson(
|
|
4786
|
+
await clientFrom(cmd2).toolboxes.upload(opts.toolbox, file, opts.metadataType),
|
|
4787
|
+
outputOptions(cmd2)
|
|
4788
|
+
);
|
|
4789
|
+
});
|
|
4790
|
+
}
|
|
3716
4791
|
groupChildren(cmd, {
|
|
3717
4792
|
READ: ["list", "get"],
|
|
3718
4793
|
RUN: ["execute", "debug"],
|
|
3719
|
-
WRITE: [
|
|
4794
|
+
WRITE: [
|
|
4795
|
+
config.createCommand,
|
|
4796
|
+
"update",
|
|
4797
|
+
"delete",
|
|
4798
|
+
"enable",
|
|
4799
|
+
"disable",
|
|
4800
|
+
...config.includeUpload ? ["upload"] : []
|
|
4801
|
+
]
|
|
3720
4802
|
});
|
|
4803
|
+
if (kind) {
|
|
4804
|
+
guide(
|
|
4805
|
+
cmd,
|
|
4806
|
+
`WHAT THIS GROUP MANAGES
|
|
4807
|
+
${kind === "function" ? "Function Tools keep Python handler code in a Toolbox." : "OpenAPI Tools keep operations imported from a JSON or YAML specification."}
|
|
4808
|
+
\`--toolbox\` is always the container id; create it with \`toolbox create\`.
|
|
4809
|
+
|
|
4810
|
+
ORDER OF WORK
|
|
4811
|
+
toolbox create --name "<n>"${kind === "openapi" ? " --service-url <url>" : " --type function"}
|
|
4812
|
+
${config.name} ${config.createCommand} <file> --toolbox <box-id>
|
|
4813
|
+
${config.name} debug <tool-id> --toolbox <box-id> try it before enable/publish
|
|
4814
|
+
${config.name} enable <tool-id> --toolbox <box-id>
|
|
4815
|
+
toolbox publish <box-id>
|
|
4816
|
+
${config.name} execute <tool-id> --toolbox <box-id>
|
|
4817
|
+
|
|
4818
|
+
\`execute\` needs the tool enabled and the box published; an unpublished or offline
|
|
4819
|
+
box answers 400 ToolNotAvailable. \`debug\` works before either.
|
|
4820
|
+
\`${config.name} list\` does not check the box: --toolbox must name a box whose
|
|
4821
|
+
metadata type is ${kind}.${kind === "function" ? `
|
|
4822
|
+
execute and debug go through the toolbox proxy, which cuts a function at about
|
|
4823
|
+
30s whatever --timeout says, answering 200 with result: null. Run long jobs
|
|
4824
|
+
with \`sandbox run\`.` : ""}`
|
|
4825
|
+
);
|
|
4826
|
+
}
|
|
3721
4827
|
return group(cmd, "TOOLS & SKILLS");
|
|
3722
4828
|
}
|
|
3723
4829
|
|
|
3724
4830
|
// src/commands/trace.ts
|
|
3725
|
-
import { readFileSync as
|
|
3726
|
-
import { Command as
|
|
4831
|
+
import { readFileSync as readFileSync5, writeFileSync } from "fs";
|
|
4832
|
+
import { Command as Command15 } from "commander";
|
|
3727
4833
|
|
|
3728
4834
|
// src/bkn-trace/schema-validate.ts
|
|
3729
|
-
import { readFileSync as
|
|
4835
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3730
4836
|
import { extname } from "path";
|
|
3731
4837
|
import yaml2 from "js-yaml";
|
|
3732
4838
|
import { z } from "zod";
|
|
@@ -3763,7 +4869,7 @@ var DiagnosisRule = z.object({
|
|
|
3763
4869
|
params: z.record(z.string(), z.unknown()).optional()
|
|
3764
4870
|
});
|
|
3765
4871
|
function parseFile(file) {
|
|
3766
|
-
const text =
|
|
4872
|
+
const text = readFileSync4(file, "utf8");
|
|
3767
4873
|
const ext = extname(file).toLowerCase();
|
|
3768
4874
|
if (ext === ".yaml" || ext === ".yml") return yaml2.load(text);
|
|
3769
4875
|
return parseBigIntJSON(text);
|
|
@@ -3807,28 +4913,30 @@ function renderPayload(payload) {
|
|
|
3807
4913
|
return `[omitted] ${payload.omitted_reason ?? "unknown"}`;
|
|
3808
4914
|
}
|
|
3809
4915
|
function renderTechnicalTraceDetail(detail) {
|
|
4916
|
+
const summary = detail?.summary;
|
|
3810
4917
|
const lines = [
|
|
3811
|
-
`Trace: ${
|
|
3812
|
-
`Status: ${
|
|
3813
|
-
`Request: ${
|
|
3814
|
-
`Question: ${
|
|
3815
|
-
`Result: ${
|
|
3816
|
-
`Service: ${
|
|
3817
|
-
`Spans: ${detail
|
|
4918
|
+
`Trace: ${summary?.trace_id || detail?.graph?.trace_id || "-"}`,
|
|
4919
|
+
`Status: ${summary?.status || detail?.graph?.status || "-"}`,
|
|
4920
|
+
`Request: ${summary?.request_id || "-"}`,
|
|
4921
|
+
`Question: ${summary?.question_preview || "-"}`,
|
|
4922
|
+
`Result: ${summary?.result_preview || "-"}`,
|
|
4923
|
+
`Service: ${summary?.root_service || "-"}`,
|
|
4924
|
+
`Spans: ${detail?.graph?.data?.nodes?.length ?? 0}`
|
|
3818
4925
|
];
|
|
3819
|
-
if (detail
|
|
4926
|
+
if (detail?.partial) {
|
|
3820
4927
|
lines.push(`Partial: ${(detail.partial_reasons ?? []).join(", ") || "yes"}`);
|
|
3821
4928
|
}
|
|
3822
|
-
for (const operation of detail
|
|
4929
|
+
for (const operation of detail?.operations ?? []) {
|
|
4930
|
+
const fact = operation?.fact ?? {};
|
|
3823
4931
|
lines.push(
|
|
3824
4932
|
"",
|
|
3825
|
-
`${
|
|
3826
|
-
`Source: ${
|
|
3827
|
-
`Input: ${renderPayload(
|
|
4933
|
+
`${fact.tool_name ?? "-"} \xB7 ${fact.operation_id ?? "-"} \xB7 attempt ${fact.attempt ?? "-"} \xB7 ${operation?.state ?? "-"}`,
|
|
4934
|
+
`Source: ${fact.protocol ?? "-"}/${fact.source_module ?? "-"}`,
|
|
4935
|
+
`Input: ${renderPayload(fact.input)}`
|
|
3828
4936
|
);
|
|
3829
|
-
if (
|
|
3830
|
-
if (
|
|
3831
|
-
if (operation
|
|
4937
|
+
if (fact.output) lines.push(`Output: ${renderPayload(fact.output)}`);
|
|
4938
|
+
if (fact.error) lines.push(`Error: ${renderPayload(fact.error)}`);
|
|
4939
|
+
if (operation?.partial_reasons?.length) {
|
|
3832
4940
|
lines.push(`Partial: ${operation.partial_reasons.join(", ")}`);
|
|
3833
4941
|
}
|
|
3834
4942
|
}
|
|
@@ -3836,7 +4944,7 @@ function renderTechnicalTraceDetail(detail) {
|
|
|
3836
4944
|
`;
|
|
3837
4945
|
}
|
|
3838
4946
|
function traceCommand() {
|
|
3839
|
-
const cmd = new
|
|
4947
|
+
const cmd = new Command15("trace").description(
|
|
3840
4948
|
"Inspect what an agent actually did, and diagnose bad answers"
|
|
3841
4949
|
);
|
|
3842
4950
|
cmd.command("graph <trace-id>").description("Fetch normalized trace graph by trace id").action(async (traceId, _opts, cmd2) => {
|
|
@@ -3984,7 +5092,8 @@ function traceCommand() {
|
|
|
3984
5092
|
outputOptions(cmd2)
|
|
3985
5093
|
);
|
|
3986
5094
|
});
|
|
3987
|
-
cmd.command("search").description("List authorized technical traces \u2192 {entries, total, next_cursor, partial}").option("--limit <n>", "page size, 1..200", (value) => Number.parseInt(value, 10)).option("--cursor <cursor>", "opaque pagination cursor").option("--from <time>", "started at or after this RFC3339 timestamp").option("--to <time>", "started at or before this RFC3339 timestamp").option("--status <status>", "execution status").option("--service <service>", "exact producing service").option("--tool <tool>", "exact root tool").option("--trace-id <id>", "exact Trace ID").option("--error-keyword <text>", "case-insensitive error text").option("--conversation-id <id>", "exact conversation ID").option("--interaction-id <id>", "exact interaction ID").action(async (
|
|
5095
|
+
cmd.command("search").description("List authorized technical traces \u2192 {entries, total, next_cursor, partial}").option("--limit <n>", "page size, 1..200", (value) => Number.parseInt(value, 10)).option("--cursor <cursor>", "opaque pagination cursor").option("--from <time>", "started at or after this RFC3339 timestamp").option("--to <time>", "started at or before this RFC3339 timestamp").option("--status <status>", "execution status").option("--service <service>", "exact producing service").option("--tool <tool>", "exact root tool").option("--agent-or-app <name>", "agent or application").option("--trace-id <id>", "exact Trace ID").option("--keyword <text>", "trace, request, operation, or error keyword").option("--error-keyword <text>", "case-insensitive error text").option("--conversation-id <id>", "exact conversation ID").option("--interaction-id <id>", "exact interaction ID").action(async (_opts, cmd2) => {
|
|
5096
|
+
const opts = cmd2.optsWithGlobals();
|
|
3988
5097
|
printJson(
|
|
3989
5098
|
await clientFrom(cmd2).trace.search({
|
|
3990
5099
|
limit: opts.limit,
|
|
@@ -3994,7 +5103,9 @@ function traceCommand() {
|
|
|
3994
5103
|
status: opts.status,
|
|
3995
5104
|
service: opts.service,
|
|
3996
5105
|
tool: opts.tool,
|
|
5106
|
+
agentOrApp: opts.agentOrApp,
|
|
3997
5107
|
traceId: opts.traceId,
|
|
5108
|
+
keyword: opts.keyword,
|
|
3998
5109
|
errorKeyword: opts.errorKeyword,
|
|
3999
5110
|
conversationId: opts.conversationId,
|
|
4000
5111
|
interactionId: opts.interactionId
|
|
@@ -4011,15 +5122,15 @@ function traceCommand() {
|
|
|
4011
5122
|
else console.log(renderReportMarkdown(report));
|
|
4012
5123
|
});
|
|
4013
5124
|
cmd.command("scan <conversation-ids>").description("Batch-diagnose several conversations (comma-joined) + aggregate findings").option("--llm", "hybrid mode (rubric + synthesizer) per trace via local `claude`").action(async (ids, opts, cmd2) => {
|
|
4014
|
-
const
|
|
5125
|
+
const list2 = ids.split(",").map((s) => s.trim()).filter(Boolean);
|
|
4015
5126
|
printJson(
|
|
4016
|
-
await clientFrom(cmd2).trace.scan(
|
|
5127
|
+
await clientFrom(cmd2).trace.scan(list2, { llm: Boolean(opts.llm) }),
|
|
4017
5128
|
outputOptions(cmd2)
|
|
4018
5129
|
);
|
|
4019
5130
|
});
|
|
4020
5131
|
const evalSet = cmd.command("eval-set").description("Build trace eval sets");
|
|
4021
5132
|
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) => {
|
|
4022
|
-
const raw = parseBigIntJSON(
|
|
5133
|
+
const raw = parseBigIntJSON(readFileSync5(queriesFile, "utf8"));
|
|
4023
5134
|
const cases = clientFrom(cmd2).trace.evalSetBuild(raw);
|
|
4024
5135
|
if (opts.out) {
|
|
4025
5136
|
writeFileSync(opts.out, stringifyBigIntJSON({ cases }, 2));
|
|
@@ -4064,14 +5175,117 @@ MANAGED LIFECYCLE
|
|
|
4064
5175
|
}
|
|
4065
5176
|
|
|
4066
5177
|
// src/commands/vega.ts
|
|
4067
|
-
import { Command as
|
|
4068
|
-
|
|
5178
|
+
import { Command as Command16 } from "commander";
|
|
5179
|
+
|
|
5180
|
+
// src/utils/build-progress.ts
|
|
5181
|
+
var LOG_EVERY_MS = 1e4;
|
|
5182
|
+
function formatDuration(ms) {
|
|
5183
|
+
const s = Math.max(0, Math.round(ms / 1e3));
|
|
5184
|
+
if (s < 60) return `${s}s`;
|
|
5185
|
+
const m = Math.floor(s / 60);
|
|
5186
|
+
if (m < 60) return `${m}m${String(s % 60).padStart(2, "0")}s`;
|
|
5187
|
+
return `${Math.floor(m / 60)}h${String(m % 60).padStart(2, "0")}m`;
|
|
5188
|
+
}
|
|
5189
|
+
function describeBuildProgress(task, elapsedMs, etaMs) {
|
|
5190
|
+
const state = task.status ?? "unknown";
|
|
5191
|
+
const parts = [`BuildTask ${task.id}: ${state}`];
|
|
5192
|
+
const total = task.total_count;
|
|
5193
|
+
const synced = task.synced_count;
|
|
5194
|
+
if (typeof synced === "number" && typeof total === "number" && total > 0) {
|
|
5195
|
+
const pct = Math.min(100, Math.floor(synced / total * 100));
|
|
5196
|
+
parts.push(`${synced.toLocaleString("en-US")}/${total.toLocaleString("en-US")} rows (${pct}%)`);
|
|
5197
|
+
} else if (typeof synced === "number") {
|
|
5198
|
+
parts.push(`${synced.toLocaleString("en-US")} rows`);
|
|
5199
|
+
}
|
|
5200
|
+
parts.push(`${formatDuration(elapsedMs)} elapsed`);
|
|
5201
|
+
if (etaMs !== void 0) parts.push(`~${formatDuration(etaMs)} left`);
|
|
5202
|
+
return parts.join(" \xB7 ");
|
|
5203
|
+
}
|
|
5204
|
+
function buildProgressReporter(out = process.stderr, now = Date.now) {
|
|
5205
|
+
const start = now();
|
|
5206
|
+
let baseline;
|
|
5207
|
+
let lastState;
|
|
5208
|
+
let lastLine = "";
|
|
5209
|
+
let lastLoggedAt = Number.NEGATIVE_INFINITY;
|
|
5210
|
+
let open = false;
|
|
5211
|
+
const eta = (task, at) => {
|
|
5212
|
+
const synced = task.synced_count;
|
|
5213
|
+
const total = task.total_count;
|
|
5214
|
+
if (typeof synced !== "number" || typeof total !== "number" || total <= 0) return void 0;
|
|
5215
|
+
if (task.status !== "running") return void 0;
|
|
5216
|
+
if (!baseline) {
|
|
5217
|
+
baseline = { at, synced };
|
|
5218
|
+
return void 0;
|
|
5219
|
+
}
|
|
5220
|
+
const rate = (synced - baseline.synced) / (at - baseline.at);
|
|
5221
|
+
return rate > 0 ? Math.max(0, (total - synced) / rate) : void 0;
|
|
5222
|
+
};
|
|
5223
|
+
return {
|
|
5224
|
+
update(task) {
|
|
5225
|
+
const at = now();
|
|
5226
|
+
const state = task.status ?? "";
|
|
5227
|
+
const line = describeBuildProgress(task, at - start, eta(task, at));
|
|
5228
|
+
if (out.isTTY) {
|
|
5229
|
+
out.write(`\r\x1B[2K${line}`);
|
|
5230
|
+
open = true;
|
|
5231
|
+
} else if (state !== lastState || line !== lastLine && at - lastLoggedAt >= LOG_EVERY_MS) {
|
|
5232
|
+
out.write(`${line}
|
|
5233
|
+
`);
|
|
5234
|
+
lastLoggedAt = at;
|
|
5235
|
+
}
|
|
5236
|
+
lastState = state;
|
|
5237
|
+
lastLine = line;
|
|
5238
|
+
},
|
|
5239
|
+
end() {
|
|
5240
|
+
if (open) out.write("\n");
|
|
5241
|
+
open = false;
|
|
5242
|
+
}
|
|
5243
|
+
};
|
|
5244
|
+
}
|
|
5245
|
+
|
|
5246
|
+
// src/commands/vega.ts
|
|
5247
|
+
var int7 = (value) => {
|
|
4069
5248
|
const parsed = Number(value);
|
|
4070
5249
|
if (!Number.isSafeInteger(parsed)) {
|
|
4071
5250
|
throw new InputError(`expected an integer, received "${value}"`);
|
|
4072
5251
|
}
|
|
4073
5252
|
return parsed;
|
|
4074
5253
|
};
|
|
5254
|
+
var nonNegativeInt3 = (flag) => (value) => {
|
|
5255
|
+
const parsed = Number(value);
|
|
5256
|
+
if (!/^\d+$/.test(value) || !Number.isSafeInteger(parsed)) {
|
|
5257
|
+
throw new InputError(`${flag} must be an integer 0 or greater (got '${value}')`);
|
|
5258
|
+
}
|
|
5259
|
+
return parsed;
|
|
5260
|
+
};
|
|
5261
|
+
var seconds = (value) => {
|
|
5262
|
+
const parsed = Number(value);
|
|
5263
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) {
|
|
5264
|
+
throw new InputError(
|
|
5265
|
+
`--timeout must be a whole number of seconds (0 = no limit), received "${value}"`
|
|
5266
|
+
);
|
|
5267
|
+
}
|
|
5268
|
+
return parsed;
|
|
5269
|
+
};
|
|
5270
|
+
async function waitAndReport(cmd, wait) {
|
|
5271
|
+
const progress = buildProgressReporter();
|
|
5272
|
+
let task;
|
|
5273
|
+
try {
|
|
5274
|
+
task = await wait((t) => progress.update(t));
|
|
5275
|
+
} catch (err) {
|
|
5276
|
+
progress.end();
|
|
5277
|
+
if (err instanceof WaitTimeoutError) printJson(err.last, outputOptions(cmd));
|
|
5278
|
+
throw err;
|
|
5279
|
+
}
|
|
5280
|
+
progress.end();
|
|
5281
|
+
printJson(task, outputOptions(cmd));
|
|
5282
|
+
if (isBuildTaskUnsuccessful(task)) {
|
|
5283
|
+
const reason = task.error_msg;
|
|
5284
|
+
throw new Error(
|
|
5285
|
+
`BuildTask ${task.id} ended ${buildTaskState(task)}${typeof reason === "string" && reason ? `: ${reason}` : "."}`
|
|
5286
|
+
);
|
|
5287
|
+
}
|
|
5288
|
+
}
|
|
4075
5289
|
var expectedUpdateTime = (value) => {
|
|
4076
5290
|
const parsed = Number(value);
|
|
4077
5291
|
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
@@ -4115,6 +5329,12 @@ var parseJsonArray = (value, flag) => {
|
|
|
4115
5329
|
}
|
|
4116
5330
|
return parsed;
|
|
4117
5331
|
};
|
|
5332
|
+
var parseResourceProperties = (value) => parseJsonArray(value, "--schema-definition").map((property) => {
|
|
5333
|
+
if (typeof property.name !== "string" || property.name.length === 0) {
|
|
5334
|
+
throw new InputError("--schema-definition properties must have a non-empty string name");
|
|
5335
|
+
}
|
|
5336
|
+
return property;
|
|
5337
|
+
});
|
|
4118
5338
|
var healthCheckSchedule = (mode, cronExpr) => {
|
|
4119
5339
|
if (!mode) {
|
|
4120
5340
|
if (cronExpr) throw new InputError("a health-check cron expression requires enabled mode");
|
|
@@ -4255,7 +5475,7 @@ var semanticTaskSort = (raw) => {
|
|
|
4255
5475
|
}
|
|
4256
5476
|
return parsed.data;
|
|
4257
5477
|
};
|
|
4258
|
-
var
|
|
5478
|
+
var sortDirection2 = (raw) => {
|
|
4259
5479
|
if (raw === void 0) return void 0;
|
|
4260
5480
|
const parsed = SortDirection.safeParse(raw);
|
|
4261
5481
|
if (!parsed.success) {
|
|
@@ -4265,12 +5485,48 @@ var sortDirection = (raw) => {
|
|
|
4265
5485
|
}
|
|
4266
5486
|
return parsed.data;
|
|
4267
5487
|
};
|
|
5488
|
+
var connectorMode = (raw) => {
|
|
5489
|
+
if (raw === void 0) return void 0;
|
|
5490
|
+
const parsed = ConnectorMode.safeParse(raw);
|
|
5491
|
+
if (!parsed.success) {
|
|
5492
|
+
throw new InputError(
|
|
5493
|
+
`invalid connector mode "${raw}"; expected one of ${ConnectorMode.options.join(", ")}`
|
|
5494
|
+
);
|
|
5495
|
+
}
|
|
5496
|
+
return parsed.data;
|
|
5497
|
+
};
|
|
5498
|
+
var connectorCategory = (raw) => {
|
|
5499
|
+
if (raw === void 0) return void 0;
|
|
5500
|
+
const parsed = ConnectorCategory.safeParse(raw);
|
|
5501
|
+
if (!parsed.success) {
|
|
5502
|
+
throw new InputError(
|
|
5503
|
+
`invalid connector category "${raw}"; expected one of ${ConnectorCategory.options.join(", ")}`
|
|
5504
|
+
);
|
|
5505
|
+
}
|
|
5506
|
+
return parsed.data;
|
|
5507
|
+
};
|
|
4268
5508
|
function vegaCommand() {
|
|
4269
|
-
const vega = new
|
|
5509
|
+
const vega = new Command16("vega").description(
|
|
4270
5510
|
"Data sources: catalogs, connectors, SQL, index builds"
|
|
4271
5511
|
);
|
|
4272
5512
|
const catalog = vega.command("catalog").description("Catalog entries");
|
|
4273
|
-
catalog.command("list").description("List catalog entries").option("--limit <n>", "page size",
|
|
5513
|
+
catalog.command("list").description("List catalog entries").option("--limit <n>", "page size", int7, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int7, 0).option("--name <s>", "filter by name").option("--tag <s>", "filter by tag").option(
|
|
5514
|
+
"--type <type>",
|
|
5515
|
+
"filter by catalog type: physical | logical",
|
|
5516
|
+
oneOf("--type", ["physical", "logical"])
|
|
5517
|
+
).option("--connector-type <type>", "filter by connector type").option("--enabled <bool>", "filter by enabled state: true | false", bool).option(
|
|
5518
|
+
"--health-check-status <s>",
|
|
5519
|
+
`filter by health status: ${CatalogHealthCheckStatus.options.join(" | ")}`,
|
|
5520
|
+
oneOf("--health-check-status", CatalogHealthCheckStatus.options)
|
|
5521
|
+
).option(
|
|
5522
|
+
"--sort <field>",
|
|
5523
|
+
"sort field: name | create_time | update_time",
|
|
5524
|
+
oneOf("--sort", ["name", "create_time", "update_time"])
|
|
5525
|
+
).option(
|
|
5526
|
+
"--direction <dir>",
|
|
5527
|
+
"sort direction: asc | desc",
|
|
5528
|
+
oneOf("--direction", SortDirection.options)
|
|
5529
|
+
).action(async (_opts, cmd) => {
|
|
4274
5530
|
const o = cmd.optsWithGlobals();
|
|
4275
5531
|
const data = await clientFrom(cmd).vega.catalogs({
|
|
4276
5532
|
limit: o.limit,
|
|
@@ -4279,7 +5535,7 @@ function vegaCommand() {
|
|
|
4279
5535
|
tag: o.tag,
|
|
4280
5536
|
type: o.type,
|
|
4281
5537
|
connectorType: o.connectorType,
|
|
4282
|
-
enabled: o.enabled
|
|
5538
|
+
enabled: o.enabled,
|
|
4283
5539
|
healthCheckStatus: o.healthCheckStatus,
|
|
4284
5540
|
sort: o.sort,
|
|
4285
5541
|
direction: o.direction
|
|
@@ -4289,7 +5545,21 @@ function vegaCommand() {
|
|
|
4289
5545
|
catalog.command("get <id>").description("Get a catalog by id").action(async (id, _opts, cmd) => {
|
|
4290
5546
|
printJson(await clientFrom(cmd).vega.getCatalog(id), outputOptions(cmd));
|
|
4291
5547
|
});
|
|
4292
|
-
catalog.command("
|
|
5548
|
+
catalog.command("stats").description("Count visible catalogs by catalog and connector type").option("--name <s>", "filter by catalog name before aggregation").action(async (opts, cmd) => {
|
|
5549
|
+
printJson(
|
|
5550
|
+
await clientFrom(cmd).vega.catalogConnectorTypeStats({ name: opts.name }),
|
|
5551
|
+
outputOptions(cmd)
|
|
5552
|
+
);
|
|
5553
|
+
});
|
|
5554
|
+
catalog.command("resources <id>").description("List resources under a catalog").option(
|
|
5555
|
+
"--category <c>",
|
|
5556
|
+
`filter by category: ${ResourceCategory.options.join(" | ")}`,
|
|
5557
|
+
oneOf("--category", ResourceCategory.options)
|
|
5558
|
+
).option(
|
|
5559
|
+
"--limit <n>",
|
|
5560
|
+
`page size (default ${DEFAULT_LIST_LIMIT}); page with --offset against total_count`,
|
|
5561
|
+
int7
|
|
5562
|
+
).option("--offset <n>", "page offset", nonNegativeInt3("--offset"), 0).action(async (id, opts, cmd) => {
|
|
4293
5563
|
printJson(
|
|
4294
5564
|
await clientFrom(cmd).vega.catalogResources(id, opts.category, opts.limit, opts.offset),
|
|
4295
5565
|
outputOptions(cmd)
|
|
@@ -4298,8 +5568,16 @@ function vegaCommand() {
|
|
|
4298
5568
|
catalog.command("health <id>").description("Health-status for a catalog").action(async (id, _opts, cmd) => {
|
|
4299
5569
|
printJson(await clientFrom(cmd).vega.catalogHealth(id), outputOptions(cmd));
|
|
4300
5570
|
});
|
|
4301
|
-
catalog.command("create").description("Create a catalog (data source)").requiredOption("--name <s>", "catalog name").
|
|
4302
|
-
|
|
5571
|
+
catalog.command("create").description("Create a catalog (data source)").requiredOption("--name <s>", "catalog name").option("--connector-type <s>", "connector type (e.g. mysql); required unless --built-in").option("--connector-config <json>", "connector config JSON; not allowed with --built-in").option("--id <id>", "explicit catalog id").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--enabled", "create enabled (default: disabled)").option("--built-in", "create a built-in (logical) catalog, with no connector").option("--allow-unhealthy", "save the catalog when its connection test fails").option("--health-check-mode <mode>", "health schedule: inherit | enabled | disabled").option("--health-check-cron <expr>", "cron expression for enabled health checks").action(async (opts, cmd) => {
|
|
5572
|
+
if (opts.builtIn && (opts.connectorType || opts.connectorConfig)) {
|
|
5573
|
+
throw new InputError(
|
|
5574
|
+
"--built-in creates a logical catalog: omit --connector-type and --connector-config"
|
|
5575
|
+
);
|
|
5576
|
+
}
|
|
5577
|
+
if (!opts.builtIn && !opts.connectorType) {
|
|
5578
|
+
throw new InputError("--connector-type is required unless --built-in");
|
|
5579
|
+
}
|
|
5580
|
+
const connectorConfig = opts.connectorConfig === void 0 ? void 0 : parseJsonObject(opts.connectorConfig, "--connector-config");
|
|
4303
5581
|
printJson(
|
|
4304
5582
|
await clientFrom(cmd).vega.createCatalog(
|
|
4305
5583
|
{
|
|
@@ -4309,8 +5587,8 @@ function vegaCommand() {
|
|
|
4309
5587
|
connectorConfig,
|
|
4310
5588
|
tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
|
|
4311
5589
|
description: opts.description,
|
|
4312
|
-
enabled: opts.enabled
|
|
4313
|
-
|
|
5590
|
+
enabled: Boolean(opts.enabled),
|
|
5591
|
+
builtIn: opts.builtIn ? true : void 0,
|
|
4314
5592
|
healthCheckSchedule: healthCheckSchedule(opts.healthCheckMode, opts.healthCheckCron)
|
|
4315
5593
|
},
|
|
4316
5594
|
{ allowUnhealthy: opts.allowUnhealthy ? true : void 0 }
|
|
@@ -4318,11 +5596,22 @@ function vegaCommand() {
|
|
|
4318
5596
|
outputOptions(cmd)
|
|
4319
5597
|
);
|
|
4320
5598
|
});
|
|
4321
|
-
catalog.command("update <id>").description(
|
|
5599
|
+
catalog.command("update <id>").description(
|
|
5600
|
+
"Update a catalog; fields you leave out keep their current values (read, then full PUT)"
|
|
5601
|
+
).option("--name <s>", "catalog name").option("--connector-type <s>", "connector type").option("--enabled <bool>", "current enabled state (must match; use enable/disable)", bool).option("--connector-config <json>", "connector config JSON (sent only when given)").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option(
|
|
4322
5602
|
"--expected-update-time <ms>",
|
|
4323
|
-
"optimistic-lock update time",
|
|
5603
|
+
"optimistic-lock update time (default: the update_time read before the PUT)",
|
|
4324
5604
|
expectedUpdateTime
|
|
4325
5605
|
).option("--allow-unhealthy", "save the update when its connection test fails").action(async (id, opts, cmd) => {
|
|
5606
|
+
const hasPatch = [
|
|
5607
|
+
opts.name,
|
|
5608
|
+
opts.connectorType,
|
|
5609
|
+
opts.enabled,
|
|
5610
|
+
opts.connectorConfig,
|
|
5611
|
+
opts.tags,
|
|
5612
|
+
opts.description
|
|
5613
|
+
].some((value) => value !== void 0);
|
|
5614
|
+
if (!hasPatch) throw new InputError("provide at least one catalog field to update");
|
|
4326
5615
|
const connectorConfig = opts.connectorConfig ? parseJsonObject(opts.connectorConfig, "--connector-config") : void 0;
|
|
4327
5616
|
printJson(
|
|
4328
5617
|
await clientFrom(cmd).vega.updateCatalog(
|
|
@@ -4390,7 +5679,7 @@ function vegaCommand() {
|
|
|
4390
5679
|
);
|
|
4391
5680
|
});
|
|
4392
5681
|
const discoverSchedule = vega.command("discover-schedule").description("Resource discovery schedules");
|
|
4393
|
-
discoverSchedule.command("list").description("List discovery schedules").option("--name <s>", "filter by name").option("--catalog-id <id>", "filter by catalog id").option("--enabled <bool>", "filter by enabled state", bool).option("--limit <n>", "page size",
|
|
5682
|
+
discoverSchedule.command("list").description("List discovery schedules").option("--name <s>", "filter by name").option("--catalog-id <id>", "filter by catalog id").option("--enabled <bool>", "filter by enabled state", bool).option("--limit <n>", "page size", int7, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int7, 0).option("--sort <field>", "name | create_time | update_time | next_run").option("--direction <dir>", "asc | desc").action(async (opts, cmd) => {
|
|
4394
5683
|
printJson(
|
|
4395
5684
|
await clientFrom(cmd).vega.discoverSchedules({
|
|
4396
5685
|
name: opts.name,
|
|
@@ -4399,7 +5688,7 @@ function vegaCommand() {
|
|
|
4399
5688
|
limit: opts.limit,
|
|
4400
5689
|
offset: opts.offset,
|
|
4401
5690
|
sort: discoverScheduleSort(opts.sort),
|
|
4402
|
-
direction:
|
|
5691
|
+
direction: sortDirection2(opts.direction)
|
|
4403
5692
|
}),
|
|
4404
5693
|
outputOptions(cmd)
|
|
4405
5694
|
);
|
|
@@ -4407,7 +5696,7 @@ function vegaCommand() {
|
|
|
4407
5696
|
discoverSchedule.command("get <id>").description("Get a discovery schedule").action(async (id, _opts, cmd) => {
|
|
4408
5697
|
printJson(await clientFrom(cmd).vega.getDiscoverSchedule(id), outputOptions(cmd));
|
|
4409
5698
|
});
|
|
4410
|
-
discoverSchedule.command("create").description("Create a discovery schedule").requiredOption("--name <s>", "schedule name").requiredOption("--catalog-id <id>", "catalog id").requiredOption("--cron <expr>", "five-field cron expression").option("--start-time <ms>", "start time",
|
|
5699
|
+
discoverSchedule.command("create").description("Create a discovery schedule").requiredOption("--name <s>", "schedule name").requiredOption("--catalog-id <id>", "catalog id").requiredOption("--cron <expr>", "five-field cron expression").option("--start-time <ms>", "start time (0 = no lower bound)", nonNegativeInt3("--start-time")).option("--end-time <ms>", "end time (0 = no upper bound)", nonNegativeInt3("--end-time")).option("--enabled", "create enabled").option("--strategy <strategy>", `strategy: ${DiscoverStrategy.options.join(" | ")}`).action(async (opts, cmd) => {
|
|
4411
5700
|
printJson(
|
|
4412
5701
|
await clientFrom(cmd).vega.createDiscoverSchedule({
|
|
4413
5702
|
name: opts.name,
|
|
@@ -4421,7 +5710,15 @@ function vegaCommand() {
|
|
|
4421
5710
|
outputOptions(cmd)
|
|
4422
5711
|
);
|
|
4423
5712
|
});
|
|
4424
|
-
discoverSchedule.command("update <id>").description("Fully update a discovery schedule").requiredOption("--name <s>", "schedule name").requiredOption("--catalog-id <id>", "current catalog id").requiredOption("--cron <expr>", "five-field cron expression").requiredOption("--enabled <bool>", "current enabled state", bool).requiredOption(
|
|
5713
|
+
discoverSchedule.command("update <id>").description("Fully update a discovery schedule").requiredOption("--name <s>", "schedule name").requiredOption("--catalog-id <id>", "current catalog id").requiredOption("--cron <expr>", "five-field cron expression").requiredOption("--enabled <bool>", "current enabled state", bool).requiredOption(
|
|
5714
|
+
"--start-time <ms>",
|
|
5715
|
+
"start time (0 = no lower bound)",
|
|
5716
|
+
nonNegativeInt3("--start-time")
|
|
5717
|
+
).requiredOption(
|
|
5718
|
+
"--end-time <ms>",
|
|
5719
|
+
"end time (0 = no upper bound)",
|
|
5720
|
+
nonNegativeInt3("--end-time")
|
|
5721
|
+
).requiredOption("--strategy <strategy>", `strategy: ${DiscoverStrategy.options.join(" | ")}`).requiredOption(
|
|
4425
5722
|
"--expected-update-time <ms>",
|
|
4426
5723
|
"optimistic-lock update time",
|
|
4427
5724
|
expectedUpdateTime
|
|
@@ -4448,7 +5745,7 @@ function vegaCommand() {
|
|
|
4448
5745
|
});
|
|
4449
5746
|
}
|
|
4450
5747
|
const discoverTask = vega.command("discover-task").description("Resource discovery tasks");
|
|
4451
|
-
discoverTask.command("list").description("List discovery tasks").option("--catalog-id <id>", "filter by catalog id").option("--resource-id <id>", "filter by resource id").option("--schedule-id <id>", "filter by schedule id").option("--status <status>", `comma-separated: ${VegaTaskStatus.options.join(" | ")}`).option("--strategy <strategy>", `strategy: ${DiscoverStrategy.options.join(" | ")}`).option("--trigger-type <type>", "manual | scheduled").option("--limit <n>", "page size",
|
|
5748
|
+
discoverTask.command("list").description("List discovery tasks").option("--catalog-id <id>", "filter by catalog id").option("--resource-id <id>", "filter by resource id").option("--schedule-id <id>", "filter by schedule id").option("--status <status>", `comma-separated: ${VegaTaskStatus.options.join(" | ")}`).option("--strategy <strategy>", `strategy: ${DiscoverStrategy.options.join(" | ")}`).option("--trigger-type <type>", "manual | scheduled").option("--limit <n>", "page size", int7, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int7, 0).option("--sort <field>", "create_time | start_time | finish_time | last_progress_time").option("--direction <dir>", "asc | desc").action(async (opts, cmd) => {
|
|
4452
5749
|
printJson(
|
|
4453
5750
|
await clientFrom(cmd).vega.discoverTasks({
|
|
4454
5751
|
catalogId: opts.catalogId,
|
|
@@ -4460,7 +5757,7 @@ function vegaCommand() {
|
|
|
4460
5757
|
limit: opts.limit,
|
|
4461
5758
|
offset: opts.offset,
|
|
4462
5759
|
sort: discoverTaskSort(opts.sort),
|
|
4463
|
-
direction:
|
|
5760
|
+
direction: sortDirection2(opts.direction)
|
|
4464
5761
|
}),
|
|
4465
5762
|
outputOptions(cmd)
|
|
4466
5763
|
);
|
|
@@ -4480,7 +5777,7 @@ function vegaCommand() {
|
|
|
4480
5777
|
semanticTask.command("list").description("List semantic-understanding tasks").option("--scope <scope>", `scope: ${SemanticUnderstandingScope.options.join(" | ")}`).option("--catalog-id <id>", "filter by catalog id").option("--resource-id <id>", "filter by resource id").option("--status <status>", `comma-separated: ${VegaTaskStatus.options.join(" | ")}`).option(
|
|
4481
5778
|
"--apply-mode <mode>",
|
|
4482
5779
|
`apply mode: ${SemanticUnderstandingApplyMode.options.join(" | ")}`
|
|
4483
|
-
).option("--applied <bool>", "filter by applied state", bool).option("--limit <n>", "page size",
|
|
5780
|
+
).option("--applied <bool>", "filter by applied state", bool).option("--limit <n>", "page size", int7, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int7, 0).option("--sort <field>", "create_time | start_time | finish_time").option("--direction <dir>", "asc | desc").action(async (opts, cmd) => {
|
|
4484
5781
|
printJson(
|
|
4485
5782
|
await clientFrom(cmd).vega.semanticUnderstandingTasks({
|
|
4486
5783
|
scope: semanticScope(opts.scope),
|
|
@@ -4492,12 +5789,12 @@ function vegaCommand() {
|
|
|
4492
5789
|
limit: opts.limit,
|
|
4493
5790
|
offset: opts.offset,
|
|
4494
5791
|
sort: semanticTaskSort(opts.sort),
|
|
4495
|
-
direction:
|
|
5792
|
+
direction: sortDirection2(opts.direction)
|
|
4496
5793
|
}),
|
|
4497
5794
|
outputOptions(cmd)
|
|
4498
5795
|
);
|
|
4499
5796
|
});
|
|
4500
|
-
semanticTask.command("create").description("Create a semantic-understanding task").requiredOption("--scope <scope>", "resource | catalog").option("--catalog-id <id>", "catalog id").option("--resource-id <id>", "resource id").option("--apply-mode <mode>", "dry_run | fill_empty | force").option("--confidence-threshold <n>", "minimum confidence (0..1)", confidenceThreshold).option("--include-sample-rows", "include resource sample rows").option("--sample-max-rows <n>", "sample row limit",
|
|
5797
|
+
semanticTask.command("create").description("Create a semantic-understanding task").requiredOption("--scope <scope>", "resource | catalog").option("--catalog-id <id>", "catalog id").option("--resource-id <id>", "resource id").option("--apply-mode <mode>", "dry_run | fill_empty | force").option("--confidence-threshold <n>", "minimum confidence (0..1)", confidenceThreshold).option("--include-sample-rows", "include resource sample rows").option("--sample-max-rows <n>", "sample row limit", int7).action(async (opts, cmd) => {
|
|
4501
5798
|
const scope = semanticScope(opts.scope);
|
|
4502
5799
|
if (!scope) throw new InputError("--scope is required");
|
|
4503
5800
|
const applyMode = semanticApplyMode(opts.applyMode);
|
|
@@ -4547,18 +5844,44 @@ function vegaCommand() {
|
|
|
4547
5844
|
);
|
|
4548
5845
|
});
|
|
4549
5846
|
const connector = vega.command("connector-type").description("Connector types");
|
|
4550
|
-
connector.command("list").description("List connector types").action(async (
|
|
4551
|
-
printJson(
|
|
5847
|
+
connector.command("list").description("List connector types").option("--name <s>", "filter by name").option("--tag <s>", "filter by tag").option("--mode <mode>", `runtime mode: ${ConnectorMode.options.join(" | ")}`).option("--category <category>", `category: ${ConnectorCategory.options.join(" | ")}`).option("--enabled <bool>", "filter by enabled state", bool).option("--available <bool>", "filter by runtime availability", bool).option("--limit <n>", "page size", int7, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int7, 0).option("--direction <dir>", `sort direction: ${SortDirection.options.join(" | ")}`).action(async (opts, cmd) => {
|
|
5848
|
+
printJson(
|
|
5849
|
+
await clientFrom(cmd).vega.connectorTypes({
|
|
5850
|
+
name: opts.name,
|
|
5851
|
+
tag: opts.tag,
|
|
5852
|
+
mode: connectorMode(opts.mode),
|
|
5853
|
+
category: connectorCategory(opts.category),
|
|
5854
|
+
enabled: opts.enabled,
|
|
5855
|
+
available: opts.available,
|
|
5856
|
+
limit: opts.limit,
|
|
5857
|
+
offset: opts.offset,
|
|
5858
|
+
direction: sortDirection2(opts.direction)
|
|
5859
|
+
}),
|
|
5860
|
+
outputOptions(cmd)
|
|
5861
|
+
);
|
|
4552
5862
|
});
|
|
4553
5863
|
connector.command("get <type>").description("Get a connector type").action(async (type, _opts, cmd) => {
|
|
4554
5864
|
printJson(await clientFrom(cmd).vega.connectorType(type), outputOptions(cmd));
|
|
4555
5865
|
});
|
|
5866
|
+
vega.command("index-capabilities").description(
|
|
5867
|
+
"List local-index analyzers and probe time (undocumented deploy extension; 404 where absent)"
|
|
5868
|
+
).action(async (_opts, cmd) => {
|
|
5869
|
+
printJson(await clientFrom(cmd).vega.indexCapabilities(), outputOptions(cmd));
|
|
5870
|
+
});
|
|
4556
5871
|
vega.command("sql").description(
|
|
4557
5872
|
"Read-only SQL straight against a data source \u2014 no knowledge network, no Trace record"
|
|
4558
5873
|
).option(
|
|
4559
5874
|
"--query <sql>",
|
|
4560
5875
|
"SQL string; reference a resource with a {{<resource-id>}} placeholder"
|
|
4561
|
-
).option(
|
|
5876
|
+
).option(
|
|
5877
|
+
"--input-dialect <dialect>",
|
|
5878
|
+
"SQL input dialect: postgres | mysql | trino | duckdb | tsql",
|
|
5879
|
+
oneOf("--input-dialect", ["postgres", "mysql", "trino", "duckdb", "tsql"])
|
|
5880
|
+
).option(
|
|
5881
|
+
"--paging-mode <mode>",
|
|
5882
|
+
"paging mode: single | cursor",
|
|
5883
|
+
oneOf("--paging-mode", ["single", "cursor"])
|
|
5884
|
+
).option("--limit <n>", "page size (cursor mode requires it)", int7).option("--offset <n>", "first-page offset", nonNegativeInt3("--offset")).option("--keep-alive-sec <s>", "cursor keep-alive in seconds (60\u20133600)", keepAliveSec).option("--cursor <cursor>", "opaque cursor returned by the previous page").option("--need-total", "include the complete total count").option("--query-timeout-sec <s>", "query timeout in seconds (1\u20133600)", int7).option(
|
|
4562
5885
|
"-d, --data <json>",
|
|
4563
5886
|
"full request body as JSON (advanced; wins over individual query flags)"
|
|
4564
5887
|
).action(async (opts, cmd) => {
|
|
@@ -4602,23 +5925,78 @@ function vegaCommand() {
|
|
|
4602
5925
|
printJson(await clientFrom(cmd).vega.sql(body), outputOptions(cmd));
|
|
4603
5926
|
});
|
|
4604
5927
|
const resource = vega.command("resource").description("Vega-backend resources");
|
|
4605
|
-
resource.command("list").description("List resources")
|
|
5928
|
+
addResourceListOptions(resource.command("list").description("List resources"), "--type").action(
|
|
5929
|
+
async (opts, cmd) => {
|
|
5930
|
+
printJson(
|
|
5931
|
+
await clientFrom(cmd).resource.list(resourceListOptionsFrom(opts)),
|
|
5932
|
+
outputOptions(cmd)
|
|
5933
|
+
);
|
|
5934
|
+
}
|
|
5935
|
+
);
|
|
5936
|
+
resource.command("get <id>").description("Get a resource").action(async (id, _opts, cmd) => {
|
|
5937
|
+
printJson(await clientFrom(cmd).resource.get(id), outputOptions(cmd));
|
|
5938
|
+
});
|
|
5939
|
+
resource.command("create").description("Create a dataset or logic-view resource").requiredOption("--catalog-id <id>", "catalog id").requiredOption("--name <s>", "resource name").requiredOption("--category <category>", "resource category: dataset | logicview").option("--id <id>", "explicit resource id").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--schema-definition <json>", "schema_definition JSON array").option("--index-config <json>", "index_config JSON object").option("--logic-definition <json>", "logic_definition JSON array").action(async (opts, cmd) => {
|
|
5940
|
+
if (opts.category !== "dataset" && opts.category !== "logicview") {
|
|
5941
|
+
throw new InputError("--category must be dataset or logicview");
|
|
5942
|
+
}
|
|
4606
5943
|
printJson(
|
|
4607
|
-
await clientFrom(cmd).resource.
|
|
5944
|
+
await clientFrom(cmd).resource.create({
|
|
5945
|
+
id: opts.id,
|
|
4608
5946
|
catalogId: opts.catalogId,
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
5947
|
+
name: opts.name,
|
|
5948
|
+
category: opts.category,
|
|
5949
|
+
...opts.tags !== void 0 ? { tags: csv(opts.tags) ?? [] } : {},
|
|
5950
|
+
description: opts.description,
|
|
5951
|
+
...opts.schemaDefinition !== void 0 ? {
|
|
5952
|
+
schemaDefinition: parseResourceProperties(opts.schemaDefinition)
|
|
5953
|
+
} : {},
|
|
5954
|
+
...opts.indexConfig !== void 0 ? {
|
|
5955
|
+
indexConfig: parseJsonObject(
|
|
5956
|
+
opts.indexConfig,
|
|
5957
|
+
"--index-config"
|
|
5958
|
+
)
|
|
5959
|
+
} : {},
|
|
5960
|
+
...opts.logicDefinition !== void 0 ? { logicDefinition: parseJsonArray(opts.logicDefinition, "--logic-definition") } : {}
|
|
4616
5961
|
}),
|
|
4617
5962
|
outputOptions(cmd)
|
|
4618
5963
|
);
|
|
4619
5964
|
});
|
|
4620
|
-
resource.command("
|
|
4621
|
-
|
|
5965
|
+
resource.command("update <id>").description("Update resource metadata, schema, features, or index configuration").option("--name <s>", "resource name").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--schema-definition <json>", "replacement schema_definition JSON array").option("--index-config <json>", "replacement index_config JSON object").option("--logic-definition <json>", "replacement logic_definition JSON array").option("--expected-update-time <ms>", "optimistic-lock update time", expectedUpdateTime).action(async (id, opts, cmd) => {
|
|
5966
|
+
const hasPatch = [
|
|
5967
|
+
opts.name,
|
|
5968
|
+
opts.tags,
|
|
5969
|
+
opts.description,
|
|
5970
|
+
opts.schemaDefinition,
|
|
5971
|
+
opts.indexConfig,
|
|
5972
|
+
opts.logicDefinition
|
|
5973
|
+
].some((value) => value !== void 0);
|
|
5974
|
+
if (!hasPatch) throw new InputError("provide at least one resource field to update");
|
|
5975
|
+
printJson(
|
|
5976
|
+
await clientFrom(cmd).resource.update(id, {
|
|
5977
|
+
name: opts.name,
|
|
5978
|
+
...opts.tags !== void 0 ? { tags: csv(opts.tags) ?? [] } : {},
|
|
5979
|
+
description: opts.description,
|
|
5980
|
+
...opts.schemaDefinition !== void 0 ? {
|
|
5981
|
+
schemaDefinition: parseResourceProperties(opts.schemaDefinition)
|
|
5982
|
+
} : {},
|
|
5983
|
+
...opts.indexConfig !== void 0 ? {
|
|
5984
|
+
indexConfig: parseJsonObject(
|
|
5985
|
+
opts.indexConfig,
|
|
5986
|
+
"--index-config"
|
|
5987
|
+
)
|
|
5988
|
+
} : {},
|
|
5989
|
+
...opts.logicDefinition !== void 0 ? { logicDefinition: parseJsonArray(opts.logicDefinition, "--logic-definition") } : {},
|
|
5990
|
+
expectedUpdateTime: opts.expectedUpdateTime
|
|
5991
|
+
}),
|
|
5992
|
+
outputOptions(cmd)
|
|
5993
|
+
);
|
|
5994
|
+
});
|
|
5995
|
+
resource.command("delete <ids...>").description("Delete one or more resources").option("--ignore-missing", "ignore missing resource ids").action(async (ids, opts, cmd) => {
|
|
5996
|
+
printJson(
|
|
5997
|
+
await clientFrom(cmd).resource.delete(ids, { ignoreMissing: opts.ignoreMissing }),
|
|
5998
|
+
outputOptions(cmd)
|
|
5999
|
+
);
|
|
4622
6000
|
});
|
|
4623
6001
|
resource.command("discover <id>").description("Trigger metadata discovery for a resource").action(async (id, _opts, cmd) => {
|
|
4624
6002
|
printJson(await clientFrom(cmd).vega.discoverResource(id), outputOptions(cmd));
|
|
@@ -4630,93 +6008,119 @@ function vegaCommand() {
|
|
|
4630
6008
|
printJson(result, outputOptions(cmd));
|
|
4631
6009
|
});
|
|
4632
6010
|
}
|
|
4633
|
-
|
|
6011
|
+
addResourceQueryOptions(
|
|
6012
|
+
resource.command("query <id>").description(`Fetch data rows from a resource (default limit ${DEFAULT_QUERY_LIMIT})`)
|
|
6013
|
+
).action(async (id, opts, cmd) => {
|
|
4634
6014
|
printJson(
|
|
4635
|
-
await clientFrom(cmd).resource.query(id,
|
|
6015
|
+
await clientFrom(cmd).resource.query(id, resourceQueryOptionsFrom(opts, DEFAULT_QUERY_LIMIT)),
|
|
4636
6016
|
outputOptions(cmd)
|
|
4637
6017
|
);
|
|
4638
6018
|
});
|
|
4639
|
-
resource.command("document-get <resource-id> <document-
|
|
6019
|
+
resource.command("document-get <resource-id> <document-ids...>").description("Get dataset documents by id").option("--ignore-missing", "Skip missing documents").action(async (resourceId, documentIds, opts, cmd) => {
|
|
4640
6020
|
printJson(
|
|
4641
|
-
await clientFrom(cmd).resource.
|
|
6021
|
+
await clientFrom(cmd).resource.getDocuments(resourceId, documentIds, {
|
|
6022
|
+
ignoreMissing: opts.ignoreMissing
|
|
6023
|
+
}),
|
|
4642
6024
|
outputOptions(cmd)
|
|
4643
6025
|
);
|
|
4644
6026
|
});
|
|
4645
|
-
resource.command("document-create <resource-id>").description("Create dataset
|
|
6027
|
+
resource.command("document-create <resource-id>").description("Create one dataset document").requiredOption(
|
|
4646
6028
|
"--data <json>",
|
|
4647
|
-
"JSON
|
|
6029
|
+
"Document JSON object \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (vega-backend)"
|
|
4648
6030
|
).action(async (resourceId, opts, cmd) => {
|
|
4649
6031
|
printJson(
|
|
4650
|
-
await clientFrom(cmd).resource.
|
|
6032
|
+
await clientFrom(cmd).resource.createDocument(
|
|
4651
6033
|
resourceId,
|
|
4652
|
-
|
|
6034
|
+
parseJsonObject(opts.data, "--data")
|
|
4653
6035
|
),
|
|
4654
6036
|
outputOptions(cmd)
|
|
4655
6037
|
);
|
|
4656
6038
|
});
|
|
4657
|
-
resource.command("document-upsert <resource-id>").description("Upsert dataset
|
|
6039
|
+
resource.command("document-upsert <resource-id> <docid>").description("Upsert one dataset document").requiredOption(
|
|
4658
6040
|
"--data <json>",
|
|
4659
|
-
"JSON
|
|
4660
|
-
).action(async (resourceId, opts, cmd) => {
|
|
4661
|
-
const documents = parseJsonArray(opts.data, "--data");
|
|
4662
|
-
if (documents.some((document) => typeof document.id !== "string")) {
|
|
4663
|
-
throw new InputError("every document in --data must have a string id");
|
|
4664
|
-
}
|
|
6041
|
+
"Document JSON object \u2014 docs: https://openbkn-ai.github.io/bkn-foundry/ (vega-backend)"
|
|
6042
|
+
).action(async (resourceId, docid, opts, cmd) => {
|
|
4665
6043
|
printJson(
|
|
4666
|
-
await clientFrom(cmd).resource.
|
|
6044
|
+
await clientFrom(cmd).resource.upsertDocument(
|
|
6045
|
+
resourceId,
|
|
6046
|
+
docid,
|
|
6047
|
+
parseJsonObject(opts.data, "--data")
|
|
6048
|
+
),
|
|
4667
6049
|
outputOptions(cmd)
|
|
4668
6050
|
);
|
|
4669
6051
|
});
|
|
4670
|
-
resource.command("document-delete <resource-id> <document-ids...>").description("Delete dataset documents by id").action(async (resourceId, documentIds,
|
|
6052
|
+
resource.command("document-delete <resource-id> <document-ids...>").description("Delete dataset documents by id").option("--ignore-missing", "Skip missing documents").action(async (resourceId, documentIds, opts, cmd) => {
|
|
4671
6053
|
printJson(
|
|
4672
|
-
await clientFrom(cmd).resource.deleteDocuments(resourceId, documentIds
|
|
6054
|
+
await clientFrom(cmd).resource.deleteDocuments(resourceId, documentIds, {
|
|
6055
|
+
ignoreMissing: opts.ignoreMissing
|
|
6056
|
+
}),
|
|
4673
6057
|
outputOptions(cmd)
|
|
4674
6058
|
);
|
|
4675
6059
|
});
|
|
4676
|
-
resource.command("document-delete-filter <resource-id>").description("Delete dataset documents by
|
|
4677
|
-
|
|
4678
|
-
|
|
6060
|
+
resource.command("document-delete-filter <resource-id>").description("Delete dataset documents by an equality selector or Vega filter condition").option("--filter <json>", "Vega filter_condition JSON object").option("--selector <json>", "JSON equality selector").action(async (resourceId, opts, cmd) => {
|
|
6061
|
+
if (Boolean(opts.filter) === Boolean(opts.selector)) {
|
|
6062
|
+
throw new InputError("exactly one of --filter or --selector is required");
|
|
6063
|
+
}
|
|
6064
|
+
const filter = parseJsonObject(
|
|
6065
|
+
opts.filter ?? opts.selector,
|
|
6066
|
+
opts.filter ? "--filter" : "--selector"
|
|
6067
|
+
);
|
|
6068
|
+
if (!Object.keys(filter).length) {
|
|
6069
|
+
throw new InputError(`${opts.filter ? "--filter" : "--selector"} must not be empty`);
|
|
6070
|
+
}
|
|
4679
6071
|
printJson(
|
|
4680
|
-
await clientFrom(cmd).resource.deleteDocumentsByFilter(resourceId, filter),
|
|
6072
|
+
await (opts.selector ? clientFrom(cmd).resource.deleteDocumentsBySelector(resourceId, filter) : clientFrom(cmd).resource.deleteDocumentsByFilter(resourceId, filter)),
|
|
4681
6073
|
outputOptions(cmd)
|
|
4682
6074
|
);
|
|
4683
6075
|
});
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
"
|
|
4687
|
-
"comma-separated key fields (batch: time; streaming: row id)"
|
|
6076
|
+
resource.command("build <resource-id>").description("Create a batch BuildTask from the resource's saved index configuration").option("--execute-type <type>", "batch execution type: incremental | full").option(
|
|
6077
|
+
"--wait",
|
|
6078
|
+
"wait for the build to end, with progress on stderr; exits non-zero unless it completes"
|
|
4688
6079
|
).option(
|
|
4689
|
-
"--
|
|
4690
|
-
"
|
|
4691
|
-
|
|
6080
|
+
"--timeout <s>",
|
|
6081
|
+
"with --wait: give up after this many seconds (0 = no limit)",
|
|
6082
|
+
seconds,
|
|
6083
|
+
300
|
|
6084
|
+
).action(async (resourceId, _opts, cmd) => {
|
|
4692
6085
|
const o = cmd.optsWithGlobals();
|
|
4693
|
-
const
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
fulltextFields,
|
|
4702
|
-
fulltextAnalyzer: o.fulltextAnalyzer
|
|
4703
|
-
});
|
|
6086
|
+
const req = {
|
|
6087
|
+
resource_id: resourceId,
|
|
6088
|
+
mode: "batch",
|
|
6089
|
+
execute_type: buildTaskExecuteType(o.executeType)
|
|
6090
|
+
};
|
|
6091
|
+
if (!o.wait) {
|
|
6092
|
+
printJson(await clientFrom(cmd).vega.build(req), outputOptions(cmd));
|
|
6093
|
+
return;
|
|
4704
6094
|
}
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
mode: o.mode,
|
|
4709
|
-
execute_type: o.executeType
|
|
4710
|
-
},
|
|
4711
|
-
{ wait: Boolean(o.wait), timeoutMs: o.timeout * 1e3 }
|
|
6095
|
+
await waitAndReport(
|
|
6096
|
+
cmd,
|
|
6097
|
+
(onProgress) => clientFrom(cmd).vega.build(req, { wait: true, timeoutMs: o.timeout * 1e3, onProgress })
|
|
4712
6098
|
);
|
|
4713
|
-
printJson(task, outputOptions(cmd));
|
|
4714
6099
|
});
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
6100
|
+
const buildTask = vega.command("build-task").description("Resource index BuildTasks");
|
|
6101
|
+
buildTask.command("get <task-id>").description("Show a BuildTask's state and progress").option(
|
|
6102
|
+
"--wait",
|
|
6103
|
+
"wait for the task to end, with progress on stderr; exits non-zero unless it completes"
|
|
6104
|
+
).option(
|
|
6105
|
+
"--timeout <s>",
|
|
6106
|
+
"with --wait: give up after this many seconds (0 = no limit)",
|
|
6107
|
+
seconds,
|
|
6108
|
+
300
|
|
6109
|
+
).action(async (taskId, opts, cmd) => {
|
|
6110
|
+
if (!opts.wait) {
|
|
6111
|
+
printJson(await clientFrom(cmd).vega.buildStatus(taskId), outputOptions(cmd));
|
|
6112
|
+
return;
|
|
6113
|
+
}
|
|
6114
|
+
await waitAndReport(
|
|
6115
|
+
cmd,
|
|
6116
|
+
(onProgress) => clientFrom(cmd).vega.waitForBuild(taskId, { timeoutMs: opts.timeout * 1e3, onProgress })
|
|
6117
|
+
);
|
|
4718
6118
|
});
|
|
4719
|
-
|
|
6119
|
+
buildTask.command("list").description("List BuildTasks").option("--limit <n>", "page size", int7, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int7, 0).option("--resource-id <id>", "filter by resource id").option("--catalog-id <id>", "filter by catalog id").option("--status <status>", `comma-separated statuses: ${BuildTaskStatus.options.join(" | ")}`).option(
|
|
6120
|
+
"--mode <mode>",
|
|
6121
|
+
`filter by mode: ${BuildMode.options.join(" | ")}`,
|
|
6122
|
+
oneOf("--mode", BuildMode.options)
|
|
6123
|
+
).option(
|
|
4720
6124
|
"--execute-type <type>",
|
|
4721
6125
|
`filter by execution type: ${BuildTaskExecuteType.options.join(" | ")}`
|
|
4722
6126
|
).option("--sort <field>", `sort field: ${BuildTaskSort.options.join(" | ")}`).option("--direction <dir>", `sort direction: ${SortDirection.options.join(" | ")}`).action(async (opts, cmd) => {
|
|
@@ -4730,21 +6134,21 @@ function vegaCommand() {
|
|
|
4730
6134
|
mode: opts.mode,
|
|
4731
6135
|
executeType: buildTaskExecuteType(opts.executeType),
|
|
4732
6136
|
sort: buildTaskSort(opts.sort),
|
|
4733
|
-
direction:
|
|
6137
|
+
direction: sortDirection2(opts.direction)
|
|
4734
6138
|
}),
|
|
4735
6139
|
outputOptions(cmd)
|
|
4736
6140
|
);
|
|
4737
6141
|
});
|
|
4738
|
-
|
|
6142
|
+
buildTask.command("start <task-id>").description("Start a BuildTask").option("--reset", "restart a full task from the beginning (rejected for incremental tasks)").action(async (taskId, opts, cmd) => {
|
|
4739
6143
|
printJson(
|
|
4740
6144
|
await clientFrom(cmd).vega.startBuildTask(taskId, { reset: opts.reset }),
|
|
4741
6145
|
outputOptions(cmd)
|
|
4742
6146
|
);
|
|
4743
6147
|
});
|
|
4744
|
-
|
|
6148
|
+
buildTask.command("stop <task-id>").description("Stop a BuildTask").action(async (taskId, _opts, cmd) => {
|
|
4745
6149
|
printJson(await clientFrom(cmd).vega.stopBuildTask(taskId), outputOptions(cmd));
|
|
4746
6150
|
});
|
|
4747
|
-
|
|
6151
|
+
buildTask.command("delete <ids...>").description("Delete one or more BuildTasks").option("--ignore-missing", "ignore missing task ids").action(async (ids, opts, cmd) => {
|
|
4748
6152
|
printJson(
|
|
4749
6153
|
await clientFrom(cmd).vega.deleteBuildTasks(ids, {
|
|
4750
6154
|
ignoreMissing: opts.ignoreMissing
|
|
@@ -4756,18 +6160,22 @@ function vegaCommand() {
|
|
|
4756
6160
|
GROUPS: [
|
|
4757
6161
|
"catalog",
|
|
4758
6162
|
"resource",
|
|
6163
|
+
"build-task",
|
|
4759
6164
|
"connector-type",
|
|
4760
|
-
"dataset",
|
|
4761
6165
|
"discover-schedule",
|
|
4762
6166
|
"discover-task",
|
|
4763
6167
|
"semantic-task"
|
|
4764
6168
|
],
|
|
6169
|
+
READ: ["index-capabilities"],
|
|
4765
6170
|
RUN: ["sql"]
|
|
4766
6171
|
});
|
|
4767
6172
|
groupChildren(resource, {
|
|
4768
6173
|
READ: ["list", "get", "document-get"],
|
|
4769
|
-
RUN: ["query", "discover"],
|
|
6174
|
+
RUN: ["query", "discover", "build"],
|
|
4770
6175
|
WRITE: [
|
|
6176
|
+
"create",
|
|
6177
|
+
"update",
|
|
6178
|
+
"delete",
|
|
4771
6179
|
"enable",
|
|
4772
6180
|
"disable",
|
|
4773
6181
|
"document-create",
|
|
@@ -4776,8 +6184,13 @@ function vegaCommand() {
|
|
|
4776
6184
|
"document-delete-filter"
|
|
4777
6185
|
]
|
|
4778
6186
|
});
|
|
6187
|
+
groupChildren(buildTask, {
|
|
6188
|
+
READ: ["list", "get"],
|
|
6189
|
+
RUN: ["start", "stop"],
|
|
6190
|
+
WRITE: ["delete"]
|
|
6191
|
+
});
|
|
4779
6192
|
groupChildren(catalog, {
|
|
4780
|
-
READ: ["list", "get", "resources", "health", "health-check-schedule"],
|
|
6193
|
+
READ: ["list", "get", "stats", "resources", "health", "health-check-schedule"],
|
|
4781
6194
|
RUN: ["test-connection", "test-connection-config", "discover"],
|
|
4782
6195
|
WRITE: ["create", "update", "enable", "disable", "delete", "set-health-check-schedule"]
|
|
4783
6196
|
});
|
|
@@ -4790,41 +6203,51 @@ function vegaCommand() {
|
|
|
4790
6203
|
QUERYING DIRECTLY
|
|
4791
6204
|
sql --query "<sql>" runs against the source itself. Name a resource with a
|
|
4792
6205
|
{{<resource-id>}} placeholder rather than the physical table it happens to have.
|
|
6206
|
+
resource query <id> reads rows through the resource: --filter, --sort, --output-fields,
|
|
6207
|
+
cursor paging, and --ignore-local-index to bypass a table's local index.
|
|
4793
6208
|
|
|
4794
6209
|
BUILDING AN INDEX
|
|
4795
|
-
|
|
4796
|
-
|
|
6210
|
+
resource update <resource-id> saves schema_definition and index_config. Then resource build
|
|
6211
|
+
<resource-id> creates a BuildTask; build-task get / list follow it.
|
|
6212
|
+
--wait (on resource build, or build-task get for an existing task) shows progress on stderr
|
|
6213
|
+
and exits non-zero unless the task completes. --timeout 0 waits without a limit.`
|
|
4797
6214
|
);
|
|
4798
6215
|
return group(vega, "DATA & KNOWLEDGE");
|
|
4799
6216
|
}
|
|
4800
6217
|
|
|
4801
6218
|
// src/cli-program.ts
|
|
4802
6219
|
function buildProgram() {
|
|
4803
|
-
const
|
|
4804
|
-
|
|
6220
|
+
const program = new Command17();
|
|
6221
|
+
program.name("openbkn").description(
|
|
4805
6222
|
"openbkn \u2014 one CLI for the BKN platform: knowledge networks, the data behind them,\nthe tools and skills agents run on them, and the traces they leave."
|
|
4806
|
-
).version(package_default.version, "-V, --version", "output the version number").option("--base-url <url>", "platform base URL (env: BKN_BASE_URL)").option("--token <value>", "access token (env: BKN_TOKEN)").option("--user <id|name>", "use specific user credentials (env: BKN_USER)").option("--json", "machine-readable JSON output").option("--compact", "single-line JSON output").option("--full", "human view: show all columns (default trims to the key ones)").option("--
|
|
6223
|
+
).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("--conversation-id <id>", "BKN Trace conversation id (env: BKN_CONVERSATION_ID)").option("--interaction-id <id>", "BKN Trace interaction id (env: BKN_INTERACTION_ID)").option(
|
|
4807
6224
|
"--new-conversation",
|
|
4808
6225
|
"ignore the remembered conversation for this command (see `openbkn context conversation`)"
|
|
4809
|
-
).option("-k, --insecure", "skip TLS verification (dev / self-signed only)").option(
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
6226
|
+
).option("-k, --insecure", "skip TLS verification (dev / self-signed only)").option(
|
|
6227
|
+
"--no-retry",
|
|
6228
|
+
"fail at once on a refused/dropped connection or a 429/502/503, instead of retrying 3 times"
|
|
6229
|
+
).option("--dry-run", "print the request this command would send, and send nothing").showHelpAfterError();
|
|
6230
|
+
program.addCommand(authCommand());
|
|
6231
|
+
program.addCommand(configCommand());
|
|
6232
|
+
program.addCommand(appkeyCommand());
|
|
6233
|
+
program.addCommand(bknCommand());
|
|
6234
|
+
program.addCommand(vegaCommand());
|
|
6235
|
+
program.addCommand(resourceCommand());
|
|
6236
|
+
program.addCommand(contextCommand());
|
|
6237
|
+
program.addCommand(modelCommand());
|
|
6238
|
+
program.addCommand(skillCommand());
|
|
6239
|
+
program.addCommand(mcpCommand());
|
|
6240
|
+
program.addCommand(sandboxCommand());
|
|
6241
|
+
program.addCommand(toolboxCommand());
|
|
6242
|
+
program.addCommand(functionToolCommand());
|
|
6243
|
+
program.addCommand(apiToolCommand());
|
|
6244
|
+
program.addCommand(toolCommand());
|
|
6245
|
+
program.addCommand(traceCommand());
|
|
6246
|
+
program.addCommand(adminCommand());
|
|
6247
|
+
program.addCommand(callCommand());
|
|
6248
|
+
program.addCommand(describeCommand(program));
|
|
4826
6249
|
guide(
|
|
4827
|
-
|
|
6250
|
+
program,
|
|
4828
6251
|
`FIRST STEPS
|
|
4829
6252
|
openbkn auth login https://your-platform -u <user> -p <pass>
|
|
4830
6253
|
openbkn bkn list # knowledge networks you can see
|
|
@@ -4837,13 +6260,16 @@ function buildProgram() {
|
|
|
4837
6260
|
context query-object-instance --args '<json>'
|
|
4838
6261
|
Look at the data vega catalog list -> resource find --name <t> -> resource query <id>
|
|
4839
6262
|
Build from a catalog bkn create-from-catalog <catalog-id> --name "<n>" ->
|
|
4840
|
-
vega
|
|
6263
|
+
vega resource build <resource-id>
|
|
4841
6264
|
Edit as files bkn pull <kn-id> ./kn -> bkn validate ./kn -> bkn push ./kn
|
|
4842
|
-
Ship
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
->
|
|
4846
|
-
|
|
6265
|
+
Ship an API toolbox create --name "<n>" --service-url <url> ->
|
|
6266
|
+
api import ./api.yaml --toolbox <box-id> ->
|
|
6267
|
+
api enable <tool-id> --toolbox <box-id> -> toolbox publish <box-id>
|
|
6268
|
+
-> api execute <tool-id> --toolbox <box-id>
|
|
6269
|
+
Ship some code sandbox run ./add.py -> toolbox create --name "<n>" --type function
|
|
6270
|
+
-> function create ./add.py --toolbox <box-id> --name add ->
|
|
6271
|
+
function enable <tool-id> --toolbox <box-id> ->
|
|
6272
|
+
toolbox publish <box-id> -> function execute <tool-id> --toolbox <box-id>
|
|
4847
6273
|
Debug an answer trace conversations list -> trace diagnose <conversation-id> --llm
|
|
4848
6274
|
|
|
4849
6275
|
GOOD TO KNOW
|
|
@@ -4855,12 +6281,31 @@ function buildProgram() {
|
|
|
4855
6281
|
--full widens it). Most list commands answer {entries, total_count}; anything else says
|
|
4856
6282
|
so in its own description. Ids come from list/search output \u2014 opaque, never guess one,
|
|
4857
6283
|
and the key holding one is not always \`id\` (\`skill_id\`, \`conversation_id\`, \`ot_id\` \u2026).
|
|
4858
|
-
|
|
6284
|
+
Saved logins are selected with --user; access follows the account's platform grants.
|
|
4859
6285
|
\`openbkn call\` reaches any endpoint a command does not cover, auth injected. Look the
|
|
4860
6286
|
path up at https://openbkn-ai.github.io/bkn-foundry/ first \u2014 do not guess one.`
|
|
4861
6287
|
);
|
|
4862
|
-
installGroupedHelp(
|
|
4863
|
-
return
|
|
6288
|
+
installGroupedHelp(program);
|
|
6289
|
+
return program;
|
|
6290
|
+
}
|
|
6291
|
+
|
|
6292
|
+
// src/cli-run.ts
|
|
6293
|
+
async function runCli(argv = process.argv) {
|
|
6294
|
+
const program = buildProgram();
|
|
6295
|
+
if (argv.includes("--dry-run")) enableDryRun();
|
|
6296
|
+
try {
|
|
6297
|
+
await program.parseAsync(argv);
|
|
6298
|
+
} catch (err) {
|
|
6299
|
+
if (err instanceof DryRunSignal) {
|
|
6300
|
+
process.stdout.write(`${JSON.stringify(err.request, null, 2)}
|
|
6301
|
+
`);
|
|
6302
|
+
return;
|
|
6303
|
+
}
|
|
6304
|
+
console.error(formatError(err));
|
|
6305
|
+
process.exitCode = toExitCode(err);
|
|
6306
|
+
} finally {
|
|
6307
|
+
await releaseLifecycleSessions();
|
|
6308
|
+
}
|
|
4864
6309
|
}
|
|
4865
6310
|
|
|
4866
6311
|
// src/cli.ts
|
|
@@ -4868,21 +6313,5 @@ process.stdout.on("error", (err) => {
|
|
|
4868
6313
|
if (err.code === "EPIPE") process.exit(0);
|
|
4869
6314
|
throw err;
|
|
4870
6315
|
});
|
|
4871
|
-
|
|
4872
|
-
var argv = process.argv.map((a) => a === "-bd" ? "--biz-domain" : a);
|
|
4873
|
-
if (argv.includes("--dry-run")) enableDryRun();
|
|
4874
|
-
try {
|
|
4875
|
-
await program.parseAsync(argv);
|
|
4876
|
-
} catch (err) {
|
|
4877
|
-
if (err instanceof DryRunSignal) {
|
|
4878
|
-
process.stdout.write(`${JSON.stringify(err.request, null, 2)}
|
|
4879
|
-
`);
|
|
4880
|
-
await releaseLifecycleSessions();
|
|
4881
|
-
process.exit(0);
|
|
4882
|
-
}
|
|
4883
|
-
console.error(formatError(err));
|
|
4884
|
-
await releaseLifecycleSessions();
|
|
4885
|
-
process.exit(toExitCode(err));
|
|
4886
|
-
}
|
|
4887
|
-
await releaseLifecycleSessions();
|
|
6316
|
+
await runCli();
|
|
4888
6317
|
//# sourceMappingURL=cli.js.map
|