@openbkn/bkn-sdk 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -33,9 +33,10 @@ import {
33
33
  switchUser,
34
34
  toExitCode,
35
35
  use,
36
+ validateFixturePath,
36
37
  whoami,
37
38
  writePlatformConfig
38
- } from "./chunk-NC6DZ2AU.js";
39
+ } from "./chunk-LH3ONZGQ.js";
39
40
 
40
41
  // src/cli.ts
41
42
  import { Command as Command17 } from "commander";
@@ -43,7 +44,7 @@ import { Command as Command17 } from "commander";
43
44
  // package.json
44
45
  var package_default = {
45
46
  name: "@openbkn/bkn-sdk",
46
- version: "0.1.1",
47
+ version: "0.1.2",
47
48
  description: "Unified TypeScript SDK + CLI for the BKN (Business Knowledge Network) platform.",
48
49
  type: "module",
49
50
  license: "Apache-2.0",
@@ -78,6 +79,7 @@ var package_default = {
78
79
  lint: "npm run check:deps && biome check . && tsc --noEmit",
79
80
  format: "biome format --write .",
80
81
  test: "vitest run",
82
+ "test:e2e:trace-business": "npm run build && node test/e2e/bkn-trace-business-interaction.mjs",
81
83
  "test:cover": "vitest run --coverage",
82
84
  ci: "npm run lint && npm test",
83
85
  prepublishOnly: "npm run ci && npm run build"
@@ -174,10 +176,15 @@ function renderOrgTree(nodes, prefix = "") {
174
176
  // src/utils/output.ts
175
177
  function printJson(value, opts = {}) {
176
178
  if (opts.json || opts.compact) {
177
- process.stdout.write(`${JSON.stringify(value, null, opts.compact ? 0 : 2)}
179
+ const json = JSON.stringify(value === void 0 ? null : value, null, opts.compact ? 0 : 2);
180
+ process.stdout.write(`${json}
178
181
  `);
179
182
  return;
180
183
  }
184
+ if (value === void 0) {
185
+ process.stdout.write("(ok)\n");
186
+ return;
187
+ }
181
188
  const rows = toRows(value);
182
189
  if (rows) {
183
190
  const fullColumns = columnsOf(rows).filter((c) => rows.some((r) => stringifyCell(r[c]) !== ""));
@@ -322,14 +329,25 @@ function promptLine(query, hidden = false) {
322
329
 
323
330
  // src/commands/_shared.ts
324
331
  import { readFileSync } from "fs";
332
+ function traceOptionsFrom(o) {
333
+ const conversationId = (typeof o.conversationId === "string" ? o.conversationId : void 0) ?? process.env.BKN_CONVERSATION_ID;
334
+ const interactionId = (typeof o.interactionId === "string" ? o.interactionId : void 0) ?? process.env.BKN_INTERACTION_ID;
335
+ if (!conversationId && !interactionId) return void 0;
336
+ return {
337
+ ...conversationId ? { conversationId } : {},
338
+ ...interactionId ? { interactionId } : {}
339
+ };
340
+ }
325
341
  function clientFrom(cmd) {
326
342
  const o = cmd.optsWithGlobals();
343
+ const trace = traceOptionsFrom(o);
327
344
  return createClient({
328
345
  baseUrl: o.baseUrl,
329
346
  token: o.token,
330
347
  user: o.user,
331
348
  businessDomain: o.bizDomain,
332
- insecure: o.insecure
349
+ insecure: o.insecure,
350
+ ...trace ? { trace } : {}
333
351
  });
334
352
  }
335
353
  function outputOptions(cmd) {
@@ -1349,9 +1367,6 @@ function bknCommand() {
1349
1367
  outputOptions(cmd)
1350
1368
  );
1351
1369
  });
1352
- objectType?.command("properties <kn-id> <ot-id>").description("Get an object type's calculated properties").action(async (knId, otId, _opts, cmd) => {
1353
- printJson(await clientFrom(cmd).kn.objectTypeProperties(knId, otId), outputOptions(cmd));
1354
- });
1355
1370
  bkn.command("create <name>").description("Create an (empty) knowledge network").option("--branch <b>", "branch", "main").action(async (name, opts, cmd) => {
1356
1371
  printJson(await clientFrom(cmd).kn.create({ name, branch: opts.branch }), outputOptions(cmd));
1357
1372
  });
@@ -1480,19 +1495,6 @@ function bknCommand() {
1480
1495
  sched.command("delete <kn-id> <schedule-ids>").description("Delete action schedule(s) (comma-joined ids)").action(async (knId, ids, _o, cmd) => {
1481
1496
  printJson(await clientFrom(cmd).kn.actionScheduleDelete(knId, ids), outputOptions(cmd));
1482
1497
  });
1483
- const job = bkn.command("job").description("Build jobs \u2014 list/get/tasks");
1484
- job.command("list <kn-id>").description("List jobs").action(async (knId, _o, cmd) => {
1485
- printJson(await clientFrom(cmd).kn.jobs(knId), outputOptions(cmd));
1486
- });
1487
- job.command("get <kn-id> <job-id>").description("Get a job").action(async (knId, jobId, _o, cmd) => {
1488
- printJson(await clientFrom(cmd).kn.job(knId, jobId), outputOptions(cmd));
1489
- });
1490
- job.command("tasks <kn-id> <job-id>").description("List a job's tasks").action(async (knId, jobId, _o, cmd) => {
1491
- printJson(await clientFrom(cmd).kn.jobTasks(knId, jobId), outputOptions(cmd));
1492
- });
1493
- job.command("delete <kn-id> <job-ids>").description("Delete job(s) (comma-joined ids)").action(async (knId, ids, _o, cmd) => {
1494
- printJson(await clientFrom(cmd).kn.jobDelete(knId, ids), outputOptions(cmd));
1495
- });
1496
1498
  bkn.command("push <directory>").description("Pack a BKN directory into a tar and import it as a knowledge network").option("--branch <name>", "target branch", "main").option("--build", "submit a Vega build task for each object type declaring a vector index").option(
1497
1499
  "--embedding-model <id>",
1498
1500
  "embedding model id for declared vector indexes (with --build)"
@@ -1584,12 +1586,14 @@ function callCommand() {
1584
1586
  []
1585
1587
  ).option("-v, --verbose", "print request line to stderr").action(async (url, opts, cmd2) => {
1586
1588
  const g = cmd2.optsWithGlobals();
1589
+ const trace = traceOptionsFrom(g);
1587
1590
  const ctx = resolveContext({
1588
1591
  baseUrl: g.baseUrl,
1589
1592
  token: g.token,
1590
1593
  user: g.user,
1591
1594
  businessDomain: g.bizDomain,
1592
- insecure: g.insecure
1595
+ insecure: g.insecure,
1596
+ ...trace ? { trace } : {}
1593
1597
  });
1594
1598
  const res = await rawCall(ctx, url, {
1595
1599
  method: opts.request,
@@ -1822,9 +1826,13 @@ function dataflowCommand() {
1822
1826
  cmd.command("list").description("List all dataflows").action(async (_opts, cmd2) => {
1823
1827
  printJson(await clientFrom(cmd2).dataflows.list(), outputOptions(cmd2));
1824
1828
  });
1825
- cmd.command("runs <dagId>").description("List run records for one dataflow").option("--since <date>", "filter runs since a date").action(async (dagId, opts, cmd2) => {
1829
+ cmd.command("runs <dagId>").description("List run records for one dataflow").option("--since <date>", "filter runs since a date").option("--limit <n>", "page size (backend default 20)", int6).option("--page <n>", "page (0-based; backend default 0)", int6).action(async (dagId, opts, cmd2) => {
1826
1830
  printJson(
1827
- await clientFrom(cmd2).dataflows.runs(dagId, { since: opts.since }),
1831
+ await clientFrom(cmd2).dataflows.runs(dagId, {
1832
+ since: opts.since,
1833
+ page: opts.page,
1834
+ limit: opts.limit
1835
+ }),
1828
1836
  outputOptions(cmd2)
1829
1837
  );
1830
1838
  });
@@ -1899,7 +1907,6 @@ var ROUTES = {
1899
1907
  }),
1900
1908
  "POST /api/bkn/instances": (c, _q, b) => c.kn.objectTypeQuery(str(b.knId), str(b.objectTypeId), b.body ?? {}),
1901
1909
  "POST /api/bkn/subgraph": (c, _q, b) => c.kn.subgraph(str(b.knId), b.body ?? b),
1902
- "POST /api/bkn/properties": (c, _q, b) => c.kn.objectTypeProperties(str(b.knId), str(b.objectTypeId)),
1903
1910
  "GET /api/vega/catalogs": (c) => c.vega.catalogs(),
1904
1911
  "GET /api/vega/catalog": (c, q) => c.vega.getCatalog(req(q, "catalogId")),
1905
1912
  "GET /api/vega/catalog-resources": (c, q) => c.vega.catalogResources(req(q, "catalogId"), q.get("category") ?? void 0),
@@ -2120,20 +2127,24 @@ function resourceCommand() {
2120
2127
  });
2121
2128
  printJson(data, outputOptions(cmd2));
2122
2129
  });
2123
- cmd.command("find").description("Search resources by name (fuzzy; --exact for strict)").requiredOption("--name <name>", "resource name to search").option("--exact", "exact name match").option("--catalog-id <id>", "limit to a catalog").option("--datasource-id <id>", "alias of --catalog-id").action(async (opts, cmd2) => {
2130
+ cmd.command("find").description("Search resources by name (fuzzy; --exact for strict)").requiredOption("--name <name>", "resource name to search").option("--exact", "exact name match").option("--catalog-id <id>", "limit to a catalog").option("--datasource-id <id>", "alias of --catalog-id").option("--limit <n>", "rows to scan before filtering", int9, DEFAULT_LIST_LIMIT).action(async (opts, cmd2) => {
2124
2131
  const data = await clientFrom(cmd2).resource.find(opts.name, {
2125
2132
  exact: opts.exact,
2126
- datasourceId: opts.catalogId ?? opts.datasourceId
2133
+ datasourceId: opts.catalogId ?? opts.datasourceId,
2134
+ limit: opts.limit
2127
2135
  });
2128
2136
  printJson(data, outputOptions(cmd2));
2129
2137
  });
2130
2138
  cmd.command("get <id>").description("Get resource details").action(async (id, _opts, cmd2) => {
2131
2139
  printJson(await clientFrom(cmd2).resource.get(id), outputOptions(cmd2));
2132
2140
  });
2133
- cmd.command("query <id>").description("Fetch data rows from a resource").option("--limit <n>", "row limit", int9, DEFAULT_QUERY_LIMIT).option("--offset <n>", "row offset", int9, 0).option("--need-total", "include total count").action(async (id, opts, cmd2) => {
2141
+ cmd.command("query <id>").description("Fetch data rows from a resource").option("--limit <n>", "row limit", int9, DEFAULT_QUERY_LIMIT).option("--offset <n>", "row offset", int9, 0).option("--paging-mode <mode>", "paging mode: single | cursor").option("--keep-alive-sec <s>", "cursor keep-alive in seconds (60\u20133600)", int9).option("--cursor <cursor>", "opaque cursor returned by the previous page").option("--need-total", "include total count").action(async (id, opts, cmd2) => {
2134
2142
  const data = await clientFrom(cmd2).resource.query(id, {
2135
2143
  limit: opts.limit,
2136
2144
  offset: opts.offset,
2145
+ pagingMode: opts.pagingMode,
2146
+ keepAliveSec: opts.keepAliveSec,
2147
+ cursor: opts.cursor,
2137
2148
  needTotal: opts.needTotal
2138
2149
  });
2139
2150
  printJson(data, outputOptions(cmd2));
@@ -2281,8 +2292,15 @@ function toolboxCommand() {
2281
2292
  }
2282
2293
  function toolCommand() {
2283
2294
  const cmd = new Command14("tool").description("Tools inside a toolbox");
2284
- cmd.command("list").description("List tools in a toolbox").requiredOption("--toolbox <box-id>", "toolbox id").action(async (opts, cmd2) => {
2285
- printJson(await clientFrom(cmd2).toolboxes.tools(opts.toolbox), outputOptions(cmd2));
2295
+ cmd.command("list").description("List tools in a toolbox").requiredOption("--toolbox <box-id>", "toolbox id").option("--limit <n>", "page size (backend default 10, max 100)", int11).option("--page <n>", "page (1-based; backend default 1)", int11).option("--all", "return every tool, ignoring page size").action(async (opts, cmd2) => {
2296
+ printJson(
2297
+ await clientFrom(cmd2).toolboxes.tools(opts.toolbox, {
2298
+ page: opts.page,
2299
+ pageSize: opts.limit,
2300
+ all: opts.all
2301
+ }),
2302
+ outputOptions(cmd2)
2303
+ );
2286
2304
  });
2287
2305
  cmd.command("enable <tool-ids...>").description("Enable one or more tools").requiredOption("--toolbox <box-id>", "toolbox id").action(async (toolIds, opts, cmd2) => {
2288
2306
  printJson(
@@ -2420,6 +2438,33 @@ function traceCommand() {
2420
2438
  const cmd = new Command15("trace").description(
2421
2439
  "BKN Trace \u2014 fetch spans, diagnose (symbolic + LLM rubric), scan, eval-set, schema validate"
2422
2440
  );
2441
+ cmd.command("graph <trace-id>").description("Fetch normalized trace graph by trace id").action(async (traceId, _opts, cmd2) => {
2442
+ printJson(await clientFrom(cmd2).trace.graph(traceId), outputOptions(cmd2));
2443
+ });
2444
+ cmd.command("evidence-chain [trace-id]").description("Fetch BKN Trace evidence chain by trace id or --request-id").option("--request-id <id>", "BKN request id scope").option("--limit <n>", "maximum evidence trace batches", (v) => Number.parseInt(v, 10)).action(async (traceId, opts, cmd2) => {
2445
+ printJson(
2446
+ await clientFrom(cmd2).trace.evidenceChain(traceScope(traceId, opts.requestId), {
2447
+ limit: opts.limit
2448
+ }),
2449
+ outputOptions(cmd2)
2450
+ );
2451
+ });
2452
+ cmd.command("business-graph [trace-id]").description("Fetch BKN Trace business semantic graph by trace id or --request-id").option("--request-id <id>", "BKN request id scope").option("--limit <n>", "maximum evidence trace batches", (v) => Number.parseInt(v, 10)).action(async (traceId, opts, cmd2) => {
2453
+ printJson(
2454
+ await clientFrom(cmd2).trace.businessGraph(traceScope(traceId, opts.requestId), {
2455
+ limit: opts.limit
2456
+ }),
2457
+ outputOptions(cmd2)
2458
+ );
2459
+ });
2460
+ cmd.command("snapshot-preview [trace-id]").description("Fetch metadata-only evidence snapshot preview by trace id or --request-id").option("--request-id <id>", "BKN request id scope").option("--limit <n>", "maximum evidence trace batches", (v) => Number.parseInt(v, 10)).action(async (traceId, opts, cmd2) => {
2461
+ printJson(
2462
+ await clientFrom(cmd2).trace.snapshotPreview(traceScope(traceId, opts.requestId), {
2463
+ limit: opts.limit
2464
+ }),
2465
+ outputOptions(cmd2)
2466
+ );
2467
+ });
2423
2468
  cmd.command("get <conversation-id>").description("Fetch all trace spans for a conversation").option("--max-spans <n>", "max spans", (v) => Number.parseInt(v, 10)).action(async (conversationId, opts, cmd2) => {
2424
2469
  printJson(
2425
2470
  await clientFrom(cmd2).trace.spans(conversationId, { maxSpans: opts.maxSpans }),
@@ -2471,8 +2516,26 @@ function traceCommand() {
2471
2516
  printJson(result, outputOptions(cmd2));
2472
2517
  if (!result.valid) process.exitCode = 1;
2473
2518
  });
2519
+ cmd.command("validate-fixture <path>").description("Validate BKN Trace 1.0/2.0/2.1 fixture JSON files").action(async (path, _opts, cmd2) => {
2520
+ const result = validateFixturePath(path);
2521
+ printJson(result, outputOptions(cmd2));
2522
+ if (!result.ok) process.exitCode = 1;
2523
+ });
2524
+ const evidence = cmd.command("evidence").description("Submit BKN Trace 2.x business evidence events");
2525
+ evidence.command("emit <file>").description("Submit a BKN Trace 2.0/2.1 event batch JSON file").action(async (file, _opts, cmd2) => {
2526
+ const body = JSON.parse(readFileSync5(file, "utf8"));
2527
+ printJson(await clientFrom(cmd2).trace.emitEvidenceEvents(body), outputOptions(cmd2));
2528
+ });
2474
2529
  return group(cmd, "TRACE AI");
2475
2530
  }
2531
+ function traceScope(traceId, requestId) {
2532
+ if (traceId && requestId) {
2533
+ throw new InputError("Provide either trace id or --request-id, not both.");
2534
+ }
2535
+ if (requestId) return { requestId };
2536
+ if (traceId) return traceId;
2537
+ throw new InputError("Provide a trace id or --request-id.");
2538
+ }
2476
2539
 
2477
2540
  // src/commands/vega.ts
2478
2541
  import { Command as Command16 } from "commander";
@@ -2511,8 +2574,11 @@ function vegaCommand() {
2511
2574
  catalog.command("get <id>").description("Get a catalog by id").action(async (id, _opts, cmd) => {
2512
2575
  printJson(await clientFrom(cmd).vega.getCatalog(id), outputOptions(cmd));
2513
2576
  });
2514
- catalog.command("resources <id>").description("List resources under a catalog").option("--category <c>", "filter by category (e.g. table)").action(async (id, opts, cmd) => {
2515
- printJson(await clientFrom(cmd).vega.catalogResources(id, opts.category), outputOptions(cmd));
2577
+ catalog.command("resources <id>").description("List resources under a catalog").option("--category <c>", "filter by category (e.g. table)").option("--limit <n>", "page size (backend default 20, max 1000; -1 = all)", int12).option("--offset <n>", "page offset", int12, 0).action(async (id, opts, cmd) => {
2578
+ printJson(
2579
+ await clientFrom(cmd).vega.catalogResources(id, opts.category, opts.limit, opts.offset),
2580
+ outputOptions(cmd)
2581
+ );
2516
2582
  });
2517
2583
  catalog.command("health <ids...>").description("Health-status for one or more catalogs").action(async (ids, _opts, cmd) => {
2518
2584
  printJson(await clientFrom(cmd).vega.catalogHealth(ids), outputOptions(cmd));
@@ -2581,12 +2647,12 @@ function vegaCommand() {
2581
2647
  connector.command("get <type>").description("Get a connector type").action(async (type, _opts, cmd) => {
2582
2648
  printJson(await clientFrom(cmd).vega.connectorType(type), outputOptions(cmd));
2583
2649
  });
2584
- vega.command("sql").description("Run SQL / OpenSearch DSL directly against a vega-backend data source").requiredOption("--resource-type <type>", "source type (mysql | postgresql | opensearch | \u2026)").option("--query-type <type>", "query mode: standard | stream").option(
2650
+ vega.command("sql").description("Run SQL / OpenSearch DSL directly against a vega-backend data source").option(
2585
2651
  "--query <sql>",
2586
2652
  "SQL string; reference a resource with a {{<resource-id>}} placeholder"
2587
- ).option("--stream-size <n>", "streaming batch size (100\u201310000)", int12).option("--query-timeout <s>", "query timeout in seconds (1\u20133600)", int12).option(
2653
+ ).option("--input-dialect <dialect>", "SQL input dialect: postgres | mysql | trino | duckdb").option("--paging-mode <mode>", "paging mode: single | cursor").option("--limit <n>", "page size (cursor mode requires it)", int12).option("--offset <n>", "first-page offset", int12).option("--keep-alive-sec <s>", "cursor keep-alive in seconds (60\u20133600)", int12).option("--cursor <cursor>", "opaque cursor returned by the previous page").option("--need-total", "include the complete total count").option("--query-timeout-sec <s>", "query timeout in seconds (1\u20133600)", int12).option(
2588
2654
  "-d, --data <json>",
2589
- "full request body as JSON (advanced; wins over --query/--resource-type)"
2655
+ "full request body as JSON (advanced; wins over individual query flags)"
2590
2656
  ).action(async (opts, cmd) => {
2591
2657
  let body;
2592
2658
  if (opts.data) {
@@ -2595,16 +2661,34 @@ function vegaCommand() {
2595
2661
  } catch {
2596
2662
  throw new InputError("--data must be valid JSON");
2597
2663
  }
2664
+ } else if (opts.cursor) {
2665
+ if (opts.query || opts.inputDialect || opts.pagingMode || opts.limit !== void 0 || opts.offset !== void 0 || opts.keepAliveSec !== void 0 || opts.queryTimeoutSec !== void 0) {
2666
+ throw new InputError("--cursor cannot be combined with initial-query options");
2667
+ }
2668
+ body = {
2669
+ paging: { cursor: opts.cursor },
2670
+ ...opts.needTotal ? { need_total: true } : {}
2671
+ };
2598
2672
  } else {
2599
2673
  if (!opts.query) {
2600
- throw new InputError("Provide --query (and optionally --resource-type), or --data.");
2674
+ throw new InputError("Provide --query, --cursor, or --data.");
2675
+ }
2676
+ if (opts.pagingMode === "cursor" && opts.limit === void 0) {
2677
+ throw new InputError("--limit is required when --paging-mode cursor");
2601
2678
  }
2679
+ const paging = {
2680
+ ...opts.pagingMode ? { mode: opts.pagingMode } : {},
2681
+ ...opts.limit !== void 0 ? { limit: opts.limit } : {},
2682
+ ...opts.offset !== void 0 ? { offset: opts.offset } : {},
2683
+ ...opts.keepAliveSec !== void 0 ? { keep_alive_sec: opts.keepAliveSec } : {}
2684
+ };
2602
2685
  body = {
2603
2686
  query: opts.query,
2604
- resource_type: opts.resourceType,
2605
- ...opts.queryType ? { query_type: opts.queryType } : {},
2606
- ...opts.streamSize !== void 0 ? { stream_size: opts.streamSize } : {},
2607
- ...opts.queryTimeout !== void 0 ? { query_timeout: opts.queryTimeout } : {}
2687
+ query_format: "sql",
2688
+ ...opts.inputDialect ? { input_dialect: opts.inputDialect } : {},
2689
+ ...Object.keys(paging).length ? { paging } : {},
2690
+ ...opts.needTotal ? { need_total: true } : {},
2691
+ ...opts.queryTimeoutSec !== void 0 ? { query_timeout_sec: opts.queryTimeoutSec } : {}
2608
2692
  };
2609
2693
  }
2610
2694
  printJson(await clientFrom(cmd).vega.sql(body), outputOptions(cmd));
@@ -2708,7 +2792,7 @@ function vegaCommand() {
2708
2792
 
2709
2793
  // src/cli.ts
2710
2794
  var program = new Command17();
2711
- program.name("openbkn").description("Operate the BKN platform from the CLI").version(package_default.version, "-V, --version", "output the version number").option("--base-url <url>", "platform base URL (env: BKN_BASE_URL)").option("--token <value>", "access token (env: BKN_TOKEN)").option("--user <id|name>", "use specific user credentials (env: BKN_USER)").option("--json", "machine-readable JSON output").option("--compact", "single-line JSON output").option("--full", "human view: show all columns (default trims to the key ones)").option("--biz-domain <s>", "business domain (alias: -bd)").option("-k, --insecure", "skip TLS verification (dev / self-signed only)").showHelpAfterError();
2795
+ program.name("openbkn").description("Operate the BKN platform from the CLI").version(package_default.version, "-V, --version", "output the version number").option("--base-url <url>", "platform base URL (env: BKN_BASE_URL)").option("--token <value>", "access token (env: BKN_TOKEN)").option("--user <id|name>", "use specific user credentials (env: BKN_USER)").option("--json", "machine-readable JSON output").option("--compact", "single-line JSON output").option("--full", "human view: show all columns (default trims to the key ones)").option("--biz-domain <s>", "business domain (alias: -bd)").option("--conversation-id <id>", "BKN Trace conversation id (env: BKN_CONVERSATION_ID)").option("--interaction-id <id>", "BKN Trace interaction id (env: BKN_INTERACTION_ID)").option("-k, --insecure", "skip TLS verification (dev / self-signed only)").showHelpAfterError();
2712
2796
  program.addCommand(authCommand());
2713
2797
  program.addCommand(callCommand());
2714
2798
  program.addCommand(configCommand());