@kweaver-ai/kweaver-sdk 0.8.3 → 0.8.4

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.
Files changed (74) hide show
  1. package/dist/api/agent-chat.d.ts +10 -2
  2. package/dist/api/agent-chat.js +19 -5
  3. package/dist/api/datasources.d.ts +14 -0
  4. package/dist/api/datasources.js +14 -0
  5. package/dist/cli.js +2 -14
  6. package/dist/client.d.ts +7 -1
  7. package/dist/client.js +7 -1
  8. package/dist/commands/bkn-ops.d.ts +1 -1
  9. package/dist/commands/bkn-ops.js +42 -21
  10. package/dist/commands/bkn.js +6 -3
  11. package/dist/commands/ds.d.ts +0 -31
  12. package/dist/commands/ds.js +18 -448
  13. package/dist/commands/explore-bkn.d.ts +7 -1
  14. package/dist/commands/explore-bkn.js +32 -3
  15. package/dist/resources/datasources.d.ts +7 -0
  16. package/dist/resources/datasources.js +7 -0
  17. package/dist/templates/explorer/bkn.js +860 -9
  18. package/dist/templates/explorer/index.html +1 -0
  19. package/dist/templates/explorer/style.css +225 -0
  20. package/dist/templates/explorer/vendor/g6.min.js +68 -0
  21. package/dist/trace-ai/eval-set/schemas.d.ts +1 -0
  22. package/dist/trace-ai/eval-set/schemas.js +4 -0
  23. package/dist/trace-ai/eval-set/types.d.ts +2 -0
  24. package/dist/trace-ai/exp/capture-fingerprint.d.ts +10 -0
  25. package/dist/trace-ai/exp/capture-fingerprint.js +12 -0
  26. package/dist/trace-ai/exp/context/context-assembler.d.ts +18 -0
  27. package/dist/trace-ai/exp/context/context-assembler.js +42 -0
  28. package/dist/trace-ai/exp/context/failure-analyzer.d.ts +22 -0
  29. package/dist/trace-ai/exp/context/failure-analyzer.js +59 -0
  30. package/dist/trace-ai/exp/context/kn-data-prober.d.ts +13 -0
  31. package/dist/trace-ai/exp/context/kn-data-prober.js +38 -0
  32. package/dist/trace-ai/exp/context/kn-schema-client.d.ts +14 -0
  33. package/dist/trace-ai/exp/context/kn-schema-client.js +41 -0
  34. package/dist/trace-ai/exp/context/retrieval-health.d.ts +32 -0
  35. package/dist/trace-ai/exp/context/retrieval-health.js +138 -0
  36. package/dist/trace-ai/exp/context/vega-catalog-client.d.ts +14 -0
  37. package/dist/trace-ai/exp/context/vega-catalog-client.js +15 -0
  38. package/dist/trace-ai/exp/coordinator.d.ts +34 -21
  39. package/dist/trace-ai/exp/coordinator.js +246 -24
  40. package/dist/trace-ai/exp/eval-runner.js +4 -2
  41. package/dist/trace-ai/exp/exp-store/events-jsonl.d.ts +1 -0
  42. package/dist/trace-ai/exp/exp-store/events-jsonl.js +18 -0
  43. package/dist/trace-ai/exp/exp-store/expected-fingerprint.d.ts +3 -0
  44. package/dist/trace-ai/exp/exp-store/expected-fingerprint.js +31 -0
  45. package/dist/trace-ai/exp/exp-store/index.d.ts +63 -2
  46. package/dist/trace-ai/exp/exp-store/index.js +2 -1
  47. package/dist/trace-ai/exp/exp-store/rollback-yaml.d.ts +12 -0
  48. package/dist/trace-ai/exp/exp-store/rollback-yaml.js +29 -0
  49. package/dist/trace-ai/exp/index.d.ts +2 -0
  50. package/dist/trace-ai/exp/index.js +68 -3
  51. package/dist/trace-ai/exp/info.js +1 -1
  52. package/dist/trace-ai/exp/patch/index.d.ts +13 -2
  53. package/dist/trace-ai/exp/patch/index.js +65 -10
  54. package/dist/trace-ai/exp/patch/kn-api-client.d.ts +40 -0
  55. package/dist/trace-ai/exp/patch/kn-api-client.js +14 -0
  56. package/dist/trace-ai/exp/patch/kn.d.ts +8 -0
  57. package/dist/trace-ai/exp/patch/kn.js +36 -0
  58. package/dist/trace-ai/exp/patch/skill-api-client.d.ts +17 -0
  59. package/dist/trace-ai/exp/patch/skill-api-client.js +14 -0
  60. package/dist/trace-ai/exp/patch/skill-content.d.ts +9 -0
  61. package/dist/trace-ai/exp/patch/skill-content.js +12 -0
  62. package/dist/trace-ai/exp/preflight.d.ts +77 -0
  63. package/dist/trace-ai/exp/preflight.js +148 -0
  64. package/dist/trace-ai/exp/providers/synthesizer-client.d.ts +3 -14
  65. package/dist/trace-ai/exp/providers/synthesizer-client.js +53 -35
  66. package/dist/trace-ai/exp/providers/triage-client.d.ts +15 -2
  67. package/dist/trace-ai/exp/providers/triage-client.js +143 -28
  68. package/dist/trace-ai/exp/run-preflight.d.ts +19 -0
  69. package/dist/trace-ai/exp/run-preflight.js +56 -0
  70. package/dist/trace-ai/exp/schemas.d.ts +402 -44
  71. package/dist/trace-ai/exp/schemas.js +131 -18
  72. package/dist/utils/deprecation.d.ts +1 -0
  73. package/dist/utils/deprecation.js +18 -0
  74. package/package.json +2 -1
