@openbkn/bkn-sdk 0.1.2 → 0.1.3

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/dist/cli.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  activePlatform,
9
9
  attachToken,
10
10
  changePasswordSafe,
11
+ classifyPath,
11
12
  createClient,
12
13
  credentialDeviceLogin,
13
14
  currentToken,
@@ -16,9 +17,11 @@ import {
16
17
  deletePlatform,
17
18
  deviceLogin,
18
19
  exportCreds,
20
+ filesUnder,
19
21
  formatError,
20
22
  getUserSafe,
21
23
  isHeadless,
24
+ lifecycleHint,
22
25
  listPlatforms,
23
26
  logout,
24
27
  openBrowser,
@@ -26,7 +29,9 @@ import {
26
29
  parsePkMap,
27
30
  rawCall,
28
31
  readPlatformConfig,
32
+ releaseLifecycleSessions,
29
33
  renderReportMarkdown,
34
+ renderTree,
30
35
  resolveContext,
31
36
  setActivePlatform,
32
37
  status,
@@ -36,7 +41,7 @@ import {
36
41
  validateFixturePath,
37
42
  whoami,
38
43
  writePlatformConfig
39
- } from "./chunk-LH3ONZGQ.js";
44
+ } from "./chunk-PC2F54XD.js";
40
45
 
41
46
  // src/cli.ts
42
47
  import { Command as Command17 } from "commander";
@@ -44,12 +49,12 @@ import { Command as Command17 } from "commander";
44
49
  // package.json
45
50
  var package_default = {
46
51
  name: "@openbkn/bkn-sdk",
47
- version: "0.1.2",
52
+ version: "0.1.3",
48
53
  description: "Unified TypeScript SDK + CLI for the BKN (Business Knowledge Network) platform.",
49
54
  type: "module",
50
55
  license: "Apache-2.0",
51
56
  engines: {
52
- node: ">=18"
57
+ node: ">=22.19.0"
53
58
  },
54
59
  bin: {
55
60
  openbkn: "./dist/cli.js"
@@ -89,9 +94,9 @@ var package_default = {
89
94
  chalk: "^5.4.1",
90
95
  commander: "^13.1.0",
91
96
  "csv-parse": "^6.2.1",
92
- "js-yaml": "^4.2.0",
97
+ "js-yaml": "^4.3.0",
93
98
  jszip: "^3.10.1",
94
- undici: "^8.7.0",
99
+ undici: "^8.9.0",
95
100
  zod: "^3.24.1"
96
101
  },
97
102
  devDependencies: {
@@ -255,8 +260,7 @@ var NOISE_COLS = /* @__PURE__ */ new Set([
255
260
  "status_message",
256
261
  "last_check_time",
257
262
  "last_discover_status",
258
- "health_check_result",
259
- "health_check_enabled"
263
+ "health_check_result"
260
264
  ]);
261
265
  var isNoiseCol = (c) => NOISE_COLS.has(c) || /_time$/.test(c);
262
266
  var isKeyCol = (c) => /^(id|name|key|title|label)$/i.test(c) || /_(id|name|key)$/i.test(c) || /^(status|state|type|category|mode|enabled|version|branch)$/i.test(c);
@@ -1610,7 +1614,11 @@ function callCommand() {
1610
1614
  process.stdout.write(res.body.endsWith("\n") ? res.body : `${res.body}
1611
1615
  `);
1612
1616
  }
1613
- if (res.status >= 400) process.exitCode = 1;
1617
+ if (res.status >= 400) {
1618
+ const hint = lifecycleHint(res.body);
1619
+ if (hint) console.error(hint);
1620
+ process.exitCode = 1;
1621
+ }
1614
1622
  });
1615
1623
  return group(cmd, "AUTHENTICATION & CONFIG");
1616
1624
  }
@@ -2158,6 +2166,29 @@ function resourceCommand() {
2158
2166
  // src/commands/skill.ts
2159
2167
  import { Command as Command13 } from "commander";
2160
2168
  var int10 = (v) => Number.parseInt(v, 10);
2169
+ var positiveInt = (flag) => (v) => {
2170
+ if (!/^\d+$/.test(v)) {
2171
+ throw new InputError(`${flag} must be a positive integer (got '${v}')`);
2172
+ }
2173
+ const n = Number.parseInt(v, 10);
2174
+ if (!Number.isSafeInteger(n) || n <= 0) {
2175
+ throw new InputError(`${flag} must be a positive integer (got '${v}')`);
2176
+ }
2177
+ return n;
2178
+ };
2179
+ var MOCKED_EXIT_CODE = 125;
2180
+ function sandboxExitCode(result) {
2181
+ if (result?.mocked) return MOCKED_EXIT_CODE;
2182
+ const code = result?.exit_code ?? 0;
2183
+ if (!Number.isSafeInteger(code) || code < 0) return 1;
2184
+ return code > 255 ? 1 : code;
2185
+ }
2186
+ var SKILL_SOURCES = ["custom", "internal"];
2187
+ function checkSource(source) {
2188
+ if (source === void 0 || SKILL_SOURCES.includes(source)) return source;
2189
+ throw new InputError(`--source must be one of: ${SKILL_SOURCES.join(" | ")} (got '${source}')`);
2190
+ }
2191
+ var draftOption = (c) => c.option("--draft", "read the draft (management) version instead of the published one");
2161
2192
  function skillCommand() {
2162
2193
  const cmd = new Command13("skill").description("Skill registry and market");
2163
2194
  const listOpts = (c) => c.option("--name <s>", "filter by name").option("--source <s>", "filter by source").option("--status <s>", "filter by status").option("--limit <n>", "page size", int10, DEFAULT_LIST_LIMIT).option("--page <n>", "page", int10, 1);
@@ -2196,11 +2227,97 @@ function skillCommand() {
2196
2227
  cmd.command("delete <skill-id>").description("Delete a skill").action(async (id, _opts, cmd2) => {
2197
2228
  printJson(await clientFrom(cmd2).skills.delete(id), outputOptions(cmd2));
2198
2229
  });
2199
- cmd.command("content <skill-id>").description("Read a skill's SKILL.md content index").action(async (id, _opts, cmd2) => {
2200
- printJson(await clientFrom(cmd2).skills.content(id), outputOptions(cmd2));
2230
+ draftOption(cmd.command("content <skill-id>")).description("Read a skill's SKILL.md content index").option("--raw", "write SKILL.md's own text instead of the index JSON").action(async (id, opts, cmd2) => {
2231
+ const skills = clientFrom(cmd2).skills;
2232
+ if (opts.raw) {
2233
+ process.stdout.write(await skills.contentRaw(id, { draft: opts.draft }));
2234
+ return;
2235
+ }
2236
+ printJson(await skills.content(id, { draft: opts.draft }), outputOptions(cmd2));
2237
+ });
2238
+ draftOption(cmd.command("read-file <skill-id> <rel-path>")).description("Read a file inside a skill (progressive)").option("--raw", "write the file's own text instead of the response JSON").action(async (id, relPath, opts, cmd2) => {
2239
+ const skills = clientFrom(cmd2).skills;
2240
+ if (opts.raw) {
2241
+ process.stdout.write(await skills.readFileRaw(id, relPath, { draft: opts.draft }));
2242
+ return;
2243
+ }
2244
+ printJson(await skills.readFile(id, relPath, { draft: opts.draft }), outputOptions(cmd2));
2245
+ });
2246
+ draftOption(cmd.command("files <skill-id> [path]")).description("List a skill's files (one level; --tree for the whole hierarchy)").option("--tree", "render the full hierarchy instead of one level").action(async (id, path, opts, cmd2) => {
2247
+ const skills = clientFrom(cmd2).skills;
2248
+ const out = outputOptions(cmd2);
2249
+ if (opts.tree) {
2250
+ const all = await skills.fileManifest(id, { draft: opts.draft });
2251
+ if (path !== void 0) {
2252
+ const kind = classifyPath(all, path);
2253
+ if (kind === "file")
2254
+ throw new InputError(`'${path}' is a file \u2014 use \`skill read-file\`.`);
2255
+ if (kind === "missing") throw new InputError(`'${path}' not found in skill ${id}.`);
2256
+ }
2257
+ const files = filesUnder(all, path);
2258
+ const bytes = files.reduce((sum, f) => sum + (f.size ?? 0), 0);
2259
+ if (out.json || out.compact) {
2260
+ printJson(
2261
+ {
2262
+ skillId: id,
2263
+ path: path ?? "",
2264
+ files: files.map((f) => ({
2265
+ relPath: f.rel_path,
2266
+ fileType: f.file_type,
2267
+ size: f.size,
2268
+ mime: f.mime_type
2269
+ })),
2270
+ totalFiles: files.length,
2271
+ totalSize: bytes
2272
+ },
2273
+ out
2274
+ );
2275
+ return;
2276
+ }
2277
+ process.stdout.write(`${renderTree(files)}
2278
+
2279
+ ${files.length} files, ${bytes} B
2280
+ `);
2281
+ return;
2282
+ }
2283
+ const listing = await skills.files(id, path, { draft: opts.draft });
2284
+ if (out.json || out.compact) {
2285
+ printJson(listing, out);
2286
+ return;
2287
+ }
2288
+ printJson(
2289
+ listing.entries.map(
2290
+ (e) => e.type === "dir" ? { name: `${e.name}/`, type: "dir", size: e.size, mime: "" } : { name: e.name, type: e.fileType ?? "file", size: e.size, mime: e.mime ?? "" }
2291
+ ),
2292
+ out
2293
+ );
2294
+ process.stdout.write(
2295
+ `${listing.entries.length} entries here; ${listing.totalFiles} files, ${listing.totalSize} B below
2296
+ `
2297
+ );
2298
+ });
2299
+ cmd.command("names <ids...>").description("Resolve skill ids to names (unknown ids are skipped)").action(async (ids, _opts, cmd2) => {
2300
+ printJson(await clientFrom(cmd2).skills.names(ids), outputOptions(cmd2));
2201
2301
  });
2202
- cmd.command("read-file <skill-id> <rel-path>").description("Read a file inside a skill (progressive)").action(async (id, relPath, _opts, cmd2) => {
2203
- printJson(await clientFrom(cmd2).skills.readFile(id, relPath), outputOptions(cmd2));
2302
+ cmd.command("execute <skill-id>").description("Run a skill in the platform sandbox").requiredOption("--entry <shell>", "shell command to run inside the skill's work dir").option(
2303
+ "--timeout <seconds>",
2304
+ "sandbox time limit (the sandbox's own limit when omitted)",
2305
+ positiveInt("--timeout")
2306
+ ).option("--raw", "write the run's stdout/stderr straight through").option("--exit-code", "exit with the sandbox's exit code").action(async (id, opts, cmd2) => {
2307
+ const result = await clientFrom(cmd2).skills.execute(id, {
2308
+ entryShell: opts.entry,
2309
+ timeout: opts.timeout
2310
+ });
2311
+ if (result?.mocked) {
2312
+ process.stderr.write("warning: sandbox reported mocked=true \u2014 the skill did not run\n");
2313
+ }
2314
+ if (opts.raw) {
2315
+ if (result?.stdout) process.stdout.write(result.stdout);
2316
+ if (result?.stderr) process.stderr.write(result.stderr);
2317
+ } else {
2318
+ printJson(result, outputOptions(cmd2));
2319
+ }
2320
+ if (opts.exitCode) process.exitCode = sandboxExitCode(result);
2204
2321
  });
2205
2322
  cmd.command("history <skill-id>").description("Show a skill's version history").action(async (id, _opts, cmd2) => {
2206
2323
  printJson(await clientFrom(cmd2).skills.history(id), outputOptions(cmd2));
@@ -2211,15 +2328,21 @@ function skillCommand() {
2211
2328
  outputOptions(cmd2)
2212
2329
  );
2213
2330
  });
2214
- cmd.command("register <directory>").description("Zip a local skill directory and register it").option("--source <s>", "source tag").option("--extend-info <json>", "extra metadata as JSON").action(async (dir, opts, cmd2) => {
2331
+ 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) => {
2215
2332
  const extendInfo = opts.extendInfo ? JSON.parse(opts.extendInfo) : void 0;
2216
2333
  printJson(
2217
- await clientFrom(cmd2).skills.register(dir, { source: opts.source, extendInfo }),
2334
+ await clientFrom(cmd2).skills.register(dir, {
2335
+ source: checkSource(opts.source),
2336
+ extendInfo
2337
+ }),
2218
2338
  outputOptions(cmd2)
2219
2339
  );
2220
2340
  });
2221
- cmd.command("download <skill-id> [out-path]").description("Download a skill archive to a local .zip").action(async (skillId, outPath, _o, cmd2) => {
2222
- printJson(await clientFrom(cmd2).skills.download(skillId, outPath), outputOptions(cmd2));
2341
+ draftOption(cmd.command("download <skill-id> [out-path]")).description("Download a skill archive to a local .zip").action(async (skillId, outPath, opts, cmd2) => {
2342
+ printJson(
2343
+ await clientFrom(cmd2).skills.download(skillId, outPath, { draft: opts.draft }),
2344
+ outputOptions(cmd2)
2345
+ );
2223
2346
  });
2224
2347
  cmd.command("install <skill-id> [directory]").description("Download a skill archive and extract it locally").action(async (skillId, dir, _o, cmd2) => {
2225
2348
  printJson(await clientFrom(cmd2).skills.install(skillId, dir), outputOptions(cmd2));
@@ -2441,30 +2564,108 @@ function traceCommand() {
2441
2564
  cmd.command("graph <trace-id>").description("Fetch normalized trace graph by trace id").action(async (traceId, _opts, cmd2) => {
2442
2565
  printJson(await clientFrom(cmd2).trace.graph(traceId), outputOptions(cmd2));
2443
2566
  });
2444
- cmd.command("evidence-chain [trace-id]").description("Fetch BKN Trace evidence chain by trace id or --request-id").option("--request-id <id>", "BKN request id scope").option("--limit <n>", "maximum evidence trace batches", (v) => Number.parseInt(v, 10)).action(async (traceId, opts, cmd2) => {
2567
+ const conversations = cmd.command("conversations").description("Manage Trace conversations");
2568
+ conversations.command("list").description("List conversations in the authorized owner scope").option("--limit <n>", "page size, 1..100", (value) => Number.parseInt(value, 10)).action(async (opts, cmd2) => {
2445
2569
  printJson(
2446
- await clientFrom(cmd2).trace.evidenceChain(traceScope(traceId, opts.requestId), {
2447
- limit: opts.limit
2570
+ await clientFrom(cmd2).trace.lifecycle.listConversations({ limit: opts.limit }),
2571
+ outputOptions(cmd2)
2572
+ );
2573
+ });
2574
+ conversations.command("ensure-current <external-conversation-key>").description("Ensure the current Core-owned conversation generation").option("--one-shot", "create a one-shot conversation").option("--idempotency-key <key>", "stable idempotency key").action(async (externalConversationKey, opts, cmd2) => {
2575
+ printJson(
2576
+ await clientFrom(cmd2).trace.lifecycle.ensureConversation({
2577
+ external_conversation_key: externalConversationKey,
2578
+ idempotency_key: opts.idempotencyKey,
2579
+ one_shot: Boolean(opts.oneShot)
2448
2580
  }),
2449
2581
  outputOptions(cmd2)
2450
2582
  );
2451
2583
  });
2452
- cmd.command("business-graph [trace-id]").description("Fetch BKN Trace business semantic graph by trace id or --request-id").option("--request-id <id>", "BKN request id scope").option("--limit <n>", "maximum evidence trace batches", (v) => Number.parseInt(v, 10)).action(async (traceId, opts, cmd2) => {
2584
+ conversations.command("create-new-generation <external-conversation-key>").description("Create the next Core-owned conversation generation").requiredOption("--idempotency-key <key>", "stable idempotency key").action(async (externalConversationKey, opts, cmd2) => {
2453
2585
  printJson(
2454
- await clientFrom(cmd2).trace.businessGraph(traceScope(traceId, opts.requestId), {
2455
- limit: opts.limit
2586
+ await clientFrom(cmd2).trace.lifecycle.createNewConversationGeneration({
2587
+ external_conversation_key: externalConversationKey,
2588
+ idempotency_key: opts.idempotencyKey
2456
2589
  }),
2457
2590
  outputOptions(cmd2)
2458
2591
  );
2459
2592
  });
2460
- cmd.command("snapshot-preview [trace-id]").description("Fetch metadata-only evidence snapshot preview by trace id or --request-id").option("--request-id <id>", "BKN request id scope").option("--limit <n>", "maximum evidence trace batches", (v) => Number.parseInt(v, 10)).action(async (traceId, opts, cmd2) => {
2593
+ conversations.command("resume <conversation-id>").description("Resume an existing authorized conversation").action(async (conversationId, _opts, cmd2) => {
2461
2594
  printJson(
2462
- await clientFrom(cmd2).trace.snapshotPreview(traceScope(traceId, opts.requestId), {
2463
- limit: opts.limit
2595
+ await clientFrom(cmd2).trace.lifecycle.resumeConversation({
2596
+ conversation_id: conversationId
2464
2597
  }),
2465
2598
  outputOptions(cmd2)
2466
2599
  );
2467
2600
  });
2601
+ conversations.command("get <conversation-id>").description("Get an authorized conversation").action(async (conversationId, _opts, cmd2) => {
2602
+ printJson(
2603
+ await clientFrom(cmd2).trace.lifecycle.getConversation(conversationId),
2604
+ outputOptions(cmd2)
2605
+ );
2606
+ });
2607
+ conversations.command("close <conversation-id>").description("Close an active conversation").option("--idempotency-key <key>", "stable idempotency key").action(async (conversationId, opts, cmd2) => {
2608
+ printJson(
2609
+ await clientFrom(cmd2).trace.lifecycle.closeConversation(conversationId, {
2610
+ idempotency_key: opts.idempotencyKey
2611
+ }),
2612
+ outputOptions(cmd2)
2613
+ );
2614
+ });
2615
+ const interactions = cmd.command("interactions").description("Inspect Trace interactions");
2616
+ interactions.command("start <conversation-id>").description("Start one managed interaction").requiredOption("--idempotency-key <key>", "stable idempotency key").option("--agent-name <name>", "conversation-level Agent display name").option(
2617
+ "--lease-seconds <n>",
2618
+ "interaction lease duration",
2619
+ (value) => Number.parseInt(value, 10)
2620
+ ).action(async (conversationId, opts, cmd2) => {
2621
+ printJson(
2622
+ await clientFrom(cmd2).trace.lifecycle.startInteraction(conversationId, {
2623
+ idempotency_key: opts.idempotencyKey,
2624
+ agent_name: opts.agentName,
2625
+ lease_seconds: opts.leaseSeconds
2626
+ }),
2627
+ outputOptions(cmd2)
2628
+ );
2629
+ });
2630
+ interactions.command("get <interaction-id>").description("Get an authorized interaction").action(async (interactionId, _opts, cmd2) => {
2631
+ printJson(
2632
+ await clientFrom(cmd2).trace.lifecycle.getInteraction(interactionId),
2633
+ outputOptions(cmd2)
2634
+ );
2635
+ });
2636
+ for (const action of ["complete", "fail", "cancel", "handoff"]) {
2637
+ interactions.command(`${action} <interaction-id>`).description(`${action} a managed interaction using a 3.0 completion manifest`).requiredOption("--body-file <path>", "read completion manifest JSON from a protected file").action(async (interactionId, opts, cmd2) => {
2638
+ const input = readBody(opts);
2639
+ const lifecycle = clientFrom(cmd2).trace.lifecycle;
2640
+ const terminal = {
2641
+ complete: lifecycle.completeInteraction,
2642
+ fail: lifecycle.failInteraction,
2643
+ cancel: lifecycle.cancelInteraction,
2644
+ handoff: lifecycle.handoffInteraction
2645
+ }[action];
2646
+ printJson(await terminal(interactionId, input), outputOptions(cmd2));
2647
+ });
2648
+ }
2649
+ const operations = cmd.command("operations").description("Inspect and retry operations");
2650
+ operations.command("get <operation-id>").description("Get an authorized operation").action(async (operationId, _opts, cmd2) => {
2651
+ printJson(
2652
+ await clientFrom(cmd2).trace.lifecycle.getOperation(operationId),
2653
+ outputOptions(cmd2)
2654
+ );
2655
+ });
2656
+ operations.command("retry <operation-id>").description("Create the next retry attempt for an eligible failed operation").requiredOption("--body-file <path>", "read retry request JSON from a protected file").action(async (operationId, opts, cmd2) => {
2657
+ printJson(
2658
+ await clientFrom(cmd2).trace.lifecycle.retryOperationAttempt(
2659
+ operationId,
2660
+ readBody(opts)
2661
+ ),
2662
+ outputOptions(cmd2)
2663
+ );
2664
+ });
2665
+ const receipts = cmd.command("receipts").description("Inspect durable operation receipts");
2666
+ receipts.command("get <receipt-id>").description("Get an authorized operation receipt").action(async (receiptId, _opts, cmd2) => {
2667
+ printJson(await clientFrom(cmd2).trace.lifecycle.getReceipt(receiptId), outputOptions(cmd2));
2668
+ });
2468
2669
  cmd.command("get <conversation-id>").description("Fetch all trace spans for a conversation").option("--max-spans <n>", "max spans", (v) => Number.parseInt(v, 10)).action(async (conversationId, opts, cmd2) => {
2469
2670
  printJson(
2470
2671
  await clientFrom(cmd2).trace.spans(conversationId, { maxSpans: opts.maxSpans }),
@@ -2521,25 +2722,55 @@ function traceCommand() {
2521
2722
  printJson(result, outputOptions(cmd2));
2522
2723
  if (!result.ok) process.exitCode = 1;
2523
2724
  });
2524
- const evidence = cmd.command("evidence").description("Submit BKN Trace 2.x business evidence events");
2525
- evidence.command("emit <file>").description("Submit a BKN Trace 2.0/2.1 event batch JSON file").action(async (file, _opts, cmd2) => {
2526
- const body = JSON.parse(readFileSync5(file, "utf8"));
2527
- printJson(await clientFrom(cmd2).trace.emitEvidenceEvents(body), outputOptions(cmd2));
2528
- });
2529
2725
  return group(cmd, "TRACE AI");
2530
2726
  }
2531
- function traceScope(traceId, requestId) {
2532
- if (traceId && requestId) {
2533
- throw new InputError("Provide either trace id or --request-id, not both.");
2534
- }
2535
- if (requestId) return { requestId };
2536
- if (traceId) return traceId;
2537
- throw new InputError("Provide a trace id or --request-id.");
2538
- }
2539
2727
 
2540
2728
  // src/commands/vega.ts
2541
2729
  import { Command as Command16 } from "commander";
2542
2730
  var int12 = (v) => Number.parseInt(v, 10);
2731
+ var bool = (value) => {
2732
+ if (value === "true") return true;
2733
+ if (value === "false") return false;
2734
+ throw new InputError("boolean value must be true or false");
2735
+ };
2736
+ var parseJsonObject = (value, flag) => {
2737
+ let parsed;
2738
+ try {
2739
+ parsed = JSON.parse(value);
2740
+ } catch {
2741
+ throw new InputError(`${flag} must be valid JSON`);
2742
+ }
2743
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
2744
+ throw new InputError(`${flag} must be a JSON object`);
2745
+ }
2746
+ return parsed;
2747
+ };
2748
+ var parseStringRecord = (value, flag) => {
2749
+ const parsed = parseJsonObject(value, flag);
2750
+ if (Object.values(parsed).some((item) => typeof item !== "string")) {
2751
+ throw new InputError(`${flag} values must be strings`);
2752
+ }
2753
+ return parsed;
2754
+ };
2755
+ var healthCheckSchedule = (mode, cronExpr) => {
2756
+ if (!mode) {
2757
+ if (cronExpr) throw new InputError("a health-check cron expression requires enabled mode");
2758
+ return void 0;
2759
+ }
2760
+ if (mode === "enabled") {
2761
+ if (!cronExpr) {
2762
+ throw new InputError("a health-check cron expression is required in enabled mode");
2763
+ }
2764
+ return { mode, cronExpr };
2765
+ }
2766
+ if (mode === "inherit" || mode === "disabled") {
2767
+ if (cronExpr) {
2768
+ throw new InputError("a health-check cron expression is only valid in enabled mode");
2769
+ }
2770
+ return { mode };
2771
+ }
2772
+ throw new InputError("health-check mode must be inherit, enabled, or disabled");
2773
+ };
2543
2774
  var parsePairs2 = (raw) => {
2544
2775
  if (!raw) return void 0;
2545
2776
  return raw.split(",").map((part) => {
@@ -2580,45 +2811,48 @@ function vegaCommand() {
2580
2811
  outputOptions(cmd)
2581
2812
  );
2582
2813
  });
2583
- catalog.command("health <ids...>").description("Health-status for one or more catalogs").action(async (ids, _opts, cmd) => {
2584
- printJson(await clientFrom(cmd).vega.catalogHealth(ids), outputOptions(cmd));
2814
+ catalog.command("health <id>").description("Health-status for a catalog").action(async (id, _opts, cmd) => {
2815
+ printJson(await clientFrom(cmd).vega.catalogHealth(id), outputOptions(cmd));
2585
2816
  });
2586
- catalog.command("create").description("Create a catalog (data source)").requiredOption("--name <s>", "catalog name").requiredOption("--connector-type <s>", "connector type (e.g. mysql)").requiredOption("--connector-config <json>", "connector config JSON").option("--id <id>", "explicit catalog id").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--enabled", "create enabled (default: disabled)").option("--internal", "create an internal catalog").option("--extensions <json>", "extension key/value JSON object").action(async (opts, cmd) => {
2587
- let connectorConfig;
2588
- try {
2589
- connectorConfig = JSON.parse(opts.connectorConfig);
2590
- } catch {
2591
- throw new Error("--connector-config must be valid JSON");
2592
- }
2593
- const extensions = opts.extensions ? JSON.parse(opts.extensions) : void 0;
2817
+ catalog.command("create").description("Create a catalog (data source)").requiredOption("--name <s>", "catalog name").requiredOption("--connector-type <s>", "connector type (e.g. mysql)").requiredOption("--connector-config <json>", "connector config JSON").option("--id <id>", "explicit catalog id").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--enabled", "create enabled (default: disabled)").option("--internal", "create an internal catalog").option("--extensions <json>", "extension key/value JSON object").option("--allow-unhealthy", "save the catalog when its connection test fails").option("--health-check-mode <mode>", "health schedule: inherit | enabled | disabled").option("--health-check-cron <expr>", "cron expression for enabled health checks").action(async (opts, cmd) => {
2818
+ const connectorConfig = parseJsonObject(opts.connectorConfig, "--connector-config");
2819
+ const extensions = opts.extensions ? parseStringRecord(opts.extensions, "--extensions") : void 0;
2594
2820
  printJson(
2595
- await clientFrom(cmd).vega.createCatalog({
2596
- id: opts.id,
2597
- name: opts.name,
2598
- connectorType: opts.connectorType,
2599
- connectorConfig,
2600
- tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
2601
- description: opts.description,
2602
- enabled: opts.enabled ? true : void 0,
2603
- internal: opts.internal ? true : void 0,
2604
- extensions
2605
- }),
2821
+ await clientFrom(cmd).vega.createCatalog(
2822
+ {
2823
+ id: opts.id,
2824
+ name: opts.name,
2825
+ connectorType: opts.connectorType,
2826
+ connectorConfig,
2827
+ tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
2828
+ description: opts.description,
2829
+ enabled: opts.enabled ? true : void 0,
2830
+ internal: opts.internal ? true : void 0,
2831
+ extensions,
2832
+ healthCheckSchedule: healthCheckSchedule(opts.healthCheckMode, opts.healthCheckCron)
2833
+ },
2834
+ { allowUnhealthy: opts.allowUnhealthy ? true : void 0 }
2835
+ ),
2606
2836
  outputOptions(cmd)
2607
2837
  );
2608
2838
  });
2609
- catalog.command("update <id>").description("Update a catalog").option("--name <s>", "catalog name").option("--connector-type <s>", "connector type").option("--connector-config <json>", "connector config JSON").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--enabled <bool>", "enabled state").option("--extensions <json>", "extension key/value JSON object").action(async (id, opts, cmd) => {
2610
- const connectorConfig = opts.connectorConfig ? JSON.parse(opts.connectorConfig) : void 0;
2611
- const extensions = opts.extensions ? JSON.parse(opts.extensions) : void 0;
2839
+ catalog.command("update <id>").description("Fully update a catalog").requiredOption("--name <s>", "catalog name").requiredOption("--connector-type <s>", "connector type").requiredOption("--enabled <bool>", "current enabled state", bool).option("--connector-config <json>", "connector config JSON").option("--tags <t1,t2>", "comma-separated tags").option("--description <s>", "description").option("--extensions <json>", "extension key/value JSON object").option("--allow-unhealthy", "save the update when its connection test fails").action(async (id, opts, cmd) => {
2840
+ const connectorConfig = opts.connectorConfig ? parseJsonObject(opts.connectorConfig, "--connector-config") : void 0;
2841
+ const extensions = opts.extensions ? parseStringRecord(opts.extensions, "--extensions") : void 0;
2612
2842
  printJson(
2613
- await clientFrom(cmd).vega.updateCatalog(id, {
2614
- name: opts.name,
2615
- connectorType: opts.connectorType,
2616
- connectorConfig,
2617
- tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
2618
- description: opts.description,
2619
- enabled: opts.enabled === void 0 ? void 0 : opts.enabled === "true",
2620
- extensions
2621
- }),
2843
+ await clientFrom(cmd).vega.updateCatalog(
2844
+ id,
2845
+ {
2846
+ name: opts.name,
2847
+ connectorType: opts.connectorType,
2848
+ connectorConfig,
2849
+ tags: opts.tags ? String(opts.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0,
2850
+ description: opts.description,
2851
+ enabled: opts.enabled,
2852
+ extensions
2853
+ },
2854
+ { allowUnhealthy: opts.allowUnhealthy ? true : void 0 }
2855
+ ),
2622
2856
  outputOptions(cmd)
2623
2857
  );
2624
2858
  });
@@ -2634,6 +2868,26 @@ function vegaCommand() {
2634
2868
  catalog.command("test-connection <id>").description("Test a catalog connection").action(async (id, _opts, cmd) => {
2635
2869
  printJson(await clientFrom(cmd).vega.testCatalogConnection(id), outputOptions(cmd));
2636
2870
  });
2871
+ catalog.command("test-connection-config").description("Test an unpersisted catalog connection configuration").requiredOption("--connector-type <s>", "connector type").requiredOption("--connector-config <json>", "connector config JSON").action(async (opts, cmd) => {
2872
+ printJson(
2873
+ await clientFrom(cmd).vega.testCatalogConnectionConfig({
2874
+ connectorType: opts.connectorType,
2875
+ connectorConfig: parseJsonObject(opts.connectorConfig, "--connector-config")
2876
+ }),
2877
+ outputOptions(cmd)
2878
+ );
2879
+ });
2880
+ catalog.command("health-check-schedule <id>").description("Get a catalog health-check schedule").action(async (id, _opts, cmd) => {
2881
+ printJson(await clientFrom(cmd).vega.catalogHealthCheckSchedule(id), outputOptions(cmd));
2882
+ });
2883
+ catalog.command("set-health-check-schedule <id>").description("Update a catalog health-check schedule").requiredOption("--mode <mode>", "health schedule: inherit | enabled | disabled").option("--cron <expr>", "cron expression for enabled health checks").action(async (id, opts, cmd) => {
2884
+ const schedule = healthCheckSchedule(opts.mode, opts.cron);
2885
+ if (!schedule) throw new InputError("--mode is required");
2886
+ printJson(
2887
+ await clientFrom(cmd).vega.updateCatalogHealthCheckSchedule(id, schedule),
2888
+ outputOptions(cmd)
2889
+ );
2890
+ });
2637
2891
  catalog.command("discover <id>").description("Trigger catalog resource discovery").option("--wait", "wait for discovery to complete").action(async (id, opts, cmd) => {
2638
2892
  printJson(
2639
2893
  await clientFrom(cmd).vega.discoverCatalog(id, Boolean(opts.wait)),
@@ -2749,11 +3003,16 @@ function vegaCommand() {
2749
3003
  );
2750
3004
  printJson(task, outputOptions(cmd));
2751
3005
  });
2752
- dataset.command("build-status <resource-id> <task-id>").description("Show a BuildTask's state and progress").action(async (_resourceId, taskId, _opts, cmd) => {
3006
+ dataset.command("build-status <task-id>").description("Show a BuildTask's state and progress").action(async (taskId, _opts, cmd) => {
2753
3007
  const task = await clientFrom(cmd).vega.buildStatus(taskId);
2754
3008
  printJson(task, outputOptions(cmd));
2755
3009
  });
2756
- dataset.command("build-list").description("List BuildTasks").option("--limit <n>", "page size", int12, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int12, 0).option("--resource-id <id>", "filter by resource id").option("--catalog-id <id>", "filter by catalog id").option("--status <status>", "comma-separated statuses").option("--active", "only running/init tasks").option("--mode <mode>", "filter by mode: batch | streaming").option("--order-by <field>", "default | created_at | updated_at | status | mode").option("--order <dir>", "asc | desc").action(async (opts, cmd) => {
3010
+ dataset.command("build-list").description("List BuildTasks").option("--limit <n>", "page size", int12, DEFAULT_LIST_LIMIT).option("--offset <n>", "page offset", int12, 0).option("--resource-id <id>", "filter by resource id").option("--catalog-id <id>", "filter by catalog id").option("--status <status>", "comma-separated statuses").option("--active", "only running/init tasks").option("--mode <mode>", "filter by mode: batch | streaming").option("--order-by <field>", "created_at | updated_at").option("--order <dir>", "asc | desc").action(async (opts, cmd) => {
3011
+ if (opts.orderBy === "default") {
3012
+ throw new InputError(
3013
+ '--order-by default is no longer supported; use "created_at" or "updated_at"'
3014
+ );
3015
+ }
2757
3016
  printJson(
2758
3017
  await clientFrom(cmd).vega.buildTasks({
2759
3018
  limit: opts.limit,
@@ -2769,7 +3028,7 @@ function vegaCommand() {
2769
3028
  outputOptions(cmd)
2770
3029
  );
2771
3030
  });
2772
- dataset.command("build-start <task-id>").description("Start a BuildTask").option("--reset", "restart from the beginning").action(async (taskId, opts, cmd) => {
3031
+ dataset.command("build-start <task-id>").description("Start a BuildTask").option("--reset", "restart a full task from the beginning (ignored for incremental tasks)").action(async (taskId, opts, cmd) => {
2773
3032
  printJson(
2774
3033
  await clientFrom(cmd).vega.startBuildTask(taskId, { reset: opts.reset }),
2775
3034
  outputOptions(cmd)
@@ -2816,6 +3075,8 @@ try {
2816
3075
  await program.parseAsync(argv);
2817
3076
  } catch (err) {
2818
3077
  console.error(formatError(err));
3078
+ await releaseLifecycleSessions();
2819
3079
  process.exit(toExitCode(err));
2820
3080
  }
3081
+ await releaseLifecycleSessions();
2821
3082
  //# sourceMappingURL=cli.js.map