@@ -1,443 +1,19 @@
1
- import { createInterface } from "node:readline";
1
+ // Internal CSV-import helpers formerly the `kweaver ds` command. The user-facing
2
+ // `ds` command group has been removed; these helpers are now consumed by
3
+ // `kweaver bkn create-from-csv` and by the import-csv tests.
4
+ //
5
+ // The flow still talks to the legacy `/datasources` backend endpoints. SDK-level
6
+ // shims for those endpoints remain available for users on older backends; see
7
+ // `api/datasources.ts` and `resources/datasources.ts` (both @deprecated).
2
8
  import { statSync } from "node:fs";
3
9
  import { glob } from "node:fs/promises";
4
10
  import { resolve as resolvePath } from "node:path";
5
- import { ensureValidToken, formatHttpError, with401RefreshRetry } from "../auth/oauth.js";
6
- import { testDatasource, createDatasource, listDatasources, getDatasource, deleteDatasource, } from "../api/datasources.js";
7
- import { listTablesWithColumns, scanMetadata } from "../api/vega.js";
8
- import { formatCallOutput } from "./call.js";
11
+ import { ensureValidToken, formatHttpError } from "../auth/oauth.js";
12
+ import { getDatasource } from "../api/datasources.js";
13
+ import { scanMetadata } from "../api/vega.js";
9
14
  import { resolveBusinessDomain } from "../config/store.js";
10
- import { assertVegaCatalogId } from "./bkn-utils.js";
11
15
  import { parseCsvFile, buildTableName, splitBatches, buildFieldMappings, buildDagBody, } from "./import-csv.js";
12
16
  import { executeDataflow } from "../api/dataflow.js";
13
- import { renderHelp } from "../help/format.js";
14
- const DS_HELP = renderHelp({
15
- tagline: "Manage datasources — list, get, delete, tables, connect, import-csv",
16
- usage: "kweaver ds <subcommand> [flags]",
17
- sections: [
18
- {
19
- title: "AVAILABLE COMMANDS",
20
- items: [
21
- { name: "list", desc: "List datasources" },
22
- { name: "get", desc: "Get datasource details" },
23
- { name: "delete", desc: "Delete a datasource" },
24
- { name: "tables", desc: "List tables with columns" },
25
- { name: "connect", desc: "Test, register and discover; reuses by (type,host,port,db,account) unless --force-new" },
26
- { name: "import-csv", desc: "Import CSV files into datasource tables via dataflow API" },
27
- ],
28
- },
29
- ],
30
- inheritedFlags: "--base-url, --token, --user, --help",
31
- examples: [
32
- "kweaver ds list --keyword mysql",
33
- "kweaver ds connect mysql 127.0.0.1 3306 mydb --account root --password ******",
34
- "kweaver ds tables <id> --keyword users",
35
- ],
36
- learnMore: ["Use `kweaver ds <subcommand> --help` for flag details"],
37
- });
38
- function confirmYes(prompt) {
39
- return new Promise((resolve) => {
40
- const rl = createInterface({ input: process.stdin, output: process.stdout });
41
- rl.question(`${prompt} [y/N] `, (answer) => {
42
- rl.close();
43
- const trimmed = answer.trim().toLowerCase();
44
- resolve(trimmed === "y" || trimmed === "yes");
45
- });
46
- });
47
- }
48
- function extractDatasourceId(body) {
49
- const parsed = JSON.parse(body);
50
- const item = Array.isArray(parsed) ? parsed[0] : parsed;
51
- if (!item || typeof item !== "object")
52
- return "";
53
- const id = item.id ?? item.ds_id;
54
- return id != null ? String(id) : "";
55
- }
56
- export async function runDsCommand(args) {
57
- const [subcommand, ...rest] = args;
58
- if (!subcommand || subcommand === "--help" || subcommand === "-h") {
59
- console.log(DS_HELP);
60
- return 0;
61
- }
62
- const dispatch = () => {
63
- if (subcommand === "list")
64
- return runDsListCommand(rest);
65
- if (subcommand === "get")
66
- return runDsGetCommand(rest);
67
- if (subcommand === "delete")
68
- return runDsDeleteCommand(rest);
69
- if (subcommand === "tables")
70
- return runDsTablesCommand(rest);
71
- if (subcommand === "connect")
72
- return runDsConnectCommand(rest);
73
- if (subcommand === "import-csv")
74
- return runDsImportCsvCommand(rest);
75
- return Promise.resolve(-1);
76
- };
77
- try {
78
- return await with401RefreshRetry(async () => {
79
- const code = await dispatch();
80
- if (code === -1) {
81
- console.error(`Unknown ds subcommand: ${subcommand}`);
82
- return 1;
83
- }
84
- return code;
85
- });
86
- }
87
- catch (error) {
88
- console.error(formatHttpError(error));
89
- return 1;
90
- }
91
- }
92
- export function parseDsListArgs(args) {
93
- let keyword;
94
- let type;
95
- let businessDomain = "";
96
- let pretty = true;
97
- for (let i = 0; i < args.length; i += 1) {
98
- const arg = args[i];
99
- if (arg === "--help" || arg === "-h")
100
- throw new Error("help");
101
- if (arg === "--keyword" && args[i + 1]) {
102
- keyword = args[++i];
103
- continue;
104
- }
105
- if (arg === "--type" && args[i + 1]) {
106
- type = args[++i];
107
- continue;
108
- }
109
- if ((arg === "-bd" || arg === "--biz-domain") && args[i + 1]) {
110
- businessDomain = args[++i];
111
- continue;
112
- }
113
- if (arg === "--pretty") {
114
- pretty = true;
115
- continue;
116
- }
117
- }
118
- if (!businessDomain)
119
- businessDomain = resolveBusinessDomain();
120
- return { keyword, type, businessDomain, pretty };
121
- }
122
- async function runDsListCommand(args) {
123
- try {
124
- const opts = parseDsListArgs(args);
125
- const token = await ensureValidToken();
126
- const body = await listDatasources({
127
- baseUrl: token.baseUrl,
128
- accessToken: token.accessToken,
129
- keyword: opts.keyword,
130
- type: opts.type,
131
- businessDomain: opts.businessDomain,
132
- });
133
- console.log(formatCallOutput(body, opts.pretty));
134
- return 0;
135
- }
136
- catch (error) {
137
- if (error instanceof Error && error.message === "help") {
138
- console.log(renderHelp({
139
- tagline: "List datasources",
140
- usage: "kweaver ds list [options]",
141
- flags: [
142
- { name: "--keyword <s>", desc: "Filter by keyword" },
143
- { name: "--type <s>", desc: "Filter by database type" },
144
- { name: "-bd, --biz-domain", desc: "Business domain (default: bd_public)" },
145
- { name: "--pretty", desc: "Pretty-print JSON (default)" },
146
- ],
147
- inheritedFlags: "--base-url, --token, --user, --help",
148
- }));
149
- return 0;
150
- }
151
- throw error;
152
- }
153
- }
154
- async function runDsGetCommand(args) {
155
- const id = args.find((a) => !a.startsWith("-"));
156
- if (!id) {
157
- console.error("Usage: kweaver ds get <id>");
158
- return 1;
159
- }
160
- const token = await ensureValidToken();
161
- const body = await getDatasource({
162
- baseUrl: token.baseUrl,
163
- accessToken: token.accessToken,
164
- id,
165
- });
166
- console.log(formatCallOutput(body, true));
167
- return 0;
168
- }
169
- async function runDsDeleteCommand(args) {
170
- let id = "";
171
- let yes = false;
172
- for (let i = 0; i < args.length; i += 1) {
173
- const arg = args[i];
174
- if (arg === "--yes" || arg === "-y")
175
- yes = true;
176
- else if (!arg.startsWith("-"))
177
- id = arg;
178
- }
179
- if (!id) {
180
- console.error("Usage: kweaver ds delete <id> [-y]");
181
- return 1;
182
- }
183
- if (!yes) {
184
- const confirmed = await confirmYes("Are you sure you want to delete this datasource?");
185
- if (!confirmed) {
186
- console.error("Aborted.");
187
- return 1;
188
- }
189
- }
190
- const token = await ensureValidToken();
191
- await deleteDatasource({
192
- baseUrl: token.baseUrl,
193
- accessToken: token.accessToken,
194
- id,
195
- });
196
- console.error(`Deleted ${id}`);
197
- return 0;
198
- }
199
- async function runDsTablesCommand(args) {
200
- let id = "";
201
- let keyword;
202
- let pretty = true;
203
- for (let i = 0; i < args.length; i += 1) {
204
- const arg = args[i];
205
- if (arg === "--keyword" && args[i + 1]) {
206
- keyword = args[++i];
207
- continue;
208
- }
209
- if (arg === "--pretty") {
210
- pretty = true;
211
- continue;
212
- }
213
- if (!arg.startsWith("-"))
214
- id = arg;
215
- }
216
- if (!id) {
217
- console.error("Usage: kweaver ds tables <vega-catalog-id> [--keyword X]\n" +
218
- " <vega-catalog-id> is a vega catalog id (use `kweaver vega catalog list` to find one;\n" +
219
- " legacy data-connection datasource UUIDs are no longer accepted).");
220
- return 1;
221
- }
222
- assertVegaCatalogId(id);
223
- const token = await ensureValidToken();
224
- const body = await listTablesWithColumns({
225
- baseUrl: token.baseUrl,
226
- accessToken: token.accessToken,
227
- id,
228
- keyword,
229
- });
230
- console.log(formatCallOutput(body, pretty));
231
- return 0;
232
- }
233
- export function findExistingDatasource(listBody, sig) {
234
- const parsed = JSON.parse(listBody);
235
- const entries = Array.isArray(parsed) ? parsed : (parsed.entries ?? []);
236
- const tupleMatch = entries.find((e) => e.id &&
237
- e.type === sig.type &&
238
- e.bin_data?.host === sig.host &&
239
- Number(e.bin_data?.port) === Number(sig.port) &&
240
- e.bin_data?.database_name === sig.database &&
241
- e.bin_data?.account === sig.account);
242
- if (tupleMatch) {
243
- return {
244
- id: String(tupleMatch.id),
245
- name: String(tupleMatch.name ?? ""),
246
- matchedByName: tupleMatch.name === sig.name,
247
- matchedByTuple: true,
248
- };
249
- }
250
- if (sig.name) {
251
- const nameMatch = entries.find((e) => e.id && e.name === sig.name);
252
- if (nameMatch) {
253
- return {
254
- id: String(nameMatch.id),
255
- name: String(nameMatch.name),
256
- matchedByName: true,
257
- matchedByTuple: false,
258
- };
259
- }
260
- }
261
- return undefined;
262
- }
263
- export function findDatasourceIdByName(listBody, name) {
264
- const parsed = JSON.parse(listBody);
265
- const entries = Array.isArray(parsed) ? parsed : (parsed.entries ?? []);
266
- const hit = entries.find((e) => e.id && e.name === name);
267
- return hit?.id ? String(hit.id) : undefined;
268
- }
269
- function isDuplicateNameError(err) {
270
- if (!err || typeof err !== "object")
271
- return false;
272
- // HttpError.message is just "HTTP 400 ..."; the description lives in body.
273
- const status = "status" in err ? Number(err.status) : NaN;
274
- const body = "body" in err ? String(err.body) : "";
275
- if (status !== 400)
276
- return false;
277
- return /数据源名称已存在|datasource name.*exist|already exists/i.test(body);
278
- }
279
- async function runDsConnectCommand(args) {
280
- let dbType = "";
281
- let host = "";
282
- let port = 0;
283
- let database = "";
284
- let account = "";
285
- let password = "";
286
- let schema;
287
- let name;
288
- let forceNew = false;
289
- for (let i = 0; i < args.length; i += 1) {
290
- const arg = args[i];
291
- if (arg === "--account" && args[i + 1]) {
292
- account = args[++i];
293
- continue;
294
- }
295
- if (arg === "--password" && args[i + 1]) {
296
- password = args[++i];
297
- continue;
298
- }
299
- if (arg === "--schema" && args[i + 1]) {
300
- schema = args[++i];
301
- continue;
302
- }
303
- if (arg === "--name" && args[i + 1]) {
304
- name = args[++i];
305
- continue;
306
- }
307
- if (arg === "--force-new") {
308
- forceNew = true;
309
- continue;
310
- }
311
- if (arg === "--reuse-existing") {
312
- forceNew = false;
313
- continue;
314
- }
315
- if (!arg.startsWith("-")) {
316
- if (!dbType)
317
- dbType = arg;
318
- else if (!host)
319
- host = arg;
320
- else if (port === 0)
321
- port = parseInt(arg, 10);
322
- else if (!database)
323
- database = arg;
324
- }
325
- }
326
- if (!dbType || !host || !database || !account || !password) {
327
- console.error("Usage: kweaver ds connect <db_type> <host> <port> <database> --account X --password Y [--schema Z] [--name N] [--reuse-existing|--force-new]");
328
- return 1;
329
- }
330
- if (Number.isNaN(port) || port < 1) {
331
- console.error("Invalid port");
332
- return 1;
333
- }
334
- const token = await ensureValidToken();
335
- const base = { baseUrl: token.baseUrl, accessToken: token.accessToken };
336
- const dsName = name ?? database;
337
- // Pre-flight dedup: connection-tuple match is the silent-orphan vector.
338
- // Backend already rejects duplicate names with 400, but won't notice
339
- // tuple collisions, so we own that check.
340
- if (!forceNew) {
341
- const listBody = await listDatasources({ ...base });
342
- const hit = findExistingDatasource(listBody, {
343
- type: dbType,
344
- host,
345
- port,
346
- database,
347
- account,
348
- name: dsName,
349
- });
350
- if (hit) {
351
- const why = hit.matchedByTuple
352
- ? "matched by (type,host,port,database,account)"
353
- : "matched by --name";
354
- console.error(`Reusing existing datasource ${hit.id} (${hit.name}); ${why}. Use --force-new to override.`);
355
- return printDsConnectOutput(base, hit.id);
356
- }
357
- }
358
- console.error("Testing connectivity ...");
359
- await testDatasource({
360
- ...base,
361
- type: dbType,
362
- host,
363
- port,
364
- database,
365
- account,
366
- password,
367
- schema,
368
- });
369
- let dsId = "";
370
- try {
371
- const createBody = await createDatasource({
372
- ...base,
373
- name: dsName,
374
- type: dbType,
375
- host,
376
- port,
377
- database,
378
- account,
379
- password,
380
- schema,
381
- });
382
- dsId = extractDatasourceId(createBody);
383
- }
384
- catch (err) {
385
- // Backend checks name uniqueness but not tuple. If we raced another caller
386
- // (or tuple match got disabled by --force-new and the name still collides),
387
- // turn the raw 400 into a useful pointer to the existing id.
388
- if (isDuplicateNameError(err)) {
389
- // Backend rejected the name; look it up specifically (not by tuple —
390
- // sibling ds sharing the same connection would mislead the pointer).
391
- const listBody = await listDatasources({ ...base });
392
- const existingId = findDatasourceIdByName(listBody, dsName);
393
- if (existingId) {
394
- console.error(`Datasource name '${dsName}' already exists as ${existingId}. Re-run without --force-new to reuse it, or pick a different --name.`);
395
- return 1;
396
- }
397
- }
398
- throw err;
399
- }
400
- if (!dsId) {
401
- console.error("Failed to get datasource ID from create response");
402
- return 1;
403
- }
404
- return printDsConnectOutput(base, dsId);
405
- }
406
- async function printDsConnectOutput(base, dsId) {
407
- const tablesBody = await listTablesWithColumns({ ...base, id: dsId });
408
- const tables = JSON.parse(tablesBody);
409
- const output = {
410
- datasource_id: dsId,
411
- tables: tables.map((t) => ({
412
- name: t.name,
413
- ...(t.primaryKeys && t.primaryKeys.length > 0 ? { primary_keys: t.primaryKeys } : {}),
414
- columns: t.columns.map((c) => ({
415
- name: c.name,
416
- type: c.type,
417
- comment: c.comment,
418
- ...(c.isPrimaryKey ? { is_primary_key: true } : {}),
419
- })),
420
- })),
421
- };
422
- console.log(JSON.stringify(output, null, 2));
423
- return 0;
424
- }
425
- // ── import-csv ────────────────────────────────────────────────────────────────
426
- const IMPORT_CSV_HELP = renderHelp({
427
- tagline: "Import CSV files into datasource tables via dataflow API",
428
- usage: "kweaver ds import-csv <ds-id> --files <glob_or_list> [flags]",
429
- flags: [
430
- { name: "--files <s>", desc: "CSV file paths — comma-separated or glob pattern (required)" },
431
- { name: "--table-prefix <s>", desc: "Table name prefix (default: none)" },
432
- { name: "--batch-size <n>", desc: "Rows per batch (default: 500, range: 1-10000)" },
433
- { name: "-bd, --biz-domain <s>", desc: "Business domain (default: bd_public)" },
434
- ],
435
- inheritedFlags: "--base-url, --token, --user, --help",
436
- examples: [
437
- "kweaver ds import-csv ds-123 --files './data/*.csv'",
438
- "kweaver ds import-csv ds-123 --files ./a.csv,./b.csv --table-prefix raw_ --batch-size 1000",
439
- ],
440
- });
441
17
  export function parseImportCsvArgs(args) {
442
18
  let datasourceId = "";
443
19
  let files = "";
@@ -508,13 +84,15 @@ export async function runDsImportCsv(args) {
508
84
  }
509
85
  catch (error) {
510
86
  if (error instanceof Error && error.message === "help") {
511
- console.log(IMPORT_CSV_HELP);
87
+ // The user-facing `ds import-csv` CLI is gone; this path is only reachable
88
+ // if a caller explicitly passes --help into the helper. Print a redirect.
89
+ console.error("CSV import is now an internal helper. Use `kweaver bkn create-from-csv` instead.");
512
90
  return { code: 0, tables: [], failed: [], tableColumns: {}, sampleRows: {} };
513
91
  }
514
92
  throw error;
515
93
  }
516
94
  if (!options.datasourceId) {
517
- console.error("Usage: kweaver ds import-csv <ds-id> --files <glob_or_list> [options]");
95
+ console.error("runDsImportCsv: missing datasource/catalog id (positional argument required)");
518
96
  return { code: 1, tables: [], failed: [], tableColumns: {}, sampleRows: {} };
519
97
  }
520
98
  if (!options.files) {
@@ -611,9 +189,10 @@ export async function runDsImportCsv(args) {
611
189
  if (failed.length > 0) {
612
190
  console.error(`Failed tables: ${failed.join(", ")}`);
613
191
  }
614
- // Refresh the platform metadata catalog so the freshly imported tables
615
- // are visible to ds tables / bkn create-from-ds without manual scan.
616
- // Best-effort: scan failures shouldn't mask a successful import.
192
+ // Refresh the platform metadata catalog so the freshly imported tables are
193
+ // visible to downstream commands (e.g. `bkn create-from-catalog`) without
194
+ // requiring a manual scan. Best-effort: scan failures don't mask a
195
+ // successful import.
617
196
  if (succeeded.length > 0) {
618
197
  process.stderr.write("Scanning datasource metadata ...\n");
619
198
  try {
@@ -630,12 +209,3 @@ export async function runDsImportCsv(args) {
630
209
  }
631
210
  return { code: failed.length > 0 ? 1 : 0, tables: succeeded, failed, tableColumns, sampleRows };
632
211
  }
633
- export async function runDsImportCsvCommand(args) {
634
- const result = await runDsImportCsv(args);
635
- console.log(JSON.stringify({
636
- tables: result.tables,
637
- failed: result.failed,
638
- summary: { succeeded: result.tables.length, failed: result.failed.length },
639
- }, null, 2));
640
- return result.code;
641
- }
@@ -30,6 +30,12 @@ export interface ExploreMeta {
30
30
  id: string;
31
31
  name: string;
32
32
  }>;
33
+ conceptGroups: Array<{
34
+ id: string;
35
+ name: string;
36
+ color?: string;
37
+ objectTypeIds: string[];
38
+ }>;
33
39
  }
34
40
  export interface ExploreOt {
35
41
  id: string;
@@ -63,7 +69,7 @@ export interface ExploreStats {
63
69
  }
64
70
  export declare const EXPLORE_BOOTSTRAP_RETRY_DELAY_MS = 300;
65
71
  export declare const EXPLORE_BOOTSTRAP_MAX_ATTEMPTS = 2;
66
- export declare function buildMeta(knRaw: string, otRaw: string, rtRaw: string, atRaw: string): ExploreMeta;
72
+ export declare function buildMeta(knRaw: string, otRaw: string, rtRaw: string, atRaw: string, cgRaw?: string): ExploreMeta;
67
73
  export declare function isRetryableExploreBootstrapError(error: unknown): boolean;
68
74
  export declare function loadExploreMetaWithRetry(token: {
69
75
  baseUrl: string;
@@ -2,11 +2,12 @@ import { HttpError } from "../utils/http.js";
2
2
  import { getKnowledgeNetwork, listObjectTypes, listRelationTypes, listActionTypes, } from "../api/knowledge-networks.js";
3
3
  import { objectTypeQuery, objectTypeProperties, subgraph } from "../api/ontology-query.js";
4
4
  import { semanticSearch } from "../api/semantic-search.js";
5
+ import { listConceptGroups } from "../api/bkn-backend.js";
5
6
  // ── Constants ───────────────────────────────────────────────────────────────
6
7
  export const EXPLORE_BOOTSTRAP_RETRY_DELAY_MS = 300;
7
8
  export const EXPLORE_BOOTSTRAP_MAX_ATTEMPTS = 2;
8
9
  // ── Meta builder ────────────────────────────────────────────────────────────
9
- export function buildMeta(knRaw, otRaw, rtRaw, atRaw) {
10
+ export function buildMeta(knRaw, otRaw, rtRaw, atRaw, cgRaw) {
10
11
  const kn = JSON.parse(knRaw);
11
12
  const otParsed = JSON.parse(otRaw);
12
13
  const otItems = (Array.isArray(otParsed) ? otParsed
@@ -54,8 +55,29 @@ export function buildMeta(knRaw, otRaw, rtRaw, atRaw) {
54
55
  id: a.id,
55
56
  name: a.name,
56
57
  })),
58
+ conceptGroups: parseConceptGroups(cgRaw),
57
59
  };
58
60
  }
61
+ function parseConceptGroups(cgRaw) {
62
+ if (!cgRaw)
63
+ return [];
64
+ try {
65
+ const parsed = JSON.parse(cgRaw);
66
+ const items = (Array.isArray(parsed) ? parsed
67
+ : Array.isArray(parsed.entries) ? parsed.entries
68
+ : Array.isArray(parsed.concept_groups) ? parsed.concept_groups
69
+ : []);
70
+ return items.map((g) => ({
71
+ id: g.id,
72
+ name: g.name,
73
+ ...(g.color ? { color: g.color } : {}),
74
+ objectTypeIds: Array.isArray(g.object_type_ids) ? g.object_type_ids : [],
75
+ }));
76
+ }
77
+ catch {
78
+ return [];
79
+ }
80
+ }
59
81
  // ── Bootstrap helpers ───────────────────────────────────────────────────────
60
82
  function getErrorMessage(error) {
61
83
  const parts = [];
@@ -100,7 +122,7 @@ function sleep(ms) {
100
122
  export async function loadExploreMetaWithRetry(token, knId, businessDomain) {
101
123
  for (let attempt = 1; attempt <= EXPLORE_BOOTSTRAP_MAX_ATTEMPTS; attempt++) {
102
124
  try {
103
- const [knRaw, otRaw, rtRaw, atRaw] = await Promise.all([
125
+ const [knRaw, otRaw, rtRaw, atRaw, cgRaw] = await Promise.all([
104
126
  getKnowledgeNetwork({
105
127
  baseUrl: token.baseUrl,
106
128
  accessToken: token.accessToken,
@@ -126,8 +148,15 @@ export async function loadExploreMetaWithRetry(token, knId, businessDomain) {
126
148
  knId,
127
149
  businessDomain,
128
150
  }),
151
+ // Concept groups are optional — don't fail the whole load if missing
152
+ listConceptGroups({
153
+ baseUrl: token.baseUrl,
154
+ accessToken: token.accessToken,
155
+ knId,
156
+ businessDomain,
157
+ }).catch(() => ""),
129
158
  ]);
130
- return buildMeta(knRaw, otRaw, rtRaw, atRaw);
159
+ return buildMeta(knRaw, otRaw, rtRaw, atRaw, cgRaw);
131
160
  }
132
161
  catch (error) {
133
162
  if (attempt >= EXPLORE_BOOTSTRAP_MAX_ATTEMPTS || !isRetryableExploreBootstrapError(error)) {
@@ -1,4 +1,11 @@
1
1
  import type { ClientContext } from "../client.js";
2
+ /**
3
+ * @deprecated Datasource is a legacy concept. The platform has migrated
4
+ * data-connection management to vega catalogs. Use `client.vega.catalogs`
5
+ * for catalog CRUD and `client.resources` for resource queries instead.
6
+ * This class is kept as a thin back-compat layer and may be removed in a
7
+ * future major release.
8
+ */
2
9
  export declare class DataSourcesResource {
3
10
  private readonly ctx;
4
11
  constructor(ctx: ClientContext);
@@ -1,5 +1,12 @@
1
1
  import { testDatasource, createDatasource, listDatasources, getDatasource, deleteDatasource, listTables, } from "../api/datasources.js";
2
2
  import { listTablesWithColumns, scanMetadata } from "../api/vega.js";
3
+ /**
4
+ * @deprecated Datasource is a legacy concept. The platform has migrated
5
+ * data-connection management to vega catalogs. Use `client.vega.catalogs`
6
+ * for catalog CRUD and `client.resources` for resource queries instead.
7
+ * This class is kept as a thin back-compat layer and may be removed in a
8
+ * future major release.
9
+ */
3
10
  export class DataSourcesResource {
4
11
  ctx;
5
12
  constructor(ctx) {