@yejiming/dsh-data-agent 0.0.12 → 0.1.0

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 (60) hide show
  1. package/README.en.md +97 -16
  2. package/README.md +97 -16
  3. package/conformance/dsh-ecosystem/baseline.json +59 -0
  4. package/conformance/dsh-ecosystem/dependencies.json +41 -0
  5. package/conformance/dsh-ecosystem/fixtures/host-degraded.fixture.json +12 -0
  6. package/conformance/dsh-ecosystem/fixtures/host-eligible.fixture.json +13 -0
  7. package/conformance/dsh-ecosystem/fixtures/host-rejected.fixture.json +12 -0
  8. package/conformance/dsh-ecosystem/fixtures/profiles/native-only/package.json +8 -0
  9. package/conformance/dsh-ecosystem/fixtures/profiles/native-plus-adapter/package.json +9 -0
  10. package/conformance/dsh-ecosystem/inventory.json +100 -0
  11. package/conformance/dsh-ecosystem/restrictions.json +20 -0
  12. package/cordis.patch.yml +6 -3
  13. package/dsh-plugin.json +72 -0
  14. package/lib/catalog-DEJqOXRo.js +1944 -0
  15. package/lib/catalog-identity-CVftmvQL.js +96 -0
  16. package/lib/client.js +3465 -138
  17. package/lib/client.js.map +1 -1
  18. package/lib/command-CzzSPmag.js +1719 -0
  19. package/lib/command.js +2 -2
  20. package/lib/{connections-5sfdEDsG.js → connections-CFXOZTHZ.js} +964 -68
  21. package/lib/ecosystem.js +19 -0
  22. package/lib/index.js +392 -34
  23. package/lib/routes.js +260 -8
  24. package/lib/{tool-DgL0fBfj.js → tool-DNkywSph.js} +367 -168
  25. package/lib/tool.js +1 -1
  26. package/lib/types/catalog-adapters.d.ts +52 -0
  27. package/lib/types/catalog-ai.d.ts +49 -0
  28. package/lib/types/catalog-command.d.ts +28 -0
  29. package/lib/types/catalog-identity.d.ts +23 -0
  30. package/lib/types/catalog-storage.d.ts +265 -0
  31. package/lib/types/catalog-tools.d.ts +5 -0
  32. package/lib/types/catalog-tui.d.ts +18 -0
  33. package/lib/types/catalog-types.d.ts +1376 -0
  34. package/lib/types/catalog.d.ts +59 -0
  35. package/lib/types/client/CatalogPanel.d.ts +15 -0
  36. package/lib/types/client/DataAgentWorkbench.d.ts +1 -2
  37. package/lib/types/client/QueryResultTable.d.ts +13 -0
  38. package/lib/types/client/catalog-client.d.ts +57 -0
  39. package/lib/types/client/locales.d.ts +290 -0
  40. package/lib/types/client/persistence.d.ts +3 -1
  41. package/lib/types/client/query-export.d.ts +11 -0
  42. package/lib/types/client-discovery.d.ts +3 -4
  43. package/lib/types/clients.d.ts +14 -8
  44. package/lib/types/command.d.ts +16 -5
  45. package/lib/types/connections.d.ts +42 -4
  46. package/lib/types/database-types.d.ts +23 -0
  47. package/lib/types/defaults.d.ts +26 -0
  48. package/lib/types/ecosystem.d.ts +13 -0
  49. package/lib/types/index.d.ts +58 -15
  50. package/lib/types/query.d.ts +13 -11
  51. package/lib/types/sql.d.ts +9 -1
  52. package/lib/types/storage.d.ts +11 -1
  53. package/lib/types/structured-read.d.ts +2 -2
  54. package/lib/types/structured.d.ts +1 -1
  55. package/lib/types/tool.d.ts +5 -5
  56. package/lib/types/tui-connection-form.d.ts +21 -12
  57. package/package.json +30 -4
  58. package/preset/data-agent/agent.cordis.yml +13 -2
  59. package/lib/command-DuCpwVbl.js +0 -875
  60. package/lib/defaults-DP4RyRh1.js +0 -21
package/lib/client.js CHANGED
@@ -19,7 +19,121 @@ window.__ModuleLoader__.load({
19
19
  let react = require("react");
20
20
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
21
21
  let react_jsx_runtime = require("react/jsx-runtime");
22
+ //#region src/database-types.ts
23
+ /**
24
+ * Browser-safe database type descriptors shared by every DSH surface.
25
+ * Keep this module dependency-free: server-only client/process details belong
26
+ * in the database adapters, not in Web or persistence bundles.
27
+ */
28
+ const DATABASE_TYPES = [
29
+ "mysql",
30
+ "postgres",
31
+ "sqlite",
32
+ "oracle",
33
+ "hive",
34
+ "impala",
35
+ "clickhouse",
36
+ "doris",
37
+ "sqlserver"
38
+ ];
39
+ const DATABASE_TYPE_DESCRIPTORS = {
40
+ mysql: {
41
+ type: "mysql",
42
+ label: "MySQL",
43
+ localeKey: "type.mysql",
44
+ defaultPort: 3306,
45
+ defaultUser: "root",
46
+ fileBased: false
47
+ },
48
+ postgres: {
49
+ type: "postgres",
50
+ label: "PostgreSQL",
51
+ localeKey: "type.postgres",
52
+ defaultPort: 5432,
53
+ defaultUser: "postgres",
54
+ fileBased: false
55
+ },
56
+ sqlite: {
57
+ type: "sqlite",
58
+ label: "SQLite",
59
+ localeKey: "type.sqlite",
60
+ defaultPort: 0,
61
+ defaultUser: "",
62
+ fileBased: true
63
+ },
64
+ oracle: {
65
+ type: "oracle",
66
+ label: "Oracle",
67
+ localeKey: "type.oracle",
68
+ defaultPort: 1521,
69
+ defaultUser: "",
70
+ fileBased: false
71
+ },
72
+ hive: {
73
+ type: "hive",
74
+ label: "Hive",
75
+ localeKey: "type.hive",
76
+ defaultPort: 1e4,
77
+ defaultUser: "",
78
+ fileBased: false
79
+ },
80
+ impala: {
81
+ type: "impala",
82
+ label: "Impala",
83
+ localeKey: "type.impala",
84
+ defaultPort: 21050,
85
+ defaultUser: "",
86
+ fileBased: false
87
+ },
88
+ clickhouse: {
89
+ type: "clickhouse",
90
+ label: "ClickHouse",
91
+ localeKey: "type.clickhouse",
92
+ defaultPort: 8123,
93
+ securePort: 8443,
94
+ defaultUser: "default",
95
+ fileBased: false
96
+ },
97
+ doris: {
98
+ type: "doris",
99
+ label: "Apache Doris",
100
+ localeKey: "type.doris",
101
+ defaultPort: 9030,
102
+ defaultUser: "root",
103
+ fileBased: false
104
+ },
105
+ sqlserver: {
106
+ type: "sqlserver",
107
+ label: "SQL Server",
108
+ localeKey: "type.sqlserver",
109
+ defaultPort: 1433,
110
+ defaultUser: "sa",
111
+ fileBased: false
112
+ }
113
+ };
114
+ function isDatabaseType(value) {
115
+ return typeof value === "string" && DATABASE_TYPES.includes(value);
116
+ }
117
+ function databaseTypeDescriptor(type) {
118
+ return DATABASE_TYPE_DESCRIPTORS[type];
119
+ }
120
+ function defaultDatabasePort(type, secure = false) {
121
+ const descriptor = DATABASE_TYPE_DESCRIPTORS[type];
122
+ return secure && descriptor.securePort !== void 0 ? descriptor.securePort : descriptor.defaultPort;
123
+ }
124
+ //#endregion
22
125
  //#region src/client/persistence.ts
126
+ /**
127
+ * Connection-config persistence for the database workbench. The most recent
128
+ * successful connection (type/host/port/user/database/password) is kept in
129
+ * localStorage under one key so remounts and restarts can restore the form
130
+ * and auto-reconnect (the server persists only non-secret profiles/bindings).
131
+ *
132
+ * Security note: the password is persisted in PLAIN TEXT by explicit user
133
+ * decision (local single-user scenario) — see README 安全说明. The storage
134
+ * key is versioned so a future shape change can migrate or ignore old data.
135
+ * @module @yejiming/dsh-data-agent/persistence
136
+ */
23
137
  /** localStorage key holding the most recent connection configuration. */
24
138
  const CONNECTION_STORAGE_KEY = "dsh-data-agent.connection.v1";
25
139
  /** The default storage face (localStorage; unavailable → degraded no-op). */
@@ -38,7 +152,7 @@ window.__ModuleLoader__.load({
38
152
  if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
39
153
  const candidate = value;
40
154
  const type = candidate.type;
41
- if (type !== "mysql" && type !== "postgres" && type !== "sqlite" && type !== "oracle" && type !== "hive" && type !== "impala") return null;
155
+ if (!isDatabaseType(type)) return null;
42
156
  const database = candidate.database;
43
157
  if (typeof database !== "string") return null;
44
158
  const saved = {
@@ -50,6 +164,7 @@ window.__ModuleLoader__.load({
50
164
  if (typeof candidate.port === "number" && Number.isInteger(candidate.port)) saved.port = candidate.port;
51
165
  if (typeof candidate.user === "string") saved.user = candidate.user;
52
166
  if (typeof candidate.readonly === "boolean") saved.readonly = candidate.readonly;
167
+ if (type === "clickhouse" && typeof candidate.secure === "boolean") saved.secure = candidate.secure;
53
168
  if (typeof candidate.passwordRef === "string" && candidate.passwordRef.length > 0) {
54
169
  saved.passwordRef = candidate.passwordRef;
55
170
  saved.credentialMode = "reference";
@@ -92,8 +207,801 @@ window.__ModuleLoader__.load({
92
207
  }
93
208
  }
94
209
  //#endregion
210
+ //#region node_modules/fflate/esm/browser.js
211
+ var u8 = Uint8Array;
212
+ var u16 = Uint16Array;
213
+ var i32 = Int32Array;
214
+ var fleb = new u8([
215
+ 0,
216
+ 0,
217
+ 0,
218
+ 0,
219
+ 0,
220
+ 0,
221
+ 0,
222
+ 0,
223
+ 1,
224
+ 1,
225
+ 1,
226
+ 1,
227
+ 2,
228
+ 2,
229
+ 2,
230
+ 2,
231
+ 3,
232
+ 3,
233
+ 3,
234
+ 3,
235
+ 4,
236
+ 4,
237
+ 4,
238
+ 4,
239
+ 5,
240
+ 5,
241
+ 5,
242
+ 5,
243
+ 0,
244
+ 0,
245
+ 0,
246
+ 0
247
+ ]);
248
+ var fdeb = new u8([
249
+ 0,
250
+ 0,
251
+ 0,
252
+ 0,
253
+ 1,
254
+ 1,
255
+ 2,
256
+ 2,
257
+ 3,
258
+ 3,
259
+ 4,
260
+ 4,
261
+ 5,
262
+ 5,
263
+ 6,
264
+ 6,
265
+ 7,
266
+ 7,
267
+ 8,
268
+ 8,
269
+ 9,
270
+ 9,
271
+ 10,
272
+ 10,
273
+ 11,
274
+ 11,
275
+ 12,
276
+ 12,
277
+ 13,
278
+ 13,
279
+ 0,
280
+ 0
281
+ ]);
282
+ var clim = new u8([
283
+ 16,
284
+ 17,
285
+ 18,
286
+ 0,
287
+ 8,
288
+ 7,
289
+ 9,
290
+ 6,
291
+ 10,
292
+ 5,
293
+ 11,
294
+ 4,
295
+ 12,
296
+ 3,
297
+ 13,
298
+ 2,
299
+ 14,
300
+ 1,
301
+ 15
302
+ ]);
303
+ var freb = function(eb, start) {
304
+ var b = new u16(31);
305
+ for (var i = 0; i < 31; ++i) b[i] = start += 1 << eb[i - 1];
306
+ var r = new i32(b[30]);
307
+ for (var i = 1; i < 30; ++i) for (var j = b[i]; j < b[i + 1]; ++j) r[j] = j - b[i] << 5 | i;
308
+ return {
309
+ b,
310
+ r
311
+ };
312
+ };
313
+ var _a$1 = freb(fleb, 2);
314
+ var fl = _a$1.b;
315
+ var revfl = _a$1.r;
316
+ fl[28] = 258, revfl[258] = 28;
317
+ var _b$1 = freb(fdeb, 0);
318
+ _b$1.b;
319
+ var revfd = _b$1.r;
320
+ var rev = new u16(32768);
321
+ for (var i = 0; i < 32768; ++i) {
322
+ var x = (i & 43690) >> 1 | (i & 21845) << 1;
323
+ x = (x & 52428) >> 2 | (x & 13107) << 2;
324
+ x = (x & 61680) >> 4 | (x & 3855) << 4;
325
+ rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;
326
+ }
327
+ var hMap = (function(cd, mb, r) {
328
+ var s = cd.length;
329
+ var i = 0;
330
+ var l = new u16(mb);
331
+ for (; i < s; ++i) if (cd[i]) ++l[cd[i] - 1];
332
+ var le = new u16(mb);
333
+ for (i = 1; i < mb; ++i) le[i] = le[i - 1] + l[i - 1] << 1;
334
+ var co;
335
+ if (r) {
336
+ co = new u16(1 << mb);
337
+ var rvb = 15 - mb;
338
+ for (i = 0; i < s; ++i) if (cd[i]) {
339
+ var sv = i << 4 | cd[i];
340
+ var r_1 = mb - cd[i];
341
+ var v = le[cd[i] - 1]++ << r_1;
342
+ for (var m = v | (1 << r_1) - 1; v <= m; ++v) co[rev[v] >> rvb] = sv;
343
+ }
344
+ } else {
345
+ co = new u16(s);
346
+ for (i = 0; i < s; ++i) if (cd[i]) co[i] = rev[le[cd[i] - 1]++] >> 15 - cd[i];
347
+ }
348
+ return co;
349
+ });
350
+ var flt = new u8(288);
351
+ for (var i = 0; i < 144; ++i) flt[i] = 8;
352
+ for (var i = 144; i < 256; ++i) flt[i] = 9;
353
+ for (var i = 256; i < 280; ++i) flt[i] = 7;
354
+ for (var i = 280; i < 288; ++i) flt[i] = 8;
355
+ var fdt = new u8(32);
356
+ for (var i = 0; i < 32; ++i) fdt[i] = 5;
357
+ var flm = /*#__PURE__*/ hMap(flt, 9, 0);
358
+ var fdm = /*#__PURE__*/ hMap(fdt, 5, 0);
359
+ var shft = function(p) {
360
+ return (p + 7) / 8 | 0;
361
+ };
362
+ var slc = function(v, s, e) {
363
+ if (s == null || s < 0) s = 0;
364
+ if (e == null || e > v.length) e = v.length;
365
+ return new u8(v.subarray(s, e));
366
+ };
367
+ var ec = [
368
+ "unexpected EOF",
369
+ "invalid block type",
370
+ "invalid length/literal",
371
+ "invalid distance",
372
+ "stream finished",
373
+ "no stream handler",
374
+ ,
375
+ "no callback",
376
+ "invalid UTF-8 data",
377
+ "extra field too long",
378
+ "date not in range 1980-2099",
379
+ "filename too long",
380
+ "stream finishing",
381
+ "invalid zip data"
382
+ ];
383
+ var err = function(ind, msg, nt) {
384
+ var e = new Error(msg || ec[ind]);
385
+ e.code = ind;
386
+ if (Error.captureStackTrace) Error.captureStackTrace(e, err);
387
+ if (!nt) throw e;
388
+ return e;
389
+ };
390
+ var wbits = function(d, p, v) {
391
+ v <<= p & 7;
392
+ var o = p / 8 | 0;
393
+ d[o] |= v;
394
+ d[o + 1] |= v >> 8;
395
+ };
396
+ var wbits16 = function(d, p, v) {
397
+ v <<= p & 7;
398
+ var o = p / 8 | 0;
399
+ d[o] |= v;
400
+ d[o + 1] |= v >> 8;
401
+ d[o + 2] |= v >> 16;
402
+ };
403
+ var hTree = function(d, mb) {
404
+ var t = [];
405
+ for (var i = 0; i < d.length; ++i) if (d[i]) t.push({
406
+ s: i,
407
+ f: d[i]
408
+ });
409
+ var s = t.length;
410
+ var t2 = t.slice();
411
+ if (!s) return {
412
+ t: et,
413
+ l: 0
414
+ };
415
+ if (s == 1) {
416
+ var v = new u8(t[0].s + 1);
417
+ v[t[0].s] = 1;
418
+ return {
419
+ t: v,
420
+ l: 1
421
+ };
422
+ }
423
+ t.sort(function(a, b) {
424
+ return a.f - b.f;
425
+ });
426
+ t.push({
427
+ s: -1,
428
+ f: 25001
429
+ });
430
+ var l = t[0], r = t[1], i0 = 0, i1 = 1, i2 = 2;
431
+ t[0] = {
432
+ s: -1,
433
+ f: l.f + r.f,
434
+ l,
435
+ r
436
+ };
437
+ while (i1 != s - 1) {
438
+ l = t[t[i0].f < t[i2].f ? i0++ : i2++];
439
+ r = t[i0 != i1 && t[i0].f < t[i2].f ? i0++ : i2++];
440
+ t[i1++] = {
441
+ s: -1,
442
+ f: l.f + r.f,
443
+ l,
444
+ r
445
+ };
446
+ }
447
+ var maxSym = t2[0].s;
448
+ for (var i = 1; i < s; ++i) if (t2[i].s > maxSym) maxSym = t2[i].s;
449
+ var tr = new u16(maxSym + 1);
450
+ var mbt = ln(t[i1 - 1], tr, 0);
451
+ if (mbt > mb) {
452
+ var i = 0, dt = 0;
453
+ var lft = mbt - mb, cst = 1 << lft;
454
+ t2.sort(function(a, b) {
455
+ return tr[b.s] - tr[a.s] || a.f - b.f;
456
+ });
457
+ for (; i < s; ++i) {
458
+ var i2_1 = t2[i].s;
459
+ if (tr[i2_1] > mb) {
460
+ dt += cst - (1 << mbt - tr[i2_1]);
461
+ tr[i2_1] = mb;
462
+ } else break;
463
+ }
464
+ dt >>= lft;
465
+ while (dt > 0) {
466
+ var i2_2 = t2[i].s;
467
+ if (tr[i2_2] < mb) dt -= 1 << mb - tr[i2_2]++ - 1;
468
+ else ++i;
469
+ }
470
+ for (; i >= 0 && dt; --i) {
471
+ var i2_3 = t2[i].s;
472
+ if (tr[i2_3] == mb) {
473
+ --tr[i2_3];
474
+ ++dt;
475
+ }
476
+ }
477
+ mbt = mb;
478
+ }
479
+ return {
480
+ t: new u8(tr),
481
+ l: mbt
482
+ };
483
+ };
484
+ var ln = function(n, l, d) {
485
+ return n.s == -1 ? Math.max(ln(n.l, l, d + 1), ln(n.r, l, d + 1)) : l[n.s] = d;
486
+ };
487
+ var lc = function(c) {
488
+ var s = c.length;
489
+ while (s && !c[--s]);
490
+ var cl = new u16(++s);
491
+ var cli = 0, cln = c[0], cls = 1;
492
+ var w = function(v) {
493
+ cl[cli++] = v;
494
+ };
495
+ for (var i = 1; i <= s; ++i) if (c[i] == cln && i != s) ++cls;
496
+ else {
497
+ if (!cln && cls > 2) {
498
+ for (; cls > 138; cls -= 138) w(32754);
499
+ if (cls > 2) {
500
+ w(cls > 10 ? cls - 11 << 5 | 28690 : cls - 3 << 5 | 12305);
501
+ cls = 0;
502
+ }
503
+ } else if (cls > 3) {
504
+ w(cln), --cls;
505
+ for (; cls > 6; cls -= 6) w(8304);
506
+ if (cls > 2) w(cls - 3 << 5 | 8208), cls = 0;
507
+ }
508
+ while (cls--) w(cln);
509
+ cls = 1;
510
+ cln = c[i];
511
+ }
512
+ return {
513
+ c: cl.subarray(0, cli),
514
+ n: s
515
+ };
516
+ };
517
+ var clen = function(cf, cl) {
518
+ var l = 0;
519
+ for (var i = 0; i < cl.length; ++i) l += cf[i] * cl[i];
520
+ return l;
521
+ };
522
+ var wfblk = function(out, pos, dat) {
523
+ var s = dat.length;
524
+ var o = shft(pos + 2);
525
+ out[o] = s & 255;
526
+ out[o + 1] = s >> 8;
527
+ out[o + 2] = out[o] ^ 255;
528
+ out[o + 3] = out[o + 1] ^ 255;
529
+ for (var i = 0; i < s; ++i) out[o + i + 4] = dat[i];
530
+ return (o + 4 + s) * 8;
531
+ };
532
+ var wblk = function(dat, out, final, syms, lf, df, eb, li, bs, bl, p) {
533
+ wbits(out, p++, final);
534
+ ++lf[256];
535
+ var _a = hTree(lf, 15), dlt = _a.t, mlb = _a.l;
536
+ var _b = hTree(df, 15), ddt = _b.t, mdb = _b.l;
537
+ var _c = lc(dlt), lclt = _c.c, nlc = _c.n;
538
+ var _d = lc(ddt), lcdt = _d.c, ndc = _d.n;
539
+ var lcfreq = new u16(19);
540
+ for (var i = 0; i < lclt.length; ++i) ++lcfreq[lclt[i] & 31];
541
+ for (var i = 0; i < lcdt.length; ++i) ++lcfreq[lcdt[i] & 31];
542
+ var _e = hTree(lcfreq, 7), lct = _e.t, mlcb = _e.l;
543
+ var nlcc = 19;
544
+ for (; nlcc > 4 && !lct[clim[nlcc - 1]]; --nlcc);
545
+ var flen = bl + 5 << 3;
546
+ var ftlen = clen(lf, flt) + clen(df, fdt) + eb;
547
+ var dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + 2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18];
548
+ if (bs >= 0 && flen <= ftlen && flen <= dtlen) return wfblk(out, p, dat.subarray(bs, bs + bl));
549
+ var lm, ll, dm, dl;
550
+ wbits(out, p, 1 + (dtlen < ftlen)), p += 2;
551
+ if (dtlen < ftlen) {
552
+ lm = hMap(dlt, mlb, 0), ll = dlt, dm = hMap(ddt, mdb, 0), dl = ddt;
553
+ var llm = hMap(lct, mlcb, 0);
554
+ wbits(out, p, nlc - 257);
555
+ wbits(out, p + 5, ndc - 1);
556
+ wbits(out, p + 10, nlcc - 4);
557
+ p += 14;
558
+ for (var i = 0; i < nlcc; ++i) wbits(out, p + 3 * i, lct[clim[i]]);
559
+ p += 3 * nlcc;
560
+ var lcts = [lclt, lcdt];
561
+ for (var it = 0; it < 2; ++it) {
562
+ var clct = lcts[it];
563
+ for (var i = 0; i < clct.length; ++i) {
564
+ var len = clct[i] & 31;
565
+ wbits(out, p, llm[len]), p += lct[len];
566
+ if (len > 15) wbits(out, p, clct[i] >> 5 & 127), p += clct[i] >> 12;
567
+ }
568
+ }
569
+ } else lm = flm, ll = flt, dm = fdm, dl = fdt;
570
+ for (var i = 0; i < li; ++i) {
571
+ var sym = syms[i];
572
+ if (sym > 255) {
573
+ var len = sym >> 18 & 31;
574
+ wbits16(out, p, lm[len + 257]), p += ll[len + 257];
575
+ if (len > 7) wbits(out, p, sym >> 23 & 31), p += fleb[len];
576
+ var dst = sym & 31;
577
+ wbits16(out, p, dm[dst]), p += dl[dst];
578
+ if (dst > 3) wbits16(out, p, sym >> 5 & 8191), p += fdeb[dst];
579
+ } else wbits16(out, p, lm[sym]), p += ll[sym];
580
+ }
581
+ wbits16(out, p, lm[256]);
582
+ return p + ll[256];
583
+ };
584
+ var deo = /*#__PURE__*/ new i32([
585
+ 65540,
586
+ 131080,
587
+ 131088,
588
+ 131104,
589
+ 262176,
590
+ 1048704,
591
+ 1048832,
592
+ 2114560,
593
+ 2117632
594
+ ]);
595
+ var et = /*#__PURE__*/ new u8(0);
596
+ var dflt = function(dat, lvl, plvl, pre, post, st) {
597
+ var s = st.z || dat.length;
598
+ var o = new u8(pre + s + 5 * (1 + Math.ceil(s / 7e3)) + post);
599
+ var w = o.subarray(pre, o.length - post);
600
+ var lst = st.l;
601
+ var pos = (st.r || 0) & 7;
602
+ if (lvl) {
603
+ if (pos) w[0] = st.r >> 3;
604
+ var opt = deo[lvl - 1];
605
+ var n = opt >> 13, c = opt & 8191;
606
+ var msk_1 = (1 << plvl) - 1;
607
+ var prev = st.p || new u16(32768), head = st.h || new u16(msk_1 + 1);
608
+ var bs1_1 = Math.ceil(plvl / 3), bs2_1 = 2 * bs1_1;
609
+ var hsh = function(i) {
610
+ return (dat[i] ^ dat[i + 1] << bs1_1 ^ dat[i + 2] << bs2_1) & msk_1;
611
+ };
612
+ var syms = new i32(25e3);
613
+ var lf = new u16(288), df = new u16(32);
614
+ var lc_1 = 0, eb = 0, i = st.i || 0, li = 0, wi = st.w || 0, bs = 0;
615
+ for (; i + 2 < s; ++i) {
616
+ var hv = hsh(i);
617
+ var imod = i & 32767, pimod = head[hv];
618
+ prev[imod] = pimod;
619
+ head[hv] = imod;
620
+ if (wi <= i) {
621
+ var rem = s - i;
622
+ if ((lc_1 > 7e3 || li > 24576) && (rem > 423 || !lst)) {
623
+ pos = wblk(dat, w, 0, syms, lf, df, eb, li, bs, i - bs, pos);
624
+ li = lc_1 = eb = 0, bs = i;
625
+ for (var j = 0; j < 286; ++j) lf[j] = 0;
626
+ for (var j = 0; j < 30; ++j) df[j] = 0;
627
+ }
628
+ var l = 2, d = 0, ch_1 = c, dif = imod - pimod & 32767;
629
+ if (rem > 2 && hv == hsh(i - dif)) {
630
+ var maxn = Math.min(n, rem) - 1;
631
+ var maxd = Math.min(32767, i);
632
+ var ml = Math.min(258, rem);
633
+ while (dif <= maxd && --ch_1 && imod != pimod) {
634
+ if (dat[i + l] == dat[i + l - dif]) {
635
+ var nl = 0;
636
+ for (; nl < ml && dat[i + nl] == dat[i + nl - dif]; ++nl);
637
+ if (nl > l) {
638
+ l = nl, d = dif;
639
+ if (nl > maxn) break;
640
+ var mmd = Math.min(dif, nl - 2);
641
+ var md = 0;
642
+ for (var j = 0; j < mmd; ++j) {
643
+ var ti = i - dif + j & 32767;
644
+ var cd = ti - prev[ti] & 32767;
645
+ if (cd > md) md = cd, pimod = ti;
646
+ }
647
+ }
648
+ }
649
+ imod = pimod, pimod = prev[imod];
650
+ dif += imod - pimod & 32767;
651
+ }
652
+ }
653
+ if (d) {
654
+ syms[li++] = 268435456 | revfl[l] << 18 | revfd[d];
655
+ var lin = revfl[l] & 31, din = revfd[d] & 31;
656
+ eb += fleb[lin] + fdeb[din];
657
+ ++lf[257 + lin];
658
+ ++df[din];
659
+ wi = i + l;
660
+ ++lc_1;
661
+ } else {
662
+ syms[li++] = dat[i];
663
+ ++lf[dat[i]];
664
+ }
665
+ }
666
+ }
667
+ for (i = Math.max(i, wi); i < s; ++i) {
668
+ syms[li++] = dat[i];
669
+ ++lf[dat[i]];
670
+ }
671
+ pos = wblk(dat, w, lst, syms, lf, df, eb, li, bs, i - bs, pos);
672
+ if (!lst) {
673
+ st.r = pos & 7 | w[pos / 8 | 0] << 3;
674
+ pos -= 7;
675
+ st.h = head, st.p = prev, st.i = i, st.w = wi;
676
+ }
677
+ } else {
678
+ for (var i = st.w || 0; i < s + lst; i += 65535) {
679
+ var e = i + 65535;
680
+ if (e >= s) {
681
+ w[pos / 8 | 0] = lst;
682
+ e = s;
683
+ }
684
+ pos = wfblk(w, pos + 1, dat.subarray(i, e));
685
+ }
686
+ st.i = s;
687
+ }
688
+ return slc(o, 0, pre + shft(pos) + post);
689
+ };
690
+ var crct = /*#__PURE__*/ (function() {
691
+ var t = /* @__PURE__ */ new Int32Array(256);
692
+ for (var i = 0; i < 256; ++i) {
693
+ var c = i, k = 9;
694
+ while (--k) c = (c & 1 && -306674912) ^ c >>> 1;
695
+ t[i] = c;
696
+ }
697
+ return t;
698
+ })();
699
+ var crc = function() {
700
+ var c = -1;
701
+ return {
702
+ p: function(d) {
703
+ var cr = c;
704
+ for (var i = 0; i < d.length; ++i) cr = crct[cr & 255 ^ d[i]] ^ cr >>> 8;
705
+ c = cr;
706
+ },
707
+ d: function() {
708
+ return ~c;
709
+ }
710
+ };
711
+ };
712
+ var dopt = function(dat, opt, pre, post, st) {
713
+ if (!st) {
714
+ st = { l: 1 };
715
+ if (opt.dictionary) {
716
+ var dict = opt.dictionary.subarray(-32768);
717
+ var newDat = new u8(dict.length + dat.length);
718
+ newDat.set(dict);
719
+ newDat.set(dat, dict.length);
720
+ dat = newDat;
721
+ st.w = dict.length;
722
+ }
723
+ }
724
+ return dflt(dat, opt.level == null ? 6 : opt.level, opt.mem == null ? st.l ? Math.ceil(Math.max(8, Math.min(13, Math.log(dat.length))) * 1.5) : 20 : 12 + opt.mem, pre, post, st);
725
+ };
726
+ var mrg = function(a, b) {
727
+ var o = {};
728
+ for (var k in a) o[k] = a[k];
729
+ for (var k in b) o[k] = b[k];
730
+ return o;
731
+ };
732
+ var wbytes = function(d, b, v) {
733
+ for (; v; ++b) d[b] = v, v >>>= 8;
734
+ };
735
+ /**
736
+ * Compresses data with DEFLATE without any wrapper
737
+ * @param data The data to compress
738
+ * @param opts The compression options
739
+ * @returns The deflated version of the data
740
+ */
741
+ function deflateSync(data, opts) {
742
+ return dopt(data, opts || {}, 0, 0);
743
+ }
744
+ var fltn = function(d, p, t, o) {
745
+ for (var k in d) {
746
+ var val = d[k], n = p + k, op = o;
747
+ if (Array.isArray(val)) op = mrg(o, val[1]), val = val[0];
748
+ if (ArrayBuffer.isView(val)) t[n] = [val, op];
749
+ else {
750
+ t[n += "/"] = [new u8(0), op];
751
+ fltn(val, n, t, o);
752
+ }
753
+ }
754
+ };
755
+ var te = typeof TextEncoder != "undefined" && /*#__PURE__*/ new TextEncoder();
756
+ var td = typeof TextDecoder != "undefined" && /*#__PURE__*/ new TextDecoder();
757
+ try {
758
+ td.decode(et, { stream: true });
759
+ } catch (e) {}
760
+ /**
761
+ * Converts a string into a Uint8Array for use with compression/decompression methods
762
+ * @param str The string to encode
763
+ * @param latin1 Whether or not to interpret the data as Latin-1. This should
764
+ * not need to be true unless decoding a binary string.
765
+ * @returns The string encoded in UTF-8/Latin-1 binary
766
+ */
767
+ function strToU8(str, latin1) {
768
+ if (latin1) {
769
+ var ar_1 = new u8(str.length);
770
+ for (var i = 0; i < str.length; ++i) ar_1[i] = str.charCodeAt(i);
771
+ return ar_1;
772
+ }
773
+ if (te) return te.encode(str);
774
+ var l = str.length;
775
+ var ar = new u8(str.length + (str.length >> 1));
776
+ var ai = 0;
777
+ var w = function(v) {
778
+ ar[ai++] = v;
779
+ };
780
+ for (var i = 0; i < l; ++i) {
781
+ if (ai + 5 > ar.length) {
782
+ var n = new u8(ai + 8 + (l - i << 1));
783
+ n.set(ar);
784
+ ar = n;
785
+ }
786
+ var c = str.charCodeAt(i);
787
+ if (c < 128 || latin1) w(c);
788
+ else if (c < 2048) w(192 | c >> 6), w(128 | c & 63);
789
+ else if (c > 55295 && c < 57344) c = 65536 + (c & 1047552) | str.charCodeAt(++i) & 1023, w(240 | c >> 18), w(128 | c >> 12 & 63), w(128 | c >> 6 & 63), w(128 | c & 63);
790
+ else w(224 | c >> 12), w(128 | c >> 6 & 63), w(128 | c & 63);
791
+ }
792
+ return slc(ar, 0, ai);
793
+ }
794
+ var exfl = function(ex) {
795
+ var le = 0;
796
+ if (ex) for (var k in ex) {
797
+ var l = ex[k].length;
798
+ if (l > 65535) err(9);
799
+ le += l + 4;
800
+ }
801
+ return le;
802
+ };
803
+ var wzh = function(d, b, f, fn, u, c, ce, co) {
804
+ var fl = fn.length, ex = f.extra, col = co && co.length;
805
+ var exl = exfl(ex);
806
+ wbytes(d, b, ce != null ? 33639248 : 67324752), b += 4;
807
+ if (ce != null) d[b++] = 20, d[b++] = f.os;
808
+ d[b] = 20, b += 2;
809
+ d[b++] = f.flag << 1 | (c < 0 && 8), d[b++] = u && 8;
810
+ d[b++] = f.compression & 255, d[b++] = f.compression >> 8;
811
+ var dt = new Date(f.mtime == null ? Date.now() : f.mtime), y = dt.getFullYear() - 1980;
812
+ if (y < 0 || y > 119) err(10);
813
+ wbytes(d, b, y << 25 | dt.getMonth() + 1 << 21 | dt.getDate() << 16 | dt.getHours() << 11 | dt.getMinutes() << 5 | dt.getSeconds() >> 1), b += 4;
814
+ if (c != -1) {
815
+ wbytes(d, b, f.crc);
816
+ wbytes(d, b + 4, c < 0 ? -c - 2 : c);
817
+ wbytes(d, b + 8, f.size);
818
+ }
819
+ wbytes(d, b + 12, fl);
820
+ wbytes(d, b + 14, exl), b += 16;
821
+ if (ce != null) {
822
+ wbytes(d, b, col);
823
+ wbytes(d, b + 6, f.attrs);
824
+ wbytes(d, b + 10, ce), b += 14;
825
+ }
826
+ d.set(fn, b);
827
+ b += fl;
828
+ if (exl) for (var k in ex) {
829
+ var exf = ex[k], l = exf.length;
830
+ wbytes(d, b, +k);
831
+ wbytes(d, b + 2, l);
832
+ d.set(exf, b + 4), b += 4 + l;
833
+ }
834
+ if (col) d.set(co, b), b += col;
835
+ return b;
836
+ };
837
+ var wzf = function(o, b, c, d, e) {
838
+ wbytes(o, b, 101010256);
839
+ wbytes(o, b + 8, c);
840
+ wbytes(o, b + 10, c);
841
+ wbytes(o, b + 12, d);
842
+ wbytes(o, b + 16, e);
843
+ };
844
+ /**
845
+ * Synchronously creates a ZIP file. Prefer using `zip` for better performance
846
+ * with more than one file.
847
+ * @param data The directory structure for the ZIP archive
848
+ * @param opts The main options, merged with per-file options
849
+ * @returns The generated ZIP archive
850
+ */
851
+ function zipSync(data, opts) {
852
+ if (!opts) opts = {};
853
+ var r = {};
854
+ var files = [];
855
+ fltn(data, "", r, opts);
856
+ var o = 0;
857
+ var tot = 0;
858
+ for (var fn in r) {
859
+ var _a = r[fn], file = _a[0], p = _a[1];
860
+ var compression = p.level == 0 ? 0 : 8;
861
+ var f = strToU8(fn), s = f.length;
862
+ var com = p.comment, m = com && strToU8(com), ms = m && m.length;
863
+ var exl = exfl(p.extra);
864
+ if (s > 65535) err(11);
865
+ var d = compression ? deflateSync(file, p) : file, l = d.length;
866
+ var c = crc();
867
+ c.p(file);
868
+ files.push(mrg(p, {
869
+ size: file.length,
870
+ crc: c.d(),
871
+ c: d,
872
+ f,
873
+ m,
874
+ u: s != fn.length || m && com.length != ms,
875
+ o,
876
+ compression
877
+ }));
878
+ o += 30 + s + exl + l;
879
+ tot += 76 + 2 * (s + exl) + (ms || 0) + l;
880
+ }
881
+ var out = new u8(tot + 22), oe = o, cdl = tot - o;
882
+ for (var i = 0; i < files.length; ++i) {
883
+ var f = files[i];
884
+ wzh(out, f.o, f, f.f, f.u, f.c.length);
885
+ var badd = 30 + f.f.length + exfl(f.extra);
886
+ out.set(f.c, f.o + badd);
887
+ wzh(out, o, f, f.f, f.u, f.c.length, f.o, f.m), o += 16 + badd + (f.m ? f.m.length : 0);
888
+ }
889
+ wzf(out, o, files.length, cdl, oe);
890
+ return out;
891
+ }
892
+ //#endregion
893
+ //#region src/client/query-export.ts
894
+ const EXCEL_MAX_COLUMNS = 16384;
895
+ const EXCEL_MAX_CELL_CHARS = 32767;
896
+ const FORMULA_PREFIX = /^[\t\r ]*[=+\-@]/;
897
+ function cellText(value) {
898
+ return value ?? "";
899
+ }
900
+ /** Prevent exported text from becoming an executable spreadsheet formula. */
901
+ function safeDelimitedText(value) {
902
+ return FORMULA_PREFIX.test(value) ? `'${value}` : value;
903
+ }
904
+ function delimitedCell(value, delimiter) {
905
+ const safe = safeDelimitedText(value);
906
+ return safe.includes(delimiter) || /["\r\n]/.test(safe) ? `"${safe.replaceAll("\"", "\"\"")}"` : safe;
907
+ }
908
+ function delimitedTable(data, delimiter) {
909
+ return [data.columns.map((column) => delimitedCell(column, delimiter)).join(delimiter), ...data.rows.map((row) => data.columns.map((column) => delimitedCell(cellText(row[column]), delimiter)).join(delimiter))].join("\r\n");
910
+ }
911
+ /** UTF-8 CSV with BOM so desktop Excel opens Chinese text correctly. */
912
+ function queryResultToCsv(data) {
913
+ return `\uFEFF${delimitedTable(data, ",")}`;
914
+ }
915
+ /** Tabular plain text suitable for spreadsheet clipboard paste. */
916
+ function queryResultToTsv(data) {
917
+ return delimitedTable(data, " ");
918
+ }
919
+ function xmlText(value) {
920
+ return value.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g, "�").replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
921
+ }
922
+ function columnName(index) {
923
+ let value = index + 1;
924
+ let output = "";
925
+ while (value > 0) {
926
+ const remainder = (value - 1) % 26;
927
+ output = String.fromCharCode(65 + remainder) + output;
928
+ value = Math.floor((value - 1) / 26);
929
+ }
930
+ return output;
931
+ }
932
+ function inlineStringCell(reference, value, style) {
933
+ if (value.length > EXCEL_MAX_CELL_CHARS) throw new Error(`Excel cell ${reference} exceeds ${EXCEL_MAX_CELL_CHARS} characters`);
934
+ return `<c r="${reference}" t="inlineStr"${style === void 0 ? "" : ` s="${style}"`}><is><t xml:space="preserve">${xmlText(value)}</t></is></c>`;
935
+ }
936
+ function worksheetXml(data) {
937
+ if (data.columns.length > EXCEL_MAX_COLUMNS) throw new Error(`Excel supports at most ${EXCEL_MAX_COLUMNS} columns`);
938
+ const rowXml = [];
939
+ if (data.columns.length > 0) rowXml.push(`<row r="1">${data.columns.map((column, index) => inlineStringCell(`${columnName(index)}1`, column, 1)).join("")}</row>`);
940
+ for (let rowIndex = 0; rowIndex < data.rows.length; rowIndex += 1) {
941
+ const excelRow = rowIndex + 2;
942
+ const row = data.rows[rowIndex];
943
+ const cells = data.columns.map((column, columnIndex) => {
944
+ const value = row[column];
945
+ return value === null || value === void 0 ? "" : inlineStringCell(`${columnName(columnIndex)}${excelRow}`, value);
946
+ }).join("");
947
+ rowXml.push(`<row r="${excelRow}">${cells}</row>`);
948
+ }
949
+ const widths = data.columns.map((column, columnIndex) => {
950
+ let width = Array.from(column).length;
951
+ const sampleRows = Math.min(data.rows.length, 200);
952
+ for (let index = 0; index < sampleRows; index += 1) width = Math.max(width, Array.from(cellText(data.rows[index][column])).length);
953
+ return `<col min="${columnIndex + 1}" max="${columnIndex + 1}" width="${Math.min(48, Math.max(10, width + 2))}" customWidth="1"/>`;
954
+ }).join("");
955
+ const range = `A1:${data.columns.length === 0 ? "A" : columnName(data.columns.length - 1)}${Math.max(1, data.rows.length + 1)}`;
956
+ const autoFilter = data.columns.length === 0 ? "" : `<autoFilter ref="${range}"/>`;
957
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
958
+ <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
959
+ <dimension ref="${range}"/>
960
+ <sheetViews><sheetView workbookViewId="0"><pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen"/></sheetView></sheetViews>
961
+ <sheetFormatPr defaultRowHeight="15"/>
962
+ ${widths === "" ? "" : `<cols>${widths}</cols>`}
963
+ <sheetData>${rowXml.join("")}</sheetData>
964
+ ${autoFilter}
965
+ </worksheet>`;
966
+ }
967
+ /** Build a real XLSX workbook using inline strings, frozen headers, and filters. */
968
+ function queryResultToXlsx(data) {
969
+ return zipSync({
970
+ "[Content_Types].xml": strToU8(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
971
+ <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
972
+ <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
973
+ <Default Extension="xml" ContentType="application/xml"/>
974
+ <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
975
+ <Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
976
+ <Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
977
+ </Types>`),
978
+ "_rels/.rels": strToU8(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
979
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
980
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
981
+ </Relationships>`),
982
+ "xl/workbook.xml": strToU8(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
983
+ <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
984
+ <sheets><sheet name="Query Result" sheetId="1" r:id="rId1"/></sheets>
985
+ </workbook>`),
986
+ "xl/_rels/workbook.xml.rels": strToU8(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
987
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
988
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>
989
+ <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
990
+ </Relationships>`),
991
+ "xl/styles.xml": strToU8(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
992
+ <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
993
+ <fonts count="2"><font><sz val="11"/><name val="Calibri"/></font><font><b/><sz val="11"/><name val="Calibri"/></font></fonts>
994
+ <fills count="3"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill><fill><patternFill patternType="solid"><fgColor rgb="FFE8EEF7"/><bgColor indexed="64"/></patternFill></fill></fills>
995
+ <borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>
996
+ <cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>
997
+ <cellXfs count="2"><xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/><xf numFmtId="0" fontId="1" fillId="2" borderId="0" xfId="0" applyFont="1" applyFill="1"/></cellXfs>
998
+ </styleSheet>`),
999
+ "xl/worksheets/sheet1.xml": strToU8(worksheetXml(data))
1000
+ }, { level: 6 });
1001
+ }
1002
+ //#endregion
95
1003
  //#region \0dsh-css:/Users/yejiming/Desktop/OpenSource/dsh-data-agent/src/client/DataAgentWorkbench.module.css.mjs
96
- const css$1 = ".Sv3uVW_triggerSlot{z-index:12;pointer-events:auto;display:flex;position:absolute;top:-42px;right:12px}.Sv3uVW_trigger{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-specific-selector,var(--dsw-alias-bg-layer-2,#ffffff0f));width:30px;height:30px;color:var(--dsw-alias-label-secondary,#808080e6);cursor:pointer;border-radius:9px;place-items:center;padding:0;transition:background-color .15s ease-out,border-color .15s ease-out,color .15s ease-out;display:grid;position:relative;box-shadow:0 1px 2px #0000000a}.Sv3uVW_trigger:hover,.Sv3uVW_triggerActive{border-color:var(--dsw-alias-border-l3,#80808080);background:var(--dsw-alias-interactive-bg-hover-solid,var(--dsw-alias-interactive-bg-hover,#8080801a));color:var(--dsw-alias-label-primary,inherit)}.Sv3uVW_trigger:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 25%, transparent);outline:none}.Sv3uVW_triggerDot{box-shadow:0 0 0 2px var(--dsw-specific-input-major,var(--dsw-alias-bg-base,#fff));border-radius:999px;position:absolute;bottom:-2px;right:-2px}.Sv3uVW_workbenchModal{width:min(920px,94vw)}.Sv3uVW_workbenchModalContent{min-height:min(590px,70vh);max-height:min(700px,76vh);overflow:auto}.Sv3uVW_workbench{box-sizing:border-box;min-height:520px;font-family:var(--dsw-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif);color:var(--dsw-alias-label-primary,inherit);flex-direction:column;gap:14px;font-size:13px;line-height:1.5;display:flex}.Sv3uVW_connectionSummary{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#ffffff0a);border-radius:10px;align-items:center;gap:8px;min-height:34px;padding:6px 10px;display:flex}.Sv3uVW_connectionState{flex:none;font-size:12px;font-weight:600}.Sv3uVW_summaryType{border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-1,#ffffff08);color:var(--dsw-alias-label-secondary,#808080cc);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);border-radius:999px;flex:none;padding:2px 8px;font-size:11px}.Sv3uVW_summaryDb{min-width:0;color:var(--dsw-alias-label-secondary,#808080cc);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.Sv3uVW_tabs{background:var(--dsw-specific-selector,var(--dsw-alias-bg-layer-2,#80808014));border-radius:10px;align-items:center;gap:4px;padding:3px;display:flex;overflow-x:auto}.Sv3uVW_tab{height:34px;color:var(--dsw-alias-label-secondary,#808080cc);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-radius:8px;flex:1 0 120px;justify-content:center;align-items:center;gap:7px;padding:0 14px;font-size:13px;font-weight:500;display:inline-flex}.Sv3uVW_tab:hover:not(:disabled){color:var(--dsw-alias-label-primary,inherit);background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_tabActive,.Sv3uVW_tabActive:hover:not(:disabled){color:var(--dsw-alias-label-primary,inherit);background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1,#fffc));box-shadow:var(--dsw-shadow-lv1,0 1px 3px #00000014)}.Sv3uVW_tab:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 28%, transparent);outline:none}.Sv3uVW_tab:disabled{opacity:.42;cursor:default}.Sv3uVW_tabPanel{flex-direction:column;flex:1;gap:14px;min-height:0;padding:2px;display:flex}.Sv3uVW_fieldGrid{flex-direction:column;gap:11px;display:flex}.Sv3uVW_fieldRow2{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px;display:grid}.Sv3uVW_field{flex-direction:column;gap:5px;min-width:0;display:flex}.Sv3uVW_label{color:var(--dsw-alias-label-secondary,#808080bf);font-size:11px;font-weight:500}.Sv3uVW_rememberRow{color:var(--dsw-alias-label-primary,inherit);cursor:pointer;user-select:none;align-items:center;gap:7px;font-size:12px;display:flex}.Sv3uVW_rememberRow input[type=checkbox]{width:14px;height:14px;accent-color:var(--dsw-alias-button-info-fill,#3b82f6);flex:none;margin:0}.Sv3uVW_rememberHint{color:var(--dsw-alias-label-caption,#8080808c);font-size:11px}.Sv3uVW_input{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;height:34px;color:var(--dsw-alias-label-primary,inherit);font:inherit;border-radius:8px;padding:0 10px;font-size:13px;transition:border-color .15s ease-out,box-shadow .15s ease-out}.Sv3uVW_input::placeholder{color:var(--dsw-alias-label-caption,#80808080)}.Sv3uVW_input:focus,.Sv3uVW_input:focus-visible,.Sv3uVW_sqlInput:focus,.Sv3uVW_sqlInput:focus-visible{border-color:var(--dsw-alias-button-info-fill,#3b82f6);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 18%, transparent);outline:none}.Sv3uVW_input:disabled{opacity:.58}select.Sv3uVW_input{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' fill='none' stroke='%23777' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 10px center;background-repeat:no-repeat;padding-right:28px}.Sv3uVW_actions{justify-content:flex-end;align-items:center;gap:8px;margin-top:auto;padding-top:4px;display:flex}.Sv3uVW_primary,.Sv3uVW_ghost{min-width:96px;height:34px;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;justify-content:center;align-items:center;gap:6px;padding:0 15px;font-size:13px;font-weight:500;transition:background-color .15s ease-out,border-color .15s ease-out,opacity .15s ease-out;display:inline-flex}.Sv3uVW_primary{background:var(--dsw-alias-button-info-fill,#3b82f6);color:#fff}.Sv3uVW_primary:hover:not(:disabled){background:var(--dsw-alias-button-info-hover,#3573e0)}.Sv3uVW_ghost{border-color:var(--dsw-alias-border-l2,#80808059);color:var(--dsw-alias-label-primary,inherit);background:0 0}.Sv3uVW_ghost:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_primary:focus-visible,.Sv3uVW_ghost:focus-visible,.Sv3uVW_treeItem:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 24%, transparent);outline:none}.Sv3uVW_primary:disabled,.Sv3uVW_ghost:disabled{opacity:.45;cursor:default}.Sv3uVW_schemaPanel{grid-template-columns:minmax(260px,.9fr) minmax(320px,1.1fr);gap:20px;height:min(470px,56vh);display:grid}.Sv3uVW_modalCol{flex-direction:column;gap:8px;min-width:0;min-height:0;display:flex}.Sv3uVW_modalColTitle{color:var(--dsw-alias-label-tertiary,#808080b3);letter-spacing:.06em;text-transform:uppercase;flex:none;align-items:center;gap:6px;font-size:11px;font-weight:600;display:flex}.Sv3uVW_colCount,.Sv3uVW_treeCount{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#ffffff0a);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:999px;flex:none;padding:1px 7px;font-size:10px;font-weight:500}.Sv3uVW_treeScroll{flex:1;min-height:0;padding-right:4px;overflow-y:auto}.Sv3uVW_tree{flex-direction:column;gap:1px;margin:0;padding:0;list-style:none;display:flex}.Sv3uVW_treeNode,.Sv3uVW_treeChildren{flex-direction:column;gap:1px;display:flex}.Sv3uVW_treeItem{width:100%;min-height:30px;color:var(--dsw-alias-label-primary,inherit);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:7px;align-items:center;gap:6px;padding:0 8px;font-size:12.5px;display:flex}.Sv3uVW_treeItem:hover{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_treeItem.Sv3uVW_active,.Sv3uVW_treeItem.Sv3uVW_active:hover{background:var(--dsw-alias-interactive-bg-active,#3b82f62e)}.Sv3uVW_treeChevron{color:var(--dsw-alias-label-tertiary,#80808099);flex:none;transition:transform .15s ease-out}.Sv3uVW_treeChevron.Sv3uVW_open{transform:rotate(90deg)}.Sv3uVW_treeIcon{color:var(--dsw-alias-label-secondary,#808080cc);flex:none}.Sv3uVW_treeItem.Sv3uVW_active .Sv3uVW_treeIcon{color:var(--dsw-alias-button-info-fill,#3b82f6)}.Sv3uVW_treeName{min-width:0;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:12px;overflow:hidden}.Sv3uVW_treeChildren{border-left:1px solid var(--dsw-alias-border-l2,#80808059);max-height:154px;margin-left:12px;padding-left:10px;overflow-y:auto}.Sv3uVW_hint{color:var(--dsw-alias-label-tertiary,#80808099);font-size:12px}.Sv3uVW_modalHint{color:var(--dsw-alias-label-caption,#80808080);flex:none;margin-top:2px;font-size:11.5px}.Sv3uVW_colScroll{border:1px solid var(--dsw-alias-border-l1,#80808033);border-radius:8px;flex:1;min-height:0;overflow:auto}.Sv3uVW_columnsTable{border-collapse:collapse;width:100%;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);font-size:12px}.Sv3uVW_columnsTable th{z-index:1;border-bottom:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);color:var(--dsw-alias-label-tertiary,#808080b3);letter-spacing:.05em;text-align:left;text-transform:uppercase;padding:7px 10px;font-size:10.5px;font-weight:600;position:sticky;top:0}.Sv3uVW_columnsTable td{border-bottom:1px solid var(--dsw-alias-border-l1,#80808033);padding:6px 10px}.Sv3uVW_columnsTable tbody tr:hover td{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_typeCell{color:var(--dsw-alias-label-secondary,#808080cc)}.Sv3uVW_nullCell{color:var(--dsw-alias-label-caption,#80808080);font-size:11px}.Sv3uVW_emptyState{border:1px dashed var(--dsw-alias-border-l2,#80808059);min-height:0;color:var(--dsw-alias-label-tertiary,#808080b3);border-radius:8px;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;display:flex}.Sv3uVW_emptyStateIcon{width:20px;height:20px;color:var(--dsw-alias-label-dimmed,#80808066)}.Sv3uVW_emptyStateText{font-size:12px}.Sv3uVW_sqlPanel{min-height:430px}.Sv3uVW_sqlInput{box-sizing:border-box;resize:vertical;border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;min-height:210px;color:var(--dsw-alias-label-primary,inherit);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);border-radius:10px;padding:12px;font-size:12.5px;line-height:1.6}.Sv3uVW_sqlInput::placeholder{color:var(--dsw-alias-label-caption,#80808080)}.Sv3uVW_sqlActions{justify-content:flex-end;align-items:center;gap:10px;display:flex}.Sv3uVW_shortcutHint{color:var(--dsw-alias-label-caption,#80808080);font-size:11.5px}.Sv3uVW_sqlResult{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-markdown-code-block,#ffffff0a);min-height:100px;max-height:220px;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);white-space:pre-wrap;word-break:break-word;border-radius:8px;flex:1;margin:0;padding:11px 12px;font-size:11.5px;line-height:1.55;overflow-y:auto}.Sv3uVW_errorBar{border:1px solid var(--dsw-alias-state-error-secondary,#ef444480);background:var(--dsw-alias-interactive-bg-hover-danger,#ef444414);border-radius:10px;flex-direction:column;gap:3px;padding:10px 12px;display:flex}.Sv3uVW_errorHead{color:var(--dsw-alias-state-error-primary,#ef4444);align-items:center;gap:6px;font-size:12px;font-weight:600;display:flex}.Sv3uVW_errorIcon{flex:none}.Sv3uVW_errorText{white-space:pre-wrap;word-break:break-word;font-size:12px}@media (width<=640px){.Sv3uVW_triggerSlot{top:-42px;right:10px}.Sv3uVW_workbenchModal{width:min(96vw,920px)}.Sv3uVW_workbenchModalContent{min-height:0;max-height:72vh}.Sv3uVW_workbench{min-height:0}.Sv3uVW_fieldRow2{grid-template-columns:1fr}.Sv3uVW_schemaPanel{flex-direction:column;height:auto;display:flex}.Sv3uVW_treeScroll{flex:none;height:240px}.Sv3uVW_colScroll{flex:none;height:220px}.Sv3uVW_emptyState{flex:none;min-height:120px}.Sv3uVW_rememberRow{flex-wrap:wrap;align-items:flex-start}.Sv3uVW_rememberHint{flex-basis:100%;padding-left:21px}}@media (prefers-reduced-motion:reduce){.Sv3uVW_trigger,.Sv3uVW_input,.Sv3uVW_primary,.Sv3uVW_ghost,.Sv3uVW_treeChevron{transition:none}}";
1004
+ const css$1 = ".Sv3uVW_triggerSlot{z-index:12;pointer-events:auto;display:flex;position:absolute;top:-42px;right:12px}.Sv3uVW_trigger{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-specific-selector,var(--dsw-alias-bg-layer-2,#ffffff0f));width:30px;height:30px;color:var(--dsw-alias-label-secondary,#808080e6);cursor:pointer;border-radius:9px;place-items:center;padding:0;transition:background-color .15s ease-out,border-color .15s ease-out,color .15s ease-out;display:grid;position:relative;box-shadow:0 1px 2px #0000000a}.Sv3uVW_trigger:hover,.Sv3uVW_triggerActive{border-color:var(--dsw-alias-border-l3,#80808080);background:var(--dsw-alias-interactive-bg-hover-solid,var(--dsw-alias-interactive-bg-hover,#8080801a));color:var(--dsw-alias-label-primary,inherit)}.Sv3uVW_trigger:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 25%, transparent);outline:none}.Sv3uVW_triggerDot{box-shadow:0 0 0 2px var(--dsw-specific-input-major,var(--dsw-alias-bg-base,#fff));border-radius:999px;position:absolute;bottom:-2px;right:-2px}.Sv3uVW_workbenchModal{width:min(920px,94vw)}.Sv3uVW_workbenchModalContent{min-height:min(590px,70vh);max-height:min(700px,76vh);overflow:auto}.Sv3uVW_workbench{box-sizing:border-box;min-height:520px;font-family:var(--dsw-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif);color:var(--dsw-alias-label-primary,inherit);flex-direction:column;gap:14px;font-size:13px;line-height:1.5;display:flex}.Sv3uVW_connectionSummary{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#ffffff0a);border-radius:10px;align-items:center;gap:8px;min-height:34px;padding:6px 10px;display:flex}.Sv3uVW_connectionState{flex:none;font-size:12px;font-weight:600}.Sv3uVW_summaryType{border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-1,#ffffff08);color:var(--dsw-alias-label-secondary,#808080cc);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);border-radius:999px;flex:none;padding:2px 8px;font-size:11px}.Sv3uVW_summaryDb{min-width:0;color:var(--dsw-alias-label-secondary,#808080cc);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.Sv3uVW_tabs{background:var(--dsw-specific-selector,var(--dsw-alias-bg-layer-2,#80808014));border-radius:10px;align-items:center;gap:4px;padding:3px;display:flex;overflow-x:auto}.Sv3uVW_tab{height:34px;color:var(--dsw-alias-label-secondary,#808080cc);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-radius:8px;flex:1 0 120px;justify-content:center;align-items:center;gap:7px;padding:0 14px;font-size:13px;font-weight:500;display:inline-flex}.Sv3uVW_tab:hover:not(:disabled){color:var(--dsw-alias-label-primary,inherit);background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_tabActive,.Sv3uVW_tabActive:hover:not(:disabled){color:var(--dsw-alias-label-primary,inherit);background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-1,#fffc));box-shadow:var(--dsw-shadow-lv1,0 1px 3px #00000014)}.Sv3uVW_tab:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 28%, transparent);outline:none}.Sv3uVW_tab:disabled{opacity:.42;cursor:default}.Sv3uVW_tabPanel{flex-direction:column;flex:1;gap:14px;min-height:0;padding:2px;display:flex}.Sv3uVW_fieldGrid{flex-direction:column;gap:11px;display:flex}.Sv3uVW_fieldRow2{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px;display:grid}.Sv3uVW_field{flex-direction:column;gap:5px;min-width:0;display:flex}.Sv3uVW_label{color:var(--dsw-alias-label-secondary,#808080bf);font-size:11px;font-weight:500}.Sv3uVW_rememberRow{color:var(--dsw-alias-label-primary,inherit);cursor:pointer;user-select:none;align-items:center;gap:7px;font-size:12px;display:flex}.Sv3uVW_rememberRow input[type=checkbox]{width:14px;height:14px;accent-color:var(--dsw-alias-button-info-fill,#3b82f6);flex:none;margin:0}.Sv3uVW_rememberHint{color:var(--dsw-alias-label-caption,#8080808c);font-size:11px}.Sv3uVW_input{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;height:34px;color:var(--dsw-alias-label-primary,inherit);font:inherit;border-radius:8px;padding:0 10px;font-size:13px;transition:border-color .15s ease-out,box-shadow .15s ease-out}.Sv3uVW_input::placeholder{color:var(--dsw-alias-label-caption,#80808080)}.Sv3uVW_input:focus,.Sv3uVW_input:focus-visible,.Sv3uVW_sqlInput:focus,.Sv3uVW_sqlInput:focus-visible{border-color:var(--dsw-alias-button-info-fill,#3b82f6);box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 18%, transparent);outline:none}.Sv3uVW_input:disabled{opacity:.58}select.Sv3uVW_input{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' fill='none' stroke='%23777' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 10px center;background-repeat:no-repeat;padding-right:28px}.Sv3uVW_actions{justify-content:flex-end;align-items:center;gap:8px;margin-top:auto;padding-top:4px;display:flex}.Sv3uVW_primary,.Sv3uVW_ghost{min-width:96px;height:34px;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;justify-content:center;align-items:center;gap:6px;padding:0 15px;font-size:13px;font-weight:500;transition:background-color .15s ease-out,border-color .15s ease-out,opacity .15s ease-out;display:inline-flex}.Sv3uVW_primary{background:var(--dsw-alias-button-info-fill,#3b82f6);color:#fff}.Sv3uVW_primary:hover:not(:disabled){background:var(--dsw-alias-button-info-hover,#3573e0)}.Sv3uVW_ghost{border-color:var(--dsw-alias-border-l2,#80808059);color:var(--dsw-alias-label-primary,inherit);background:0 0}.Sv3uVW_ghost:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_primary:focus-visible,.Sv3uVW_ghost:focus-visible,.Sv3uVW_treeItem:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 24%, transparent);outline:none}.Sv3uVW_primary:disabled,.Sv3uVW_ghost:disabled{opacity:.45;cursor:default}.Sv3uVW_schemaPanel{grid-template-columns:minmax(260px,.9fr) minmax(320px,1.1fr);gap:20px;height:min(470px,56vh);display:grid}.Sv3uVW_modalCol{flex-direction:column;gap:8px;min-width:0;min-height:0;display:flex}.Sv3uVW_modalColTitle{color:var(--dsw-alias-label-tertiary,#808080b3);letter-spacing:.06em;text-transform:uppercase;flex:none;align-items:center;gap:6px;font-size:11px;font-weight:600;display:flex}.Sv3uVW_colCount,.Sv3uVW_treeCount{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#ffffff0a);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:999px;flex:none;padding:1px 7px;font-size:10px;font-weight:500}.Sv3uVW_treeScroll{flex:1;min-height:0;padding-right:4px;overflow-y:auto}.Sv3uVW_tree{flex-direction:column;gap:1px;margin:0;padding:0;list-style:none;display:flex}.Sv3uVW_treeNode,.Sv3uVW_treeChildren{flex-direction:column;gap:1px;display:flex}.Sv3uVW_treeItem{width:100%;min-height:30px;color:var(--dsw-alias-label-primary,inherit);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:7px;align-items:center;gap:6px;padding:0 8px;font-size:12.5px;display:flex}.Sv3uVW_treeItem:hover{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_treeItem.Sv3uVW_active,.Sv3uVW_treeItem.Sv3uVW_active:hover{background:var(--dsw-alias-interactive-bg-active,#3b82f62e)}.Sv3uVW_treeChevron{color:var(--dsw-alias-label-tertiary,#80808099);flex:none;transition:transform .15s ease-out}.Sv3uVW_treeChevron.Sv3uVW_open{transform:rotate(90deg)}.Sv3uVW_treeIcon{color:var(--dsw-alias-label-secondary,#808080cc);flex:none}.Sv3uVW_treeItem.Sv3uVW_active .Sv3uVW_treeIcon{color:var(--dsw-alias-button-info-fill,#3b82f6)}.Sv3uVW_treeName{min-width:0;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:12px;overflow:hidden}.Sv3uVW_treeChildren{border-left:1px solid var(--dsw-alias-border-l2,#80808059);max-height:154px;margin-left:12px;padding-left:10px;overflow-y:auto}.Sv3uVW_hint{color:var(--dsw-alias-label-tertiary,#80808099);font-size:12px}.Sv3uVW_modalHint{color:var(--dsw-alias-label-caption,#80808080);flex:none;margin-top:2px;font-size:11.5px}.Sv3uVW_colScroll{border:1px solid var(--dsw-alias-border-l1,#80808033);border-radius:8px;flex:1;min-height:0;overflow:auto}.Sv3uVW_columnsTable{border-collapse:collapse;width:100%;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);font-size:12px}.Sv3uVW_columnsTable th{z-index:1;border-bottom:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);color:var(--dsw-alias-label-tertiary,#808080b3);letter-spacing:.05em;text-align:left;text-transform:uppercase;padding:7px 10px;font-size:10.5px;font-weight:600;position:sticky;top:0}.Sv3uVW_columnsTable td{border-bottom:1px solid var(--dsw-alias-border-l1,#80808033);padding:6px 10px}.Sv3uVW_columnsTable tbody tr:hover td{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_typeCell{color:var(--dsw-alias-label-secondary,#808080cc)}.Sv3uVW_nullCell{color:var(--dsw-alias-label-caption,#80808080);font-size:11px}.Sv3uVW_emptyState{border:1px dashed var(--dsw-alias-border-l2,#80808059);min-height:0;color:var(--dsw-alias-label-tertiary,#808080b3);border-radius:8px;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;display:flex}.Sv3uVW_emptyStateIcon{width:20px;height:20px;color:var(--dsw-alias-label-dimmed,#80808066)}.Sv3uVW_emptyStateText{font-size:12px}.Sv3uVW_sqlPanel{min-height:430px}.Sv3uVW_sqlInput{box-sizing:border-box;resize:vertical;border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);width:100%;min-height:210px;color:var(--dsw-alias-label-primary,inherit);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);border-radius:10px;padding:12px;font-size:12.5px;line-height:1.6}.Sv3uVW_sqlInput::placeholder{color:var(--dsw-alias-label-caption,#80808080)}.Sv3uVW_sqlActions{justify-content:flex-end;align-items:center;gap:10px;display:flex}.Sv3uVW_shortcutHint{color:var(--dsw-alias-label-caption,#80808080);font-size:11.5px}.Sv3uVW_sqlResultEmpty,.Sv3uVW_sqlMessage{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-markdown-code-block,#ffffff0a);border-radius:8px;flex:1;min-height:150px;margin:0;padding:11px 12px}.Sv3uVW_sqlResultEmpty{color:var(--dsw-alias-label-caption,#80808080);place-items:center;font-size:12px;display:grid}.Sv3uVW_sqlMessage{max-height:280px;color:var(--dsw-alias-label-primary,inherit);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);white-space:pre-wrap;word-break:break-word;font-size:11.5px;line-height:1.55;overflow:auto}.Sv3uVW_sqlMessageError{border-color:var(--dsw-alias-state-error-secondary,#ef444480);background:var(--dsw-alias-interactive-bg-hover-danger,#ef444414);color:var(--dsw-alias-state-error-primary,#ef4444)}.Sv3uVW_sqlResultPanel{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-markdown-code-block,#ffffff0a);border-radius:8px;flex-direction:column;flex:1;min-height:210px;display:flex;overflow:hidden}.Sv3uVW_sqlResultToolbar{border-bottom:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#ffffff0a);flex:none;justify-content:space-between;align-items:center;gap:10px;min-height:42px;padding:6px 8px 6px 11px;display:flex}.Sv3uVW_sqlResultMeta{min-width:0;color:var(--dsw-alias-label-secondary,#808080cc);white-space:nowrap;align-items:center;gap:8px;font-size:11.5px;display:flex}.Sv3uVW_sqlResultLimit{background:var(--dsw-alias-interactive-bg-hover,#80808014);color:var(--dsw-alias-label-tertiary,#808080a6);border-radius:999px;padding:1px 6px;font-size:10.5px}.Sv3uVW_sqlFeedback{color:var(--dsw-alias-state-success-primary,#16a34a);text-overflow:ellipsis;overflow:hidden}.Sv3uVW_sqlExportActions{flex:none;align-items:center;gap:5px;display:flex}.Sv3uVW_sqlExportButton,.Sv3uVW_sqlPageButton{border:1px solid var(--dsw-alias-border-l2,#80808059);height:28px;color:var(--dsw-alias-label-secondary,#808080cc);font:inherit;cursor:pointer;background:0 0;border-radius:7px;justify-content:center;align-items:center;gap:4px;padding:0 9px;font-size:11.5px;transition:background-color .15s ease-out,border-color .15s ease-out,color .15s ease-out,opacity .15s ease-out;display:inline-flex}.Sv3uVW_sqlExportButton:hover:not(:disabled),.Sv3uVW_sqlPageButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#80808014);color:var(--dsw-alias-label-primary,inherit)}.Sv3uVW_sqlExportButton:focus-visible,.Sv3uVW_sqlPageButton:focus-visible{box-shadow:0 0 0 3px color-mix(in srgb, var(--dsw-alias-button-info-fill,#3b82f6) 24%, transparent);outline:none}.Sv3uVW_sqlExportButton:disabled,.Sv3uVW_sqlPageButton:disabled{opacity:.42;cursor:default}.Sv3uVW_sqlTableScroll{flex:1;min-height:150px;max-height:300px;overflow:auto}.Sv3uVW_sqlResultTable{border-collapse:separate;border-spacing:0;width:max-content;min-width:100%;color:var(--dsw-alias-label-primary,inherit);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);font-size:11.5px}.Sv3uVW_sqlResultTable th{z-index:1;border-bottom:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#8080801f);color:var(--dsw-alias-label-secondary,#808080cc);text-align:left;white-space:nowrap;padding:7px 10px;font-size:11px;font-weight:600;position:sticky;top:0}.Sv3uVW_sqlResultTable td{border-bottom:1px solid var(--dsw-alias-border-l1,#8080802e);text-overflow:ellipsis;white-space:nowrap;max-width:360px;padding:6px 10px;overflow:hidden}.Sv3uVW_sqlResultTable tbody tr:hover td{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_sqlNull,.Sv3uVW_sqlEmptyString{color:var(--dsw-alias-label-caption,#80808080);font-size:10.5px}.Sv3uVW_sqlNull{font-style:italic}.Sv3uVW_sqlTableEmpty{height:92px;color:var(--dsw-alias-label-caption,#80808080);text-align:center}.Sv3uVW_sqlPagination{border-top:1px solid var(--dsw-alias-border-l1,#80808033);min-height:36px;color:var(--dsw-alias-label-tertiary,#808080a6);flex:none;justify-content:space-between;align-items:center;gap:8px;padding:4px 8px 4px 11px;font-size:11px;display:flex}.Sv3uVW_sqlPageActions{gap:5px;display:flex}.Sv3uVW_sqlPageButton{height:26px}.Sv3uVW_catalogPanel{min-height:450px}.Sv3uVW_catalogPanel[hidden]{display:none}.Sv3uVW_catalogProgress,.Sv3uVW_catalogConfirm{align-items:center;gap:8px;display:flex}.Sv3uVW_catalogToolbar{border-bottom:1px solid var(--dsw-alias-border-l1,#80808033);flex-direction:column;padding-bottom:10px;display:flex}.Sv3uVW_catalogOverview{grid-template-columns:minmax(260px,.8fr) minmax(0,1.2fr);align-items:end;gap:14px;padding-bottom:10px;display:grid}.Sv3uVW_catalogControl{min-width:0;color:var(--dsw-alias-label-secondary,#808080cc);flex-direction:column;gap:4px;font-size:11px;display:flex}.Sv3uVW_catalogStats{min-width:0;color:var(--dsw-alias-label-secondary,#808080cc);grid-template-columns:minmax(140px,auto) minmax(0,1fr);align-items:center;gap:5px 16px;font-size:11px;display:grid}.Sv3uVW_catalogSourceName{color:var(--dsw-alias-label-primary,inherit);text-overflow:ellipsis;white-space:nowrap;font-size:13px;overflow:hidden}.Sv3uVW_catalogCounts{align-items:center;gap:16px;min-width:0;display:flex}.Sv3uVW_catalogCounts>span{white-space:nowrap;align-items:baseline;gap:4px;display:inline-flex}.Sv3uVW_catalogCounts strong{color:var(--dsw-alias-label-primary,inherit);font-variant-numeric:tabular-nums;font-size:13px}.Sv3uVW_catalogScanTimes{min-width:0;color:var(--dsw-alias-label-caption,#8080808c);grid-column:1/-1;gap:18px;display:flex}.Sv3uVW_catalogScanTimes span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.Sv3uVW_catalogScanTimes time{color:var(--dsw-alias-label-secondary,#808080cc);font-variant-numeric:tabular-nums;margin-left:4px}.Sv3uVW_catalogLatestRun{border-top:1px solid var(--dsw-alias-border-l1,#80808029);min-width:0;color:var(--dsw-alias-label-secondary,#808080cc);align-items:center;gap:8px;padding:8px 0;font-size:11px;display:flex}.Sv3uVW_catalogLatestRun[data-error=true]{color:var(--dsw-alias-state-error-primary,#ef4444)}.Sv3uVW_catalogLatestLabel{flex:none;font-weight:600}.Sv3uVW_catalogLatestRun code{max-width:150px;color:var(--dsw-alias-label-caption,#8080808c);text-overflow:ellipsis;white-space:nowrap;font-size:10px;overflow:hidden}.Sv3uVW_catalogLatestError{overflow-wrap:anywhere;min-width:0}.Sv3uVW_catalogLatestError strong{font-weight:600}.Sv3uVW_catalogActions{flex-direction:column;display:flex}.Sv3uVW_catalogActionGroup{border-top:1px solid var(--dsw-alias-border-l1,#80808029);grid-template-columns:104px minmax(0,1fr);align-items:center;gap:12px;min-width:0;padding:10px 0 0;display:grid}.Sv3uVW_catalogActionGroup+.Sv3uVW_catalogActionGroup{margin-top:10px}.Sv3uVW_catalogActionGroup>div{min-width:0}.Sv3uVW_catalogSectionLabel{color:var(--dsw-alias-label-secondary,#808080cc);align-self:start;padding-top:7px;font-size:11px;font-weight:600}.Sv3uVW_catalogScanBar{align-items:center;gap:8px;min-width:0;display:flex}.Sv3uVW_catalogScanBar .Sv3uVW_input{flex:160px;max-width:none}.Sv3uVW_catalogInlineNotice{color:var(--dsw-alias-label-caption,#8080808c);margin-top:5px;font-size:10.5px}.Sv3uVW_catalogDiffBar{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;gap:8px;display:grid}.Sv3uVW_catalogNotice,.Sv3uVW_catalogError,.Sv3uVW_catalogProgress,.Sv3uVW_catalogConfirm{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#8080800d);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:8px;padding:8px 10px;font-size:11.5px}.Sv3uVW_catalogNotice{background:0 0;border:none;padding-block:5px}.Sv3uVW_catalogError{border-color:var(--dsw-alias-state-error-secondary,#ef444480);color:var(--dsw-alias-state-error-primary,#ef4444)}.Sv3uVW_catalogProgress code{margin-left:auto;font-size:10px}.Sv3uVW_catalogConfirm span{flex:1}.Sv3uVW_catalogWorkspace{flex:none;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:14px;height:clamp(380px,52vh,520px);min-height:0;display:grid;overflow:hidden}.Sv3uVW_catalogResults,.Sv3uVW_catalogDetail{flex-direction:column;gap:8px;min-width:0;min-height:0;display:flex;overflow:hidden}.Sv3uVW_catalogSearch{grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;display:grid}.Sv3uVW_catalogSearchQuery,.Sv3uVW_catalogSearchActions{grid-column:1/-1}.Sv3uVW_catalogSearchActions{justify-content:space-between;align-items:center;gap:8px;display:flex}.Sv3uVW_catalogCheck{color:var(--dsw-alias-label-secondary,#808080cc);align-items:center;gap:6px;font-size:11px;display:flex}.Sv3uVW_catalogList,.Sv3uVW_catalogDetail{border:1px solid var(--dsw-alias-border-l1,#80808033);border-radius:9px;overflow:hidden}.Sv3uVW_catalogList{overscroll-behavior:contain;flex-direction:column;flex:1;min-height:0;display:flex;overflow-y:auto}.Sv3uVW_catalogItem{border:0;border-bottom:1px solid var(--dsw-alias-border-l1,#80808029);color:var(--dsw-alias-label-primary,inherit);font:inherit;text-align:left;cursor:pointer;background:0 0;flex-direction:column;gap:3px;padding:9px 10px;display:flex}.Sv3uVW_catalogItem:hover,.Sv3uVW_catalogItemActive{background:var(--dsw-alias-interactive-bg-hover,#80808014)}.Sv3uVW_catalogItem:focus-visible{outline:2px solid var(--dsw-alias-button-info-fill,#3b82f6);outline-offset:-2px}.Sv3uVW_catalogItem code,.Sv3uVW_catalogHistoryItem code,.Sv3uVW_catalogDetailScroll>code{color:var(--dsw-alias-label-secondary,#808080cc);text-overflow:ellipsis;white-space:nowrap;font-size:10.5px;overflow:hidden}.Sv3uVW_catalogItem>span:last-child{color:var(--dsw-alias-label-caption,#8080808c);font-size:10.5px}.Sv3uVW_catalogItemHead{justify-content:space-between;align-items:center;gap:8px;display:flex}.Sv3uVW_catalogListEmpty{min-height:160px;color:var(--dsw-alias-label-caption,#8080808c);place-items:center;display:grid}.Sv3uVW_catalogBadge{border:1px solid var(--dsw-alias-border-l2,#80808059);width:fit-content;color:var(--dsw-alias-label-secondary,#808080cc);white-space:nowrap;border-radius:999px;flex:none;align-items:center;padding:1px 7px;font-size:10px;font-weight:600;display:inline-flex}.Sv3uVW_catalogBadge_verified,.Sv3uVW_catalogBadge_observed,.Sv3uVW_catalogBadge_restored{color:#16a34a;border-color:#16a34a73}.Sv3uVW_catalogBadge_inferred,.Sv3uVW_catalogBadge_needs_review,.Sv3uVW_catalogBadge_changed{color:#d97706;border-color:#d9770673}.Sv3uVW_catalogBadge_missing,.Sv3uVW_catalogBadge_unavailable,.Sv3uVW_catalogBadge_retired{color:#dc2626;border-color:#dc262661}.Sv3uVW_catalogDetailTabs{border-bottom:1px solid var(--dsw-alias-border-l1,#80808033);flex:none;gap:3px;padding:5px;display:flex}.Sv3uVW_catalogDetailHeader{border-bottom:1px solid var(--dsw-alias-border-l1,#80808033);flex-direction:column;flex:none;gap:7px;padding:12px 12px 10px;display:flex}.Sv3uVW_catalogDetailHeader h3,.Sv3uVW_catalogDetailHeader p{margin:0}.Sv3uVW_catalogDetailHeader p{color:var(--dsw-alias-label-secondary,#808080cc);font-size:11.5px}.Sv3uVW_catalogDetailTitle{justify-content:space-between;align-items:flex-start;gap:10px;min-width:0;display:flex}.Sv3uVW_catalogDetailTitle>div{flex-direction:column;gap:2px;min-width:0;display:flex}.Sv3uVW_catalogDetailTitle code{color:var(--dsw-alias-label-secondary,#808080cc);text-overflow:ellipsis;white-space:nowrap;font-size:10.5px;overflow:hidden}.Sv3uVW_catalogDetailCounts{color:var(--dsw-alias-label-caption,#8080808c);align-items:center;gap:18px;font-size:10.5px;display:flex}.Sv3uVW_catalogDetailCounts span{align-items:baseline;gap:4px;display:inline-flex}.Sv3uVW_catalogDetailCounts strong{color:var(--dsw-alias-label-primary,inherit);font-variant-numeric:tabular-nums;font-size:13px}.Sv3uVW_catalogDetailTab,.Sv3uVW_catalogDetailTabActive{color:var(--dsw-alias-label-secondary,#808080cc);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:1;padding:6px 8px;font-size:11.5px}.Sv3uVW_catalogDetailTabActive{background:var(--dsw-alias-interactive-bg-active,#3b82f624);color:var(--dsw-alias-label-primary,inherit)}.Sv3uVW_catalogDetailScroll{overscroll-behavior:contain;flex-direction:column;flex:1;gap:9px;min-height:0;padding:12px;display:flex;overflow:auto}.Sv3uVW_catalogDetailScroll h3,.Sv3uVW_catalogDetailScroll p,.Sv3uVW_catalogDefinition pre,.Sv3uVW_catalogHistoryItem p{margin:0}.Sv3uVW_catalogDefinition,.Sv3uVW_catalogHistoryItem{border:1px solid var(--dsw-alias-border-l1,#80808033);border-radius:8px;flex-direction:column;gap:5px;padding:9px;display:flex}.Sv3uVW_catalogFacts{grid-template-columns:minmax(7rem,max-content) minmax(0,1fr);gap:.35rem .8rem;margin:.75rem 0;display:grid}.Sv3uVW_catalogFacts dt{color:var(--dsh-color-text-secondary,#64748b)}.Sv3uVW_catalogFacts dd{overflow-wrap:anywhere;min-width:0;margin:0}.Sv3uVW_catalogRelations{gap:.5rem;margin-top:1rem;display:grid}.Sv3uVW_catalogScanFacts{border-top:1px solid var(--dsw-alias-border-l1,#80808033);color:var(--dsw-alias-label-secondary,#808080cc);padding-top:8px}.Sv3uVW_catalogScanFacts summary{cursor:pointer;font-weight:600}.Sv3uVW_catalogBusinessEmpty{border:1px dashed var(--dsw-alias-border-l2,#80808059);color:var(--dsw-alias-label-secondary,#808080cc);border-radius:8px;flex-direction:column;gap:6px;padding:12px;display:flex}.Sv3uVW_catalogBusinessEmpty strong{color:var(--dsw-alias-label-primary,inherit)}.Sv3uVW_catalogBusinessEmpty p{margin:0}.Sv3uVW_catalogMeaningReview,.Sv3uVW_catalogMeaningSection,.Sv3uVW_catalogMeaningFields{flex-direction:column;display:flex}.Sv3uVW_catalogMeaningReview{gap:16px}.Sv3uVW_catalogMeaningSection{gap:8px}.Sv3uVW_catalogMeaningSection h4{margin:0;font-size:12px}.Sv3uVW_catalogMeaningFields{border:1px solid var(--dsw-alias-border-l1,#80808033);border-radius:8px;gap:0;overflow:hidden}.Sv3uVW_catalogMeaningField{border-bottom:1px solid var(--dsw-alias-border-l1,#80808029);grid-template-columns:minmax(110px,.32fr) minmax(0,1fr);gap:10px;padding:9px 10px;display:grid}.Sv3uVW_catalogMeaningField:last-child{border-bottom:0}.Sv3uVW_catalogMeaningFieldMeta{flex-direction:column;gap:3px;min-width:0;display:flex}.Sv3uVW_catalogMeaningFieldMeta strong,.Sv3uVW_catalogMeaningFieldMeta code{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.Sv3uVW_catalogMeaningFieldMeta code,.Sv3uVW_catalogMeaningOrigin,.Sv3uVW_catalogMeaningActions code{color:var(--dsw-alias-label-caption,#8080808c);font-size:10px}.Sv3uVW_catalogMeaningCard{border:1px solid var(--dsw-alias-border-l1,#80808033);background:var(--dsw-alias-bg-layer-2,#80808009);border-radius:8px;flex-direction:column;gap:7px;min-width:0;padding:10px;display:flex}.Sv3uVW_catalogMeaningCardCompact{background:0 0;border:0;padding:0}.Sv3uVW_catalogMeaningCard p,.Sv3uVW_catalogMeaningMissing{margin:0;line-height:1.55}.Sv3uVW_catalogMeaningMissing{color:var(--dsw-alias-label-caption,#8080808c)}.Sv3uVW_catalogMeaningOrigin{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.Sv3uVW_catalogMeaningActions{align-items:center;gap:6px;min-width:0;display:flex}.Sv3uVW_catalogMeaningActions code{text-overflow:ellipsis;white-space:nowrap;min-width:0;margin-left:auto;overflow:hidden}.Sv3uVW_catalogDefinition pre{background:var(--dsw-alias-markdown-code-block,#80808014);white-space:pre-wrap;border-radius:6px;padding:7px;font-size:11px;overflow:auto}.Sv3uVW_catalogEditor{border-top:1px solid var(--dsw-alias-border-l1,#80808033);flex-direction:column;gap:8px;padding-top:8px;display:flex}.Sv3uVW_catalogTextArea{box-sizing:border-box;resize:vertical;border:1px solid var(--dsw-alias-border-l2,#80808059);background:var(--dsw-alias-bg-layer-2,#ffffff0a);min-height:68px;color:var(--dsw-alias-label-primary,inherit);font:inherit;border-radius:8px;padding:8px 10px}.Sv3uVW_visuallyHidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;padding:0;position:absolute;overflow:hidden}.Sv3uVW_errorBar{border:1px solid var(--dsw-alias-state-error-secondary,#ef444480);background:var(--dsw-alias-interactive-bg-hover-danger,#ef444414);border-radius:10px;flex-direction:column;gap:3px;padding:10px 12px;display:flex}.Sv3uVW_errorHead{color:var(--dsw-alias-state-error-primary,#ef4444);align-items:center;gap:6px;font-size:12px;font-weight:600;display:flex}.Sv3uVW_errorIcon{flex:none}.Sv3uVW_errorText{white-space:pre-wrap;word-break:break-word;font-size:12px}@media (width<=760px){.Sv3uVW_catalogOverview{grid-template-columns:minmax(0,1fr)}.Sv3uVW_catalogStats{grid-template-columns:minmax(120px,auto) minmax(0,1fr)}.Sv3uVW_catalogWorkspace{flex-direction:column;height:auto;display:flex;overflow:visible}.Sv3uVW_catalogList,.Sv3uVW_catalogDetail{flex:none;height:min(420px,58vh);min-height:280px;max-height:420px}.Sv3uVW_catalogMeaningField{grid-template-columns:minmax(0,1fr)}}@media (width<=640px){.Sv3uVW_triggerSlot{top:-42px;right:10px}.Sv3uVW_workbenchModal{width:min(96vw,920px)}.Sv3uVW_workbenchModalContent{min-height:0;max-height:72vh}.Sv3uVW_workbench{min-height:0}.Sv3uVW_fieldRow2{grid-template-columns:1fr}.Sv3uVW_schemaPanel{flex-direction:column;height:auto;display:flex}.Sv3uVW_catalogScanBar,.Sv3uVW_catalogConfirm,.Sv3uVW_catalogProgress{flex-direction:column;align-items:stretch}.Sv3uVW_catalogControl,.Sv3uVW_catalogScanBar .Sv3uVW_input{width:100%;max-width:none}.Sv3uVW_catalogScanBar .Sv3uVW_input{flex:none}.Sv3uVW_catalogDiffBar,.Sv3uVW_catalogSearch{grid-template-columns:minmax(0,1fr)}.Sv3uVW_catalogActionGroup{grid-template-columns:minmax(0,1fr);gap:4px}.Sv3uVW_catalogSectionLabel{padding-top:0}.Sv3uVW_catalogDiffBar>*,.Sv3uVW_catalogSearchQuery,.Sv3uVW_catalogSearchActions{grid-column:1}.Sv3uVW_catalogSearchActions{flex-direction:column;align-items:stretch}.Sv3uVW_treeScroll{flex:none;height:240px}.Sv3uVW_colScroll{flex:none;height:220px}.Sv3uVW_emptyState{flex:none;min-height:120px}.Sv3uVW_rememberRow{flex-wrap:wrap;align-items:flex-start}.Sv3uVW_rememberHint{flex-basis:100%;padding-left:21px}.Sv3uVW_sqlResultToolbar{flex-direction:column;align-items:flex-start}.Sv3uVW_sqlResultMeta{white-space:normal;flex-wrap:wrap;max-width:100%}.Sv3uVW_sqlExportActions{width:100%}.Sv3uVW_sqlExportButton{flex:1}}@media (prefers-reduced-motion:reduce){.Sv3uVW_trigger,.Sv3uVW_input,.Sv3uVW_primary,.Sv3uVW_ghost,.Sv3uVW_sqlExportButton,.Sv3uVW_sqlPageButton,.Sv3uVW_treeChevron{transition:none}}";
97
1005
  const tagId$1 = "@yejiming/dsh-data-agent/DataAgentWorkbench.module.css";
98
1006
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
99
1007
  const tag = document.createElement("style");
@@ -103,64 +1011,2149 @@ window.__ModuleLoader__.load({
103
1011
  document.head.appendChild(tag);
104
1012
  }
105
1013
  var DataAgentWorkbench_module_css_default = {
106
- "workbench": "Sv3uVW_workbench",
107
- "summaryType": "Sv3uVW_summaryType",
1014
+ "catalogDetailTabActive": "Sv3uVW_catalogDetailTabActive",
1015
+ "trigger": "Sv3uVW_trigger",
1016
+ "catalogDetail": "Sv3uVW_catalogDetail",
1017
+ "catalogPanel": "Sv3uVW_catalogPanel",
1018
+ "catalogFacts": "Sv3uVW_catalogFacts",
1019
+ "visuallyHidden": "Sv3uVW_visuallyHidden",
1020
+ "catalogError": "Sv3uVW_catalogError",
1021
+ "rememberHint": "Sv3uVW_rememberHint",
1022
+ "catalogItemHead": "Sv3uVW_catalogItemHead",
1023
+ "catalogActionGroup": "Sv3uVW_catalogActionGroup",
108
1024
  "field": "Sv3uVW_field",
109
- "treeChildren": "Sv3uVW_treeChildren",
110
- "active": "Sv3uVW_active",
111
- "hint": "Sv3uVW_hint",
112
- "triggerActive": "Sv3uVW_triggerActive",
113
- "sqlResult": "Sv3uVW_sqlResult",
1025
+ "modalHint": "Sv3uVW_modalHint",
1026
+ "catalogLatestRun": "Sv3uVW_catalogLatestRun",
1027
+ "catalogDiffBar": "Sv3uVW_catalogDiffBar",
114
1028
  "errorIcon": "Sv3uVW_errorIcon",
115
- "nullCell": "Sv3uVW_nullCell",
116
- "tabPanel": "Sv3uVW_tabPanel",
117
- "emptyStateText": "Sv3uVW_emptyStateText",
118
- "modalColTitle": "Sv3uVW_modalColTitle",
119
- "label": "Sv3uVW_label",
1029
+ "catalogMeaningFields": "Sv3uVW_catalogMeaningFields",
1030
+ "catalogProgress": "Sv3uVW_catalogProgress",
1031
+ "errorBar": "Sv3uVW_errorBar",
1032
+ "connectionSummary": "Sv3uVW_connectionSummary",
1033
+ "ghost": "Sv3uVW_ghost",
1034
+ "treeCount": "Sv3uVW_treeCount",
1035
+ "primary": "Sv3uVW_primary",
1036
+ "sqlResultLimit": "Sv3uVW_sqlResultLimit",
1037
+ "catalogBadge_inferred": "Sv3uVW_catalogBadge_inferred",
1038
+ "catalogDetailTabs": "Sv3uVW_catalogDetailTabs",
1039
+ "catalogMeaningFieldMeta": "Sv3uVW_catalogMeaningFieldMeta",
120
1040
  "errorHead": "Sv3uVW_errorHead",
121
- "open": "Sv3uVW_open",
122
- "modalHint": "Sv3uVW_modalHint",
1041
+ "catalogCounts": "Sv3uVW_catalogCounts",
1042
+ "sqlNull": "Sv3uVW_sqlNull",
1043
+ "sqlPageButton": "Sv3uVW_sqlPageButton",
1044
+ "shortcutHint": "Sv3uVW_shortcutHint",
1045
+ "catalogLatestError": "Sv3uVW_catalogLatestError",
1046
+ "sqlResultEmpty": "Sv3uVW_sqlResultEmpty",
1047
+ "workbenchModalContent": "Sv3uVW_workbenchModalContent",
1048
+ "tabActive": "Sv3uVW_tabActive",
1049
+ "catalogMeaningSection": "Sv3uVW_catalogMeaningSection",
123
1050
  "rememberRow": "Sv3uVW_rememberRow",
124
- "ghost": "Sv3uVW_ghost",
125
- "tab": "Sv3uVW_tab",
126
- "connectionState": "Sv3uVW_connectionState",
127
- "fieldGrid": "Sv3uVW_fieldGrid",
1051
+ "catalogSectionLabel": "Sv3uVW_catalogSectionLabel",
1052
+ "schemaPanel": "Sv3uVW_schemaPanel",
128
1053
  "sqlPanel": "Sv3uVW_sqlPanel",
129
- "treeItem": "Sv3uVW_treeItem",
130
- "errorBar": "Sv3uVW_errorBar",
131
1054
  "colScroll": "Sv3uVW_colScroll",
132
- "connectionSummary": "Sv3uVW_connectionSummary",
133
- "typeCell": "Sv3uVW_typeCell",
134
- "schemaPanel": "Sv3uVW_schemaPanel",
135
- "treeNode": "Sv3uVW_treeNode",
136
- "rememberHint": "Sv3uVW_rememberHint",
1055
+ "sqlActions": "Sv3uVW_sqlActions",
1056
+ "catalogHistoryItem": "Sv3uVW_catalogHistoryItem",
1057
+ "catalogCheck": "Sv3uVW_catalogCheck",
1058
+ "catalogDetailTab": "Sv3uVW_catalogDetailTab",
1059
+ "catalogBadge_retired": "Sv3uVW_catalogBadge_retired",
1060
+ "emptyStateIcon": "Sv3uVW_emptyStateIcon",
1061
+ "fieldGrid": "Sv3uVW_fieldGrid",
1062
+ "catalogOverview": "Sv3uVW_catalogOverview",
137
1063
  "tabs": "Sv3uVW_tabs",
138
- "treeName": "Sv3uVW_treeName",
139
- "actions": "Sv3uVW_actions",
1064
+ "triggerSlot": "Sv3uVW_triggerSlot",
1065
+ "catalogSourceName": "Sv3uVW_catalogSourceName",
1066
+ "catalogScanTimes": "Sv3uVW_catalogScanTimes",
1067
+ "treeItem": "Sv3uVW_treeItem",
1068
+ "catalogScanFacts": "Sv3uVW_catalogScanFacts",
1069
+ "catalogMeaningCard": "Sv3uVW_catalogMeaningCard",
1070
+ "label": "Sv3uVW_label",
140
1071
  "treeChevron": "Sv3uVW_treeChevron",
141
- "triggerDot": "Sv3uVW_triggerDot",
142
- "workbenchModalContent": "Sv3uVW_workbenchModalContent",
143
- "fieldRow2": "Sv3uVW_fieldRow2",
144
- "tabActive": "Sv3uVW_tabActive",
145
- "modalCol": "Sv3uVW_modalCol",
146
- "emptyState": "Sv3uVW_emptyState",
147
- "input": "Sv3uVW_input",
148
- "treeCount": "Sv3uVW_treeCount",
149
- "sqlActions": "Sv3uVW_sqlActions",
150
- "colCount": "Sv3uVW_colCount",
151
1072
  "columnsTable": "Sv3uVW_columnsTable",
1073
+ "catalogScanBar": "Sv3uVW_catalogScanBar",
1074
+ "catalogBadge_missing": "Sv3uVW_catalogBadge_missing",
1075
+ "catalogMeaningMissing": "Sv3uVW_catalogMeaningMissing",
1076
+ "catalogMeaningOrigin": "Sv3uVW_catalogMeaningOrigin",
1077
+ "catalogActions": "Sv3uVW_catalogActions",
1078
+ "catalogStats": "Sv3uVW_catalogStats",
1079
+ "catalogToolbar": "Sv3uVW_catalogToolbar",
152
1080
  "summaryDb": "Sv3uVW_summaryDb",
153
- "trigger": "Sv3uVW_trigger",
154
- "treeScroll": "Sv3uVW_treeScroll",
155
- "triggerSlot": "Sv3uVW_triggerSlot",
156
- "treeIcon": "Sv3uVW_treeIcon",
1081
+ "catalogListEmpty": "Sv3uVW_catalogListEmpty",
1082
+ "catalogBadge_needs_review": "Sv3uVW_catalogBadge_needs_review",
1083
+ "sqlMessageError": "Sv3uVW_sqlMessageError",
1084
+ "nullCell": "Sv3uVW_nullCell",
1085
+ "connectionState": "Sv3uVW_connectionState",
1086
+ "catalogList": "Sv3uVW_catalogList",
1087
+ "sqlResultTable": "Sv3uVW_sqlResultTable",
1088
+ "treeChildren": "Sv3uVW_treeChildren",
1089
+ "catalogBadge_changed": "Sv3uVW_catalogBadge_changed",
1090
+ "catalogBadge_verified": "Sv3uVW_catalogBadge_verified",
1091
+ "catalogBusinessEmpty": "Sv3uVW_catalogBusinessEmpty",
1092
+ "catalogDetailTitle": "Sv3uVW_catalogDetailTitle",
1093
+ "tab": "Sv3uVW_tab",
1094
+ "triggerActive": "Sv3uVW_triggerActive",
1095
+ "sqlFeedback": "Sv3uVW_sqlFeedback",
1096
+ "catalogRelations": "Sv3uVW_catalogRelations",
1097
+ "sqlTableEmpty": "Sv3uVW_sqlTableEmpty",
1098
+ "colCount": "Sv3uVW_colCount",
1099
+ "sqlResultPanel": "Sv3uVW_sqlResultPanel",
1100
+ "catalogResults": "Sv3uVW_catalogResults",
1101
+ "catalogDetailHeader": "Sv3uVW_catalogDetailHeader",
1102
+ "catalogItemActive": "Sv3uVW_catalogItemActive",
1103
+ "input": "Sv3uVW_input",
1104
+ "catalogMeaningCardCompact": "Sv3uVW_catalogMeaningCardCompact",
1105
+ "catalogBadge_observed": "Sv3uVW_catalogBadge_observed",
1106
+ "treeName": "Sv3uVW_treeName",
1107
+ "hint": "Sv3uVW_hint",
1108
+ "catalogNotice": "Sv3uVW_catalogNotice",
1109
+ "catalogSearchActions": "Sv3uVW_catalogSearchActions",
1110
+ "catalogDefinition": "Sv3uVW_catalogDefinition",
1111
+ "sqlMessage": "Sv3uVW_sqlMessage",
1112
+ "sqlTableScroll": "Sv3uVW_sqlTableScroll",
1113
+ "catalogItem": "Sv3uVW_catalogItem",
1114
+ "fieldRow2": "Sv3uVW_fieldRow2",
1115
+ "catalogLatestLabel": "Sv3uVW_catalogLatestLabel",
1116
+ "catalogMeaningActions": "Sv3uVW_catalogMeaningActions",
1117
+ "sqlExportActions": "Sv3uVW_sqlExportActions",
1118
+ "summaryType": "Sv3uVW_summaryType",
1119
+ "catalogBadge_restored": "Sv3uVW_catalogBadge_restored",
1120
+ "catalogTextArea": "Sv3uVW_catalogTextArea",
1121
+ "catalogMeaningField": "Sv3uVW_catalogMeaningField",
1122
+ "sqlPagination": "Sv3uVW_sqlPagination",
1123
+ "sqlEmptyString": "Sv3uVW_sqlEmptyString",
1124
+ "catalogBadge_unavailable": "Sv3uVW_catalogBadge_unavailable",
1125
+ "modalColTitle": "Sv3uVW_modalColTitle",
1126
+ "open": "Sv3uVW_open",
1127
+ "catalogWorkspace": "Sv3uVW_catalogWorkspace",
1128
+ "workbench": "Sv3uVW_workbench",
157
1129
  "sqlInput": "Sv3uVW_sqlInput",
158
- "tree": "Sv3uVW_tree",
159
- "primary": "Sv3uVW_primary",
160
- "shortcutHint": "Sv3uVW_shortcutHint",
1130
+ "sqlExportButton": "Sv3uVW_sqlExportButton",
161
1131
  "errorText": "Sv3uVW_errorText",
162
- "emptyStateIcon": "Sv3uVW_emptyStateIcon",
163
- "workbenchModal": "Sv3uVW_workbenchModal"
1132
+ "tree": "Sv3uVW_tree",
1133
+ "catalogConfirm": "Sv3uVW_catalogConfirm",
1134
+ "typeCell": "Sv3uVW_typeCell",
1135
+ "catalogDetailCounts": "Sv3uVW_catalogDetailCounts",
1136
+ "catalogDetailScroll": "Sv3uVW_catalogDetailScroll",
1137
+ "triggerDot": "Sv3uVW_triggerDot",
1138
+ "treeScroll": "Sv3uVW_treeScroll",
1139
+ "emptyStateText": "Sv3uVW_emptyStateText",
1140
+ "catalogInlineNotice": "Sv3uVW_catalogInlineNotice",
1141
+ "catalogMeaningReview": "Sv3uVW_catalogMeaningReview",
1142
+ "actions": "Sv3uVW_actions",
1143
+ "sqlPageActions": "Sv3uVW_sqlPageActions",
1144
+ "treeNode": "Sv3uVW_treeNode",
1145
+ "treeIcon": "Sv3uVW_treeIcon",
1146
+ "tabPanel": "Sv3uVW_tabPanel",
1147
+ "workbenchModal": "Sv3uVW_workbenchModal",
1148
+ "modalCol": "Sv3uVW_modalCol",
1149
+ "catalogBadge": "Sv3uVW_catalogBadge",
1150
+ "sqlResultToolbar": "Sv3uVW_sqlResultToolbar",
1151
+ "catalogSearchQuery": "Sv3uVW_catalogSearchQuery",
1152
+ "catalogEditor": "Sv3uVW_catalogEditor",
1153
+ "emptyState": "Sv3uVW_emptyState",
1154
+ "catalogControl": "Sv3uVW_catalogControl",
1155
+ "sqlResultMeta": "Sv3uVW_sqlResultMeta",
1156
+ "catalogSearch": "Sv3uVW_catalogSearch",
1157
+ "active": "Sv3uVW_active"
1158
+ };
1159
+ //#endregion
1160
+ //#region src/client/QueryResultTable.tsx
1161
+ const RESULT_PAGE_SIZE = 100;
1162
+ function DownloadIcon() {
1163
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1164
+ width: "13",
1165
+ height: "13",
1166
+ viewBox: "0 0 16 16",
1167
+ fill: "none",
1168
+ "aria-hidden": "true",
1169
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1170
+ d: "M8 2.2V9.4M5.3 6.9L8 9.6L10.7 6.9",
1171
+ stroke: "currentColor",
1172
+ strokeWidth: "1.25",
1173
+ strokeLinecap: "round",
1174
+ strokeLinejoin: "round"
1175
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1176
+ d: "M3 11.3V13H13V11.3",
1177
+ stroke: "currentColor",
1178
+ strokeWidth: "1.25",
1179
+ strokeLinecap: "round",
1180
+ strokeLinejoin: "round"
1181
+ })]
1182
+ });
1183
+ }
1184
+ function CopyIcon() {
1185
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1186
+ width: "13",
1187
+ height: "13",
1188
+ viewBox: "0 0 16 16",
1189
+ fill: "none",
1190
+ "aria-hidden": "true",
1191
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
1192
+ x: "4",
1193
+ y: "3.5",
1194
+ width: "8.5",
1195
+ height: "10",
1196
+ rx: "1.5",
1197
+ stroke: "currentColor",
1198
+ strokeWidth: "1.2"
1199
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1200
+ d: "M6 3.8V2.5H10V3.8M4 6H2.5V12H4",
1201
+ stroke: "currentColor",
1202
+ strokeWidth: "1.2",
1203
+ strokeLinecap: "round",
1204
+ strokeLinejoin: "round"
1205
+ })]
1206
+ });
1207
+ }
1208
+ function resultFilename(extension) {
1209
+ return `query-result-${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace("T", "-").slice(0, 15)}.${extension}`;
1210
+ }
1211
+ function downloadBlob(blob, filename) {
1212
+ const url = URL.createObjectURL(blob);
1213
+ const anchor = document.createElement("a");
1214
+ anchor.href = url;
1215
+ anchor.download = filename;
1216
+ anchor.style.display = "none";
1217
+ document.body.append(anchor);
1218
+ anchor.click();
1219
+ anchor.remove();
1220
+ setTimeout(() => URL.revokeObjectURL(url), 0);
1221
+ }
1222
+ async function copyText(text) {
1223
+ if (navigator.clipboard?.writeText !== void 0) {
1224
+ await navigator.clipboard.writeText(text);
1225
+ return;
1226
+ }
1227
+ const textarea = document.createElement("textarea");
1228
+ textarea.value = text;
1229
+ textarea.readOnly = true;
1230
+ textarea.style.position = "fixed";
1231
+ textarea.style.opacity = "0";
1232
+ document.body.append(textarea);
1233
+ textarea.select();
1234
+ const copied = typeof document.execCommand === "function" && document.execCommand("copy");
1235
+ textarea.remove();
1236
+ if (!copied) throw new Error("clipboard unavailable");
1237
+ }
1238
+ function QueryResultTable({ result, t }) {
1239
+ const [page, setPage] = (0, react.useState)(0);
1240
+ const [exportBusy, setExportBusy] = (0, react.useState)(null);
1241
+ const [feedback, setFeedback] = (0, react.useState)(null);
1242
+ const totalPages = Math.max(1, Math.ceil(result.rows.length / RESULT_PAGE_SIZE));
1243
+ const safePage = Math.min(page, totalPages - 1);
1244
+ const pageStart = safePage * RESULT_PAGE_SIZE;
1245
+ const visibleRows = result.rows.slice(pageStart, pageStart + RESULT_PAGE_SIZE);
1246
+ const exportResult = async (format) => {
1247
+ const data = {
1248
+ columns: result.columns,
1249
+ rows: result.rows
1250
+ };
1251
+ setExportBusy(format);
1252
+ setFeedback(null);
1253
+ try {
1254
+ if (format === "excel") {
1255
+ const bytes = queryResultToXlsx(data);
1256
+ downloadBlob(new Blob([new Uint8Array(bytes).buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }), resultFilename("xlsx"));
1257
+ } else if (format === "csv") downloadBlob(new Blob([queryResultToCsv(data)], { type: "text/csv;charset=utf-8" }), resultFilename("csv"));
1258
+ else await copyText(queryResultToTsv(data));
1259
+ setFeedback(t(format === "clipboard" ? "wb.sql.copy.done" : "wb.sql.export.done", { rows: result.rows.length }));
1260
+ } catch (cause) {
1261
+ const detail = cause instanceof Error ? cause.message : String(cause);
1262
+ setFeedback(t("wb.sql.export.failed", { detail }));
1263
+ } finally {
1264
+ setExportBusy(null);
1265
+ }
1266
+ };
1267
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1268
+ className: DataAgentWorkbench_module_css_default.sqlResultPanel,
1269
+ children: [
1270
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1271
+ className: DataAgentWorkbench_module_css_default.sqlResultToolbar,
1272
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1273
+ className: DataAgentWorkbench_module_css_default.sqlResultMeta,
1274
+ "aria-live": "polite",
1275
+ children: [
1276
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("wb.sql.result.summary", {
1277
+ rows: result.rows.length,
1278
+ columns: result.columns.length,
1279
+ elapsed: result.elapsedMs
1280
+ }) }),
1281
+ result.truncated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1282
+ className: DataAgentWorkbench_module_css_default.sqlResultLimit,
1283
+ children: t("wb.sql.result.capped", { rows: result.maxRows })
1284
+ }),
1285
+ feedback !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1286
+ className: DataAgentWorkbench_module_css_default.sqlFeedback,
1287
+ role: "status",
1288
+ children: feedback
1289
+ })
1290
+ ]
1291
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1292
+ className: DataAgentWorkbench_module_css_default.sqlExportActions,
1293
+ "aria-label": t("wb.sql.export.actions"),
1294
+ children: [
1295
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1296
+ type: "button",
1297
+ className: DataAgentWorkbench_module_css_default.sqlExportButton,
1298
+ disabled: exportBusy !== null,
1299
+ onClick: () => {
1300
+ exportResult("excel");
1301
+ },
1302
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DownloadIcon, {}), exportBusy === "excel" ? t("wb.sql.exporting") : t("wb.sql.export.excel")]
1303
+ }),
1304
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1305
+ type: "button",
1306
+ className: DataAgentWorkbench_module_css_default.sqlExportButton,
1307
+ disabled: exportBusy !== null,
1308
+ onClick: () => {
1309
+ exportResult("csv");
1310
+ },
1311
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DownloadIcon, {}), exportBusy === "csv" ? t("wb.sql.exporting") : t("wb.sql.export.csv")]
1312
+ }),
1313
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1314
+ type: "button",
1315
+ className: DataAgentWorkbench_module_css_default.sqlExportButton,
1316
+ disabled: exportBusy !== null,
1317
+ onClick: () => {
1318
+ exportResult("clipboard");
1319
+ },
1320
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyIcon, {}), exportBusy === "clipboard" ? t("wb.sql.copying") : t("wb.sql.export.clipboard")]
1321
+ })
1322
+ ]
1323
+ })]
1324
+ }),
1325
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1326
+ className: DataAgentWorkbench_module_css_default.sqlTableScroll,
1327
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
1328
+ className: DataAgentWorkbench_module_css_default.sqlResultTable,
1329
+ children: [
1330
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("caption", {
1331
+ className: DataAgentWorkbench_module_css_default.visuallyHidden,
1332
+ children: t("wb.sql.result.table")
1333
+ }),
1334
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: result.columns.map((column) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
1335
+ scope: "col",
1336
+ children: column
1337
+ }, column)) }) }),
1338
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: visibleRows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1339
+ className: DataAgentWorkbench_module_css_default.sqlTableEmpty,
1340
+ colSpan: Math.max(1, result.columns.length),
1341
+ children: t("wb.sql.result.noRows")
1342
+ }) }) : visibleRows.map((row, rowIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: result.columns.map((column) => {
1343
+ const value = row[column];
1344
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1345
+ title: value ?? void 0,
1346
+ children: value === null || value === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1347
+ className: DataAgentWorkbench_module_css_default.sqlNull,
1348
+ children: "NULL"
1349
+ }) : value === "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1350
+ className: DataAgentWorkbench_module_css_default.sqlEmptyString,
1351
+ children: "''"
1352
+ }) : value
1353
+ }, column);
1354
+ }) }, pageStart + rowIndex)) })
1355
+ ]
1356
+ })
1357
+ }),
1358
+ totalPages > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1359
+ className: DataAgentWorkbench_module_css_default.sqlPagination,
1360
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("wb.sql.page.summary", {
1361
+ page: safePage + 1,
1362
+ pages: totalPages
1363
+ }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1364
+ className: DataAgentWorkbench_module_css_default.sqlPageActions,
1365
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1366
+ type: "button",
1367
+ className: DataAgentWorkbench_module_css_default.sqlPageButton,
1368
+ disabled: safePage === 0,
1369
+ onClick: () => setPage((value) => Math.max(0, value - 1)),
1370
+ children: t("wb.sql.page.previous")
1371
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1372
+ type: "button",
1373
+ className: DataAgentWorkbench_module_css_default.sqlPageButton,
1374
+ disabled: safePage >= totalPages - 1,
1375
+ onClick: () => setPage((value) => Math.min(totalPages - 1, value + 1)),
1376
+ children: t("wb.sql.page.next")
1377
+ })]
1378
+ })]
1379
+ })
1380
+ ]
1381
+ });
1382
+ }
1383
+ //#endregion
1384
+ //#region src/client/catalog-client.ts
1385
+ const BASE = "/plugins/data-agent/catalog";
1386
+ async function listCatalogSources(signal) {
1387
+ return (await request(`${BASE}/sources`, { signal })).sources;
1388
+ }
1389
+ async function getCatalogStatus(sourceId, signal) {
1390
+ const params = new URLSearchParams({ sourceId });
1391
+ return (await request(`${BASE}/status?${params}`, { signal })).status;
1392
+ }
1393
+ async function listCatalogRuns(sourceId, signal) {
1394
+ const params = new URLSearchParams({
1395
+ sourceId,
1396
+ limit: "100"
1397
+ });
1398
+ return (await request(`${BASE}/runs?${params}`, { signal })).runs;
1399
+ }
1400
+ async function searchCatalog(input, signal) {
1401
+ const params = new URLSearchParams({
1402
+ sourceId: input.sourceId,
1403
+ query: input.query.trim() || "*"
1404
+ });
1405
+ if (input.schema !== void 0 && input.schema !== "") params.set("schema", input.schema);
1406
+ if (input.assetKinds?.length) params.set("assetKinds", input.assetKinds.join(","));
1407
+ if (input.semanticKinds?.length) params.set("semanticKinds", input.semanticKinds.join(","));
1408
+ if (input.assetStatuses?.length) params.set("assetStatuses", input.assetStatuses.join(","));
1409
+ if (input.semanticStatuses?.length) params.set("semanticStatuses", input.semanticStatuses.join(","));
1410
+ if (input.includeInferred === true) params.set("includeInferred", "true");
1411
+ if (input.cursor !== void 0) params.set("cursor", input.cursor);
1412
+ if (input.pageSize !== void 0) params.set("pageSize", String(input.pageSize));
1413
+ return (await request(`${BASE}/search?${params}`, { signal })).page;
1414
+ }
1415
+ async function getCatalogAsset(sourceId, assetId, cursor, signal) {
1416
+ const params = new URLSearchParams({
1417
+ sourceId,
1418
+ pageSize: "100"
1419
+ });
1420
+ if (cursor !== void 0) params.set("cursor", cursor);
1421
+ return (await request(`${BASE}/assets/${encodeURIComponent(assetId)}?${params}`, { signal })).detail;
1422
+ }
1423
+ async function getCatalogSemantic(sourceId, semanticId, version, signal) {
1424
+ const params = new URLSearchParams({ sourceId });
1425
+ if (version !== void 0) params.set("version", String(version));
1426
+ return (await request(`${BASE}/semantics/${encodeURIComponent(semanticId)}?${params}`, { signal })).semantic;
1427
+ }
1428
+ async function startCatalogScan(sessionId, scope) {
1429
+ return (await request(`${BASE}/scan`, json({
1430
+ sessionId,
1431
+ scope
1432
+ }))).run;
1433
+ }
1434
+ async function cancelCatalogScan(sourceId, runId) {
1435
+ return (await request(`${BASE}/cancel`, json({
1436
+ sourceId,
1437
+ ...runId ? { runId } : {}
1438
+ }))).run;
1439
+ }
1440
+ async function getCatalogDiff(sourceId, from, to, cursor) {
1441
+ const params = new URLSearchParams({
1442
+ sourceId,
1443
+ pageSize: "100"
1444
+ });
1445
+ if (from !== void 0 && to !== void 0) {
1446
+ params.set("from", from);
1447
+ params.set("to", to);
1448
+ }
1449
+ if (cursor !== void 0) params.set("cursor", cursor);
1450
+ return (await request(`${BASE}/diff?${params}`)).diff;
1451
+ }
1452
+ async function saveCatalogCandidate(input) {
1453
+ return (await request(`${BASE}/semantics`, json(input))).semantic;
1454
+ }
1455
+ async function verifyCatalogSemantic(input) {
1456
+ return (await request(`${BASE}/semantics/${encodeURIComponent(input.semanticId)}/verify`, json({
1457
+ sourceId: input.sourceId,
1458
+ expectedVersion: input.expectedVersion,
1459
+ definition: input.definition
1460
+ }))).semantic;
1461
+ }
1462
+ async function retireCatalogSemantic(input) {
1463
+ return (await request(`${BASE}/semantics/${encodeURIComponent(input.semanticId)}/retire`, json({
1464
+ sourceId: input.sourceId,
1465
+ expectedVersion: input.expectedVersion,
1466
+ revisionNote: input.revisionNote
1467
+ }))).semantic;
1468
+ }
1469
+ async function dismissCatalogMeaning(input) {
1470
+ return (await request(`${BASE}/semantics/${encodeURIComponent(input.semanticId)}/dismiss`, json({
1471
+ sourceId: input.sourceId,
1472
+ expectedVersion: input.expectedVersion
1473
+ }))).semantic;
1474
+ }
1475
+ function json(body) {
1476
+ return {
1477
+ method: "POST",
1478
+ headers: { "content-type": "application/json" },
1479
+ body: JSON.stringify(body)
1480
+ };
1481
+ }
1482
+ async function request(url, init) {
1483
+ const response = await fetch(url, init);
1484
+ let body;
1485
+ try {
1486
+ body = await response.json();
1487
+ } catch {
1488
+ body = void 0;
1489
+ }
1490
+ if (!response.ok) {
1491
+ const error = body !== null && typeof body === "object" && typeof body.error === "string" ? body.error : `HTTP ${response.status}`;
1492
+ throw new Error(error);
1493
+ }
1494
+ return body;
1495
+ }
1496
+ //#endregion
1497
+ //#region src/client/CatalogPanel.tsx
1498
+ const EMPTY_DRAFT = {
1499
+ name: "",
1500
+ aliases: "",
1501
+ description: "",
1502
+ formula: "",
1503
+ grain: "",
1504
+ sourceAssetIds: "",
1505
+ timeFieldAssetId: "",
1506
+ filters: "",
1507
+ exclusions: "",
1508
+ validFrom: "",
1509
+ validTo: "",
1510
+ owner: "",
1511
+ revisionNote: ""
1512
+ };
1513
+ const EMPTY_TERM_DRAFT = {
1514
+ name: "",
1515
+ aliases: "",
1516
+ description: "",
1517
+ sourceAssetIds: "",
1518
+ validFrom: "",
1519
+ validTo: "",
1520
+ owner: "",
1521
+ revisionNote: ""
1522
+ };
1523
+ const catalogPanelMemory = /* @__PURE__ */ new WeakMap();
1524
+ function CatalogPanel(props) {
1525
+ const { active, connected, connectionProfileId, sessionId, t, onAvailabilityChange } = props;
1526
+ const saved = catalogPanelMemory.get(props.stateKey);
1527
+ const [sources, setSources] = (0, react.useState)(saved?.sources ?? []);
1528
+ const [sourceId, setSourceId] = (0, react.useState)(saved?.sourceId ?? "");
1529
+ const [status, setStatus] = (0, react.useState)(saved?.status ?? null);
1530
+ const [busy, setBusy] = (0, react.useState)(false);
1531
+ const [error, setError] = (0, react.useState)(null);
1532
+ const [query, setQuery] = (0, react.useState)(saved?.query ?? "");
1533
+ const [schema, setSchema] = (0, react.useState)(saved?.schema ?? "");
1534
+ const [kind, setKind] = (0, react.useState)(saved?.kind ?? "relation");
1535
+ const [assetStatus, setAssetStatus] = (0, react.useState)(saved?.assetStatus ?? "observed");
1536
+ const [semanticStatus, setSemanticStatus] = (0, react.useState)(saved?.semanticStatus ?? "");
1537
+ const [includeInferred, setIncludeInferred] = (0, react.useState)(saved?.includeInferred ?? false);
1538
+ const [items, setItems] = (0, react.useState)(saved?.items ?? []);
1539
+ const [nextCursor, setNextCursor] = (0, react.useState)(saved?.nextCursor);
1540
+ const [selection, setSelection] = (0, react.useState)(saved?.selection ?? null);
1541
+ const [assetDetail, setAssetDetail] = (0, react.useState)(saved?.assetDetail ?? null);
1542
+ const [semanticDetail, setSemanticDetail] = (0, react.useState)(saved?.semanticDetail ?? null);
1543
+ const [detailTab, setDetailTab] = (0, react.useState)(saved?.detailTab ?? "technical");
1544
+ const [scanKind, setScanKind] = (0, react.useState)(saved?.scanKind ?? "schema");
1545
+ const [scanSchema, setScanSchema] = (0, react.useState)(saved?.scanSchema ?? "");
1546
+ const [scanTable, setScanTable] = (0, react.useState)(saved?.scanTable ?? "");
1547
+ const [confirmFull, setConfirmFull] = (0, react.useState)(false);
1548
+ const [diff, setDiff] = (0, react.useState)(saved?.diff ?? null);
1549
+ const [runs, setRuns] = (0, react.useState)(saved?.runs ?? []);
1550
+ const [diffFrom, setDiffFrom] = (0, react.useState)(saved?.diffFrom ?? "");
1551
+ const [diffTo, setDiffTo] = (0, react.useState)(saved?.diffTo ?? "");
1552
+ const [editingMetric, setEditingMetric] = (0, react.useState)(saved?.editingMetric ?? false);
1553
+ const [metricDraft, setMetricDraft] = (0, react.useState)(saved?.metricDraft ?? EMPTY_DRAFT);
1554
+ const [editingTerm, setEditingTerm] = (0, react.useState)(saved?.editingTerm ?? false);
1555
+ const [termDraft, setTermDraft] = (0, react.useState)(saved?.termDraft ?? EMPTY_TERM_DRAFT);
1556
+ const detailRequestId = (0, react.useRef)(0);
1557
+ const detailController = (0, react.useRef)(null);
1558
+ const previousSourceId = (0, react.useRef)(sourceId);
1559
+ const searchInput = (0, react.useRef)({
1560
+ query,
1561
+ schema,
1562
+ kind,
1563
+ assetStatus,
1564
+ semanticStatus,
1565
+ includeInferred
1566
+ });
1567
+ (0, react.useEffect)(() => {
1568
+ searchInput.current = {
1569
+ query,
1570
+ schema,
1571
+ kind,
1572
+ assetStatus,
1573
+ semanticStatus,
1574
+ includeInferred
1575
+ };
1576
+ }, [
1577
+ query,
1578
+ schema,
1579
+ kind,
1580
+ assetStatus,
1581
+ semanticStatus,
1582
+ includeInferred
1583
+ ]);
1584
+ (0, react.useEffect)(() => {
1585
+ catalogPanelMemory.set(props.stateKey, {
1586
+ sources,
1587
+ sourceId,
1588
+ status,
1589
+ query,
1590
+ schema,
1591
+ kind,
1592
+ assetStatus,
1593
+ semanticStatus,
1594
+ includeInferred,
1595
+ items,
1596
+ ...nextCursor !== void 0 ? { nextCursor } : {},
1597
+ selection,
1598
+ assetDetail,
1599
+ semanticDetail,
1600
+ detailTab,
1601
+ scanKind,
1602
+ scanSchema,
1603
+ scanTable,
1604
+ diff,
1605
+ runs,
1606
+ diffFrom,
1607
+ diffTo,
1608
+ editingMetric,
1609
+ metricDraft,
1610
+ editingTerm,
1611
+ termDraft
1612
+ });
1613
+ });
1614
+ const scanAllowed = connected && connectionProfileId !== void 0 && (sourceId === "" || sourceId === connectionProfileId);
1615
+ const activeRun = status?.activeRun;
1616
+ const reportError = (0, react.useCallback)((cause) => {
1617
+ setError(cause instanceof Error ? cause.message : String(cause));
1618
+ }, []);
1619
+ const refreshSources = (0, react.useCallback)(async (signal) => {
1620
+ const response = await listCatalogSources(signal);
1621
+ if (signal?.aborted) return [];
1622
+ const next = Array.isArray(response) ? response : [];
1623
+ setSources(next);
1624
+ onAvailabilityChange(next.length > 0);
1625
+ setSourceId((current) => {
1626
+ if (current !== "" && next.some((source) => source.id === current)) return current;
1627
+ if (connectionProfileId !== void 0 && next.some((source) => source.id === connectionProfileId)) return connectionProfileId;
1628
+ return next[0]?.id ?? "";
1629
+ });
1630
+ return next;
1631
+ }, [connectionProfileId, onAvailabilityChange]);
1632
+ (0, react.useEffect)(() => {
1633
+ const controller = new AbortController();
1634
+ refreshSources(controller.signal).catch((cause) => {
1635
+ if (!controller.signal.aborted) reportError(cause);
1636
+ });
1637
+ return () => controller.abort();
1638
+ }, [refreshSources, reportError]);
1639
+ (0, react.useEffect)(() => () => detailController.current?.abort(), []);
1640
+ const refreshStatus = (0, react.useCallback)(async (signal) => {
1641
+ if (sourceId === "") {
1642
+ setStatus(null);
1643
+ return null;
1644
+ }
1645
+ const next = await getCatalogStatus(sourceId, signal);
1646
+ if (signal?.aborted) return next;
1647
+ setStatus(next);
1648
+ return next;
1649
+ }, [sourceId]);
1650
+ const refreshRuns = (0, react.useCallback)(async (signal) => {
1651
+ if (sourceId === "") {
1652
+ setRuns([]);
1653
+ return;
1654
+ }
1655
+ const next = await listCatalogRuns(sourceId, signal);
1656
+ if (signal?.aborted) return;
1657
+ setRuns(next);
1658
+ const successful = next.filter((run) => run.status === "succeeded");
1659
+ setDiffFrom((current) => successful.some((run) => run.id === current) ? current : successful.at(-2)?.id ?? "");
1660
+ setDiffTo((current) => successful.some((run) => run.id === current) ? current : successful.at(-1)?.id ?? "");
1661
+ }, [sourceId]);
1662
+ const runSearch = (0, react.useCallback)(async (cursor, append = false, signal) => {
1663
+ if (sourceId === "") {
1664
+ setItems([]);
1665
+ setNextCursor(void 0);
1666
+ return;
1667
+ }
1668
+ const input = searchInput.current;
1669
+ const page = await searchCatalog({
1670
+ sourceId,
1671
+ query: input.query,
1672
+ ...input.schema !== "" ? { schema: input.schema } : {},
1673
+ ...input.kind === "relation" ? { assetKinds: ["table", "view"] } : {},
1674
+ ...input.kind !== "" && input.kind !== "relation" && input.kind !== "meaning" && input.kind !== "term" && input.kind !== "metric" ? { assetKinds: [input.kind] } : {},
1675
+ ...input.kind === "meaning" || input.kind === "term" || input.kind === "metric" ? { semanticKinds: [input.kind] } : {},
1676
+ ...input.assetStatus !== "" ? { assetStatuses: [input.assetStatus] } : {},
1677
+ ...input.semanticStatus !== "" ? { semanticStatuses: [input.semanticStatus] } : {},
1678
+ includeInferred: input.includeInferred,
1679
+ ...cursor !== void 0 ? { cursor } : {},
1680
+ pageSize: 50
1681
+ }, signal);
1682
+ if (signal?.aborted) return;
1683
+ setItems((current) => append ? [...current, ...page.items] : page.items);
1684
+ setNextCursor(page.nextCursor);
1685
+ }, [sourceId]);
1686
+ (0, react.useEffect)(() => {
1687
+ if (previousSourceId.current === sourceId) return;
1688
+ previousSourceId.current = sourceId;
1689
+ detailRequestId.current += 1;
1690
+ detailController.current?.abort();
1691
+ setSelection(null);
1692
+ setAssetDetail(null);
1693
+ setSemanticDetail(null);
1694
+ setDiff(null);
1695
+ setEditingMetric(false);
1696
+ setEditingTerm(false);
1697
+ const selectedSource = sources.find((source) => source.id === sourceId);
1698
+ const nextSearch = {
1699
+ query: "",
1700
+ schema: selectedSource === void 0 ? "" : defaultBrowseSchema(selectedSource),
1701
+ kind: "relation",
1702
+ assetStatus: "observed",
1703
+ semanticStatus: "",
1704
+ includeInferred: false
1705
+ };
1706
+ searchInput.current = nextSearch;
1707
+ setQuery(nextSearch.query);
1708
+ setSchema(nextSearch.schema);
1709
+ setKind(nextSearch.kind);
1710
+ setAssetStatus(nextSearch.assetStatus);
1711
+ setSemanticStatus(nextSearch.semanticStatus);
1712
+ setIncludeInferred(nextSearch.includeInferred);
1713
+ }, [sourceId, sources]);
1714
+ (0, react.useEffect)(() => {
1715
+ if (sourceId === "") return;
1716
+ const controller = new AbortController();
1717
+ setBusy(true);
1718
+ Promise.all([
1719
+ refreshStatus(controller.signal),
1720
+ refreshRuns(controller.signal),
1721
+ runSearch(void 0, false, controller.signal)
1722
+ ]).catch((cause) => {
1723
+ if (!controller.signal.aborted) reportError(cause);
1724
+ }).finally(() => {
1725
+ if (!controller.signal.aborted) setBusy(false);
1726
+ });
1727
+ return () => controller.abort();
1728
+ }, [
1729
+ sourceId,
1730
+ refreshStatus,
1731
+ refreshRuns,
1732
+ runSearch,
1733
+ reportError
1734
+ ]);
1735
+ (0, react.useEffect)(() => {
1736
+ if (!active || activeRun === void 0 || sourceId === "") return;
1737
+ const timer = window.setInterval(() => {
1738
+ refreshStatus().then((next) => Promise.all([runSearch(), ...next?.activeRun === void 0 ? [refreshSources(), refreshRuns()] : []])).catch(reportError);
1739
+ }, 1500);
1740
+ return () => window.clearInterval(timer);
1741
+ }, [
1742
+ active,
1743
+ activeRun,
1744
+ sourceId,
1745
+ refreshStatus,
1746
+ runSearch,
1747
+ refreshSources,
1748
+ refreshRuns,
1749
+ reportError
1750
+ ]);
1751
+ const selectItem = async (item) => {
1752
+ detailController.current?.abort();
1753
+ const controller = new AbortController();
1754
+ detailController.current = controller;
1755
+ const requestId = ++detailRequestId.current;
1756
+ setSelection({
1757
+ type: item.resultType,
1758
+ item
1759
+ });
1760
+ setDetailTab(item.resultType === "asset" ? "technical" : "business");
1761
+ setAssetDetail(null);
1762
+ setSemanticDetail(null);
1763
+ setEditingMetric(false);
1764
+ setEditingTerm(false);
1765
+ setBusy(true);
1766
+ setError(null);
1767
+ try {
1768
+ if (item.resultType === "asset") {
1769
+ const detail = await getCatalogAsset(sourceId, item.id, void 0, controller.signal);
1770
+ if (requestId === detailRequestId.current) setAssetDetail(detail);
1771
+ } else {
1772
+ const semantic = await getCatalogSemantic(sourceId, item.id, void 0, controller.signal);
1773
+ if (requestId !== detailRequestId.current) return;
1774
+ setSemanticDetail(semantic);
1775
+ if (semantic.definition.kind === "metric") setMetricDraft(draftFromSemantic(semantic));
1776
+ else if (semantic.definition.kind === "term") setTermDraft(termDraftFromSemantic(semantic));
1777
+ }
1778
+ } catch (cause) {
1779
+ if (!controller.signal.aborted && requestId === detailRequestId.current) reportError(cause);
1780
+ } finally {
1781
+ setBusy((current) => requestId === detailRequestId.current ? false : current);
1782
+ }
1783
+ };
1784
+ const loadMoreFields = async () => {
1785
+ if (assetDetail?.nextCursor === void 0 || sourceId === "") return;
1786
+ setBusy(true);
1787
+ try {
1788
+ const next = await getCatalogAsset(sourceId, assetDetail.asset.assetId, assetDetail.nextCursor);
1789
+ setAssetDetail({
1790
+ ...next,
1791
+ fields: [...assetDetail.fields, ...next.fields],
1792
+ relations: [...new Map([...assetDetail.relations, ...next.relations].map((value) => [value.id, value])).values()],
1793
+ semantics: [...new Map([...assetDetail.semantics, ...next.semantics].map((value) => [value.semanticId, value])).values()],
1794
+ history: [...new Map([...assetDetail.history, ...next.history].map((value) => [value.id, value])).values()]
1795
+ });
1796
+ } catch (cause) {
1797
+ reportError(cause);
1798
+ } finally {
1799
+ setBusy(false);
1800
+ }
1801
+ };
1802
+ const beginScan = async () => {
1803
+ if (!scanAllowed) {
1804
+ setError(t("catalog.scan.reconnect"));
1805
+ return;
1806
+ }
1807
+ if (scanKind === "source" && !confirmFull) {
1808
+ setConfirmFull(true);
1809
+ return;
1810
+ }
1811
+ let scope;
1812
+ if (scanKind === "source") scope = { kind: "source" };
1813
+ else if (scanKind === "schema") {
1814
+ if (scanSchema.trim() === "") {
1815
+ setError(t("catalog.validation.schema"));
1816
+ return;
1817
+ }
1818
+ scope = {
1819
+ kind: "schema",
1820
+ schema: scanSchema.trim()
1821
+ };
1822
+ } else {
1823
+ if (scanSchema.trim() === "" || scanTable.trim() === "") {
1824
+ setError(t("catalog.validation.table"));
1825
+ return;
1826
+ }
1827
+ scope = {
1828
+ kind: "table",
1829
+ schema: scanSchema.trim(),
1830
+ table: scanTable.trim()
1831
+ };
1832
+ }
1833
+ setBusy(true);
1834
+ setError(null);
1835
+ try {
1836
+ await startCatalogScan(sessionId, scope);
1837
+ const nextSources = await refreshSources();
1838
+ const nextSourceId = connectionProfileId ?? nextSources[0]?.id;
1839
+ if (nextSourceId !== void 0) {
1840
+ setSourceId(nextSourceId);
1841
+ setStatus(await getCatalogStatus(nextSourceId));
1842
+ }
1843
+ setConfirmFull(false);
1844
+ } catch (cause) {
1845
+ reportError(cause);
1846
+ } finally {
1847
+ setBusy(false);
1848
+ }
1849
+ };
1850
+ const cancelScan = async () => {
1851
+ if (sourceId === "" || activeRun === void 0) return;
1852
+ setBusy(true);
1853
+ try {
1854
+ await cancelCatalogScan(sourceId, activeRun.id);
1855
+ await refreshStatus();
1856
+ } catch (cause) {
1857
+ reportError(cause);
1858
+ } finally {
1859
+ setBusy(false);
1860
+ }
1861
+ };
1862
+ const loadDiff = async (cursor, append = false) => {
1863
+ if (sourceId === "") return;
1864
+ setBusy(true);
1865
+ try {
1866
+ const next = await getCatalogDiff(sourceId, diffFrom || void 0, diffTo || void 0, cursor);
1867
+ setDiff((current) => append && current !== null ? {
1868
+ ...next,
1869
+ items: [...current.items, ...next.items]
1870
+ } : next);
1871
+ } catch (cause) {
1872
+ reportError(cause);
1873
+ } finally {
1874
+ setBusy(false);
1875
+ }
1876
+ };
1877
+ const startMetric = (semantic) => {
1878
+ setEditingMetric(true);
1879
+ setEditingTerm(false);
1880
+ setDetailTab("business");
1881
+ setMetricDraft(semantic?.definition.kind === "metric" ? draftFromSemantic(semantic) : {
1882
+ ...EMPTY_DRAFT,
1883
+ sourceAssetIds: selection?.type === "asset" ? selection.item.id : ""
1884
+ });
1885
+ };
1886
+ const startTerm = (semantic) => {
1887
+ setEditingTerm(true);
1888
+ setEditingMetric(false);
1889
+ setDetailTab("business");
1890
+ setTermDraft(semantic?.definition.kind === "term" ? termDraftFromSemantic(semantic) : {
1891
+ ...EMPTY_TERM_DRAFT,
1892
+ sourceAssetIds: selection?.type === "asset" ? selection.item.id : ""
1893
+ });
1894
+ };
1895
+ const metricDefinition = (state) => {
1896
+ return {
1897
+ kind: "metric",
1898
+ name: metricDraft.name,
1899
+ aliases: splitList(metricDraft.aliases),
1900
+ description: metricDraft.description,
1901
+ owner: metricDraft.owner || void 0,
1902
+ sourceAssetIds: splitList(metricDraft.sourceAssetIds),
1903
+ status: state,
1904
+ formula: metricDraft.formula,
1905
+ grain: metricDraft.grain,
1906
+ timeFieldAssetId: metricDraft.timeFieldAssetId || void 0,
1907
+ filters: splitLines(metricDraft.filters),
1908
+ exclusions: splitLines(metricDraft.exclusions),
1909
+ validFrom: metricDraft.validFrom || void 0,
1910
+ validTo: metricDraft.validTo || void 0,
1911
+ revisionNote: metricDraft.revisionNote
1912
+ };
1913
+ };
1914
+ const termDefinition = (state) => ({
1915
+ kind: "term",
1916
+ name: termDraft.name,
1917
+ aliases: splitList(termDraft.aliases),
1918
+ description: termDraft.description,
1919
+ owner: termDraft.owner || void 0,
1920
+ sourceAssetIds: splitList(termDraft.sourceAssetIds),
1921
+ status: state,
1922
+ validFrom: termDraft.validFrom || void 0,
1923
+ validTo: termDraft.validTo || void 0,
1924
+ revisionNote: termDraft.revisionNote
1925
+ });
1926
+ const saveMetric = async (verify) => {
1927
+ if (sourceId === "" || metricDraft.name.trim() === "" || metricDraft.formula.trim() === "" || metricDraft.grain.trim() === "") return;
1928
+ setBusy(true);
1929
+ setError(null);
1930
+ try {
1931
+ const semantic = verify && semanticDetail !== null ? await verifyCatalogSemantic({
1932
+ sourceId,
1933
+ semanticId: semanticDetail.semanticId,
1934
+ expectedVersion: semanticDetail.version,
1935
+ definition: metricDefinition("verified")
1936
+ }) : await saveCatalogCandidate({
1937
+ sourceId,
1938
+ ...semanticDetail !== null ? {
1939
+ semanticId: semanticDetail.semanticId,
1940
+ expectedVersion: semanticDetail.version
1941
+ } : {},
1942
+ definition: metricDefinition("inferred")
1943
+ });
1944
+ setSemanticDetail(semantic);
1945
+ setMetricDraft(draftFromSemantic(semantic));
1946
+ setEditingMetric(false);
1947
+ await runSearch();
1948
+ await refreshStatus();
1949
+ } catch (cause) {
1950
+ reportError(cause);
1951
+ } finally {
1952
+ setBusy(false);
1953
+ }
1954
+ };
1955
+ const saveTerm = async (verify) => {
1956
+ if (sourceId === "" || termDraft.name.trim() === "" || termDraft.description.trim() === "") return;
1957
+ setBusy(true);
1958
+ setError(null);
1959
+ try {
1960
+ const semantic = verify && semanticDetail !== null ? await verifyCatalogSemantic({
1961
+ sourceId,
1962
+ semanticId: semanticDetail.semanticId,
1963
+ expectedVersion: semanticDetail.version,
1964
+ definition: termDefinition("verified")
1965
+ }) : await saveCatalogCandidate({
1966
+ sourceId,
1967
+ ...semanticDetail !== null ? {
1968
+ semanticId: semanticDetail.semanticId,
1969
+ expectedVersion: semanticDetail.version
1970
+ } : {},
1971
+ definition: termDefinition("inferred")
1972
+ });
1973
+ setSemanticDetail(semantic);
1974
+ setTermDraft(termDraftFromSemantic(semantic));
1975
+ setEditingTerm(false);
1976
+ await runSearch();
1977
+ await refreshStatus();
1978
+ } catch (cause) {
1979
+ reportError(cause);
1980
+ } finally {
1981
+ setBusy(false);
1982
+ }
1983
+ };
1984
+ const retireSemantic = async (revisionNote) => {
1985
+ if (sourceId === "" || semanticDetail === null || revisionNote.trim() === "") return;
1986
+ setBusy(true);
1987
+ try {
1988
+ const semantic = await retireCatalogSemantic({
1989
+ sourceId,
1990
+ semanticId: semanticDetail.semanticId,
1991
+ expectedVersion: semanticDetail.version,
1992
+ revisionNote
1993
+ });
1994
+ setSemanticDetail(semantic);
1995
+ await runSearch();
1996
+ await refreshStatus();
1997
+ } catch (cause) {
1998
+ reportError(cause);
1999
+ } finally {
2000
+ setBusy(false);
2001
+ }
2002
+ };
2003
+ const refreshSelectedAsset = async () => {
2004
+ if (sourceId === "" || assetDetail === null) return;
2005
+ setAssetDetail(await getCatalogAsset(sourceId, assetDetail.asset.assetId));
2006
+ };
2007
+ const confirmMeaning = async (meaning) => {
2008
+ if (sourceId === "" || meaning.definition.kind !== "meaning") return;
2009
+ setBusy(true);
2010
+ setError(null);
2011
+ try {
2012
+ const semantic = await verifyCatalogSemantic({
2013
+ sourceId,
2014
+ semanticId: meaning.semanticId,
2015
+ expectedVersion: meaning.version,
2016
+ definition: {
2017
+ ...meaning.definition,
2018
+ status: "verified",
2019
+ revisionNote: "AI-generated business meaning confirmed in Catalog UI"
2020
+ }
2021
+ });
2022
+ if (semanticDetail?.semanticId === semantic.semanticId) setSemanticDetail(semantic);
2023
+ await Promise.all([
2024
+ refreshSelectedAsset(),
2025
+ runSearch(),
2026
+ refreshStatus()
2027
+ ]);
2028
+ } catch (cause) {
2029
+ reportError(cause);
2030
+ } finally {
2031
+ setBusy(false);
2032
+ }
2033
+ };
2034
+ const dismissMeaning = async (meaning) => {
2035
+ if (sourceId === "" || meaning.definition.kind !== "meaning") return;
2036
+ setBusy(true);
2037
+ setError(null);
2038
+ try {
2039
+ await dismissCatalogMeaning({
2040
+ sourceId,
2041
+ semanticId: meaning.semanticId,
2042
+ expectedVersion: meaning.version
2043
+ });
2044
+ if (semanticDetail?.semanticId === meaning.semanticId) setSemanticDetail(null);
2045
+ await Promise.all([
2046
+ refreshSelectedAsset(),
2047
+ runSearch(),
2048
+ refreshStatus()
2049
+ ]);
2050
+ } catch (cause) {
2051
+ reportError(cause);
2052
+ } finally {
2053
+ setBusy(false);
2054
+ }
2055
+ };
2056
+ const statusLabel = (value) => {
2057
+ const key = `catalog.state.${value}`;
2058
+ return key in STATUS_KEYS ? t(key) : value;
2059
+ };
2060
+ const kindLabel = (value) => {
2061
+ const key = `catalog.kind.${value}`;
2062
+ return key in KIND_KEYS ? t(key) : value;
2063
+ };
2064
+ const displayedSource = sources.find((source) => source.id === sourceId);
2065
+ const scopeInputs = scanKind !== "source";
2066
+ const technicalRows = assetDetail?.fields ?? [];
2067
+ const businessDefinitions = assetDetail?.semantics ?? (semanticDetail ? [semanticDetail] : []);
2068
+ const meaningDefinitions = businessDefinitions.filter((value) => value.definition.kind === "meaning");
2069
+ const governedDefinitions = businessDefinitions.filter((value) => value.definition.kind !== "meaning");
2070
+ const assetKind = assetDetail?.asset.payload.identity.kind;
2071
+ const relationDetail = assetKind === "table" || assetKind === "view";
2072
+ const fieldDetail = assetKind === "column";
2073
+ const fieldCount = assetDetail === null ? 0 : `${technicalRows.length}${assetDetail.nextCursor === void 0 ? "" : "+"}`;
2074
+ const tableMeaning = assetDetail === null ? void 0 : meaningDefinitions.find((value) => value.definition.kind === "meaning" && value.definition.targetAssetId === assetDetail.asset.assetId);
2075
+ const fieldMeanings = new Map(meaningDefinitions.flatMap((value) => value.definition.kind === "meaning" ? [[value.definition.targetAssetId, value]] : []));
2076
+ const canVerify = semanticDetail !== null && semanticDetail.definition.status !== "retired";
2077
+ const canSaveMetric = metricDraft.name.trim() !== "" && metricDraft.formula.trim() !== "" && metricDraft.grain.trim() !== "";
2078
+ const canSaveTerm = termDraft.name.trim() !== "" && termDraft.description.trim() !== "";
2079
+ const canVerifyMetric = canVerify && canSaveMetric && metricDraft.revisionNote.trim() !== "";
2080
+ const canVerifyTerm = canVerify && canSaveTerm && termDraft.revisionNote.trim() !== "";
2081
+ const successfulRuns = runs.filter((run) => run.status === "succeeded");
2082
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2083
+ id: props.id,
2084
+ role: "tabpanel",
2085
+ "aria-labelledby": props.labelledBy,
2086
+ className: `${DataAgentWorkbench_module_css_default.tabPanel} ${DataAgentWorkbench_module_css_default.catalogPanel}`,
2087
+ hidden: !active,
2088
+ children: [
2089
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2090
+ className: DataAgentWorkbench_module_css_default.catalogToolbar,
2091
+ children: [
2092
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2093
+ className: DataAgentWorkbench_module_css_default.catalogOverview,
2094
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
2095
+ className: DataAgentWorkbench_module_css_default.catalogControl,
2096
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("catalog.source") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2097
+ className: DataAgentWorkbench_module_css_default.input,
2098
+ value: sourceId,
2099
+ onChange: (event) => setSourceId(event.target.value),
2100
+ children: [sources.length === 0 && connectionProfileId !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2101
+ value: "",
2102
+ children: t("catalog.source.current")
2103
+ }), sources.map((source) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
2104
+ value: source.id,
2105
+ children: [
2106
+ source.name,
2107
+ " · ",
2108
+ source.database
2109
+ ]
2110
+ }, source.id))]
2111
+ })]
2112
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2113
+ className: DataAgentWorkbench_module_css_default.catalogStats,
2114
+ role: "status",
2115
+ children: [
2116
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
2117
+ className: DataAgentWorkbench_module_css_default.catalogSourceName,
2118
+ children: displayedSource?.name ?? t("catalog.status.never")
2119
+ }),
2120
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2121
+ className: DataAgentWorkbench_module_css_default.catalogCounts,
2122
+ children: [
2123
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: status?.counts.assets ?? 0 }), t("catalog.count.assets")] }),
2124
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: status?.counts.fields ?? 0 }), t("catalog.count.fields")] }),
2125
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: status?.counts.needsReview ?? 0 }), t("catalog.count.review")] })
2126
+ ]
2127
+ }),
2128
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2129
+ className: DataAgentWorkbench_module_css_default.catalogScanTimes,
2130
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
2131
+ t("catalog.status.full"),
2132
+ " ",
2133
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", { children: displayedSource?.lastFullScanAt ?? "—" })
2134
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
2135
+ t("catalog.status.partial"),
2136
+ " ",
2137
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", { children: displayedSource?.lastPartialScanAt ?? "—" })
2138
+ ] })]
2139
+ })
2140
+ ]
2141
+ })]
2142
+ }),
2143
+ status?.latestRun !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2144
+ className: DataAgentWorkbench_module_css_default.catalogLatestRun,
2145
+ "data-error": status.latestRun.status === "failed" || status.latestRun.enrichment?.status === "failed" || void 0,
2146
+ children: [
2147
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2148
+ className: DataAgentWorkbench_module_css_default.catalogLatestLabel,
2149
+ children: t("catalog.status.latest")
2150
+ }),
2151
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2152
+ className: DataAgentWorkbench_module_css_default.catalogBadge,
2153
+ children: statusLabel(status.latestRun.status)
2154
+ }),
2155
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
2156
+ title: status.latestRun.id,
2157
+ children: status.latestRun.id
2158
+ }),
2159
+ status.latestRun.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2160
+ className: DataAgentWorkbench_module_css_default.catalogLatestError,
2161
+ children: [
2162
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("catalog.status.failureReason") }),
2163
+ " ",
2164
+ status.latestRun.error
2165
+ ]
2166
+ }),
2167
+ status.latestRun.enrichment !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2168
+ className: DataAgentWorkbench_module_css_default.catalogLatestError,
2169
+ children: [
2170
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("catalog.enrichment.label") }),
2171
+ " ",
2172
+ t(`catalog.enrichment.${status.latestRun.enrichment.status}`),
2173
+ " · ",
2174
+ status.latestRun.enrichment.tablesCompleted,
2175
+ "/",
2176
+ status.latestRun.enrichment.tablesTotal,
2177
+ status.latestRun.enrichment.error !== void 0 ? ` · ${status.latestRun.enrichment.error}` : ""
2178
+ ]
2179
+ })
2180
+ ]
2181
+ }),
2182
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2183
+ className: DataAgentWorkbench_module_css_default.catalogActions,
2184
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2185
+ className: DataAgentWorkbench_module_css_default.catalogActionGroup,
2186
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2187
+ className: DataAgentWorkbench_module_css_default.catalogSectionLabel,
2188
+ children: t("catalog.section.scan")
2189
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2190
+ className: DataAgentWorkbench_module_css_default.catalogScanBar,
2191
+ children: [
2192
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2193
+ className: DataAgentWorkbench_module_css_default.input,
2194
+ value: scanKind,
2195
+ disabled: activeRun !== void 0,
2196
+ onChange: (event) => {
2197
+ setScanKind(event.target.value);
2198
+ setConfirmFull(false);
2199
+ },
2200
+ "aria-label": t("catalog.scan"),
2201
+ children: [
2202
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2203
+ value: "source",
2204
+ children: t("catalog.scan.all")
2205
+ }),
2206
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2207
+ value: "schema",
2208
+ children: t("catalog.scan.schema")
2209
+ }),
2210
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2211
+ value: "table",
2212
+ children: t("catalog.scan.table")
2213
+ })
2214
+ ]
2215
+ }),
2216
+ scopeInputs && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2217
+ className: DataAgentWorkbench_module_css_default.input,
2218
+ value: scanSchema,
2219
+ onChange: (event) => setScanSchema(event.target.value),
2220
+ placeholder: t("catalog.schema"),
2221
+ "aria-label": t("catalog.schema")
2222
+ }),
2223
+ scanKind === "table" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2224
+ className: DataAgentWorkbench_module_css_default.input,
2225
+ value: scanTable,
2226
+ onChange: (event) => setScanTable(event.target.value),
2227
+ placeholder: t("catalog.table"),
2228
+ "aria-label": t("catalog.table")
2229
+ }),
2230
+ activeRun === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2231
+ type: "button",
2232
+ className: DataAgentWorkbench_module_css_default.primary,
2233
+ disabled: busy || !scanAllowed,
2234
+ onClick: () => {
2235
+ beginScan();
2236
+ },
2237
+ children: t("catalog.scan")
2238
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2239
+ type: "button",
2240
+ className: DataAgentWorkbench_module_css_default.ghost,
2241
+ disabled: busy,
2242
+ onClick: () => {
2243
+ cancelScan();
2244
+ },
2245
+ children: t("catalog.cancel")
2246
+ })
2247
+ ]
2248
+ }), !scanAllowed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2249
+ className: DataAgentWorkbench_module_css_default.catalogInlineNotice,
2250
+ children: t("catalog.scan.reconnect")
2251
+ })] })]
2252
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2253
+ className: DataAgentWorkbench_module_css_default.catalogActionGroup,
2254
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2255
+ className: DataAgentWorkbench_module_css_default.catalogSectionLabel,
2256
+ children: t("catalog.section.diff")
2257
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2258
+ className: DataAgentWorkbench_module_css_default.catalogDiffBar,
2259
+ children: [
2260
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2261
+ className: DataAgentWorkbench_module_css_default.input,
2262
+ value: diffFrom,
2263
+ onChange: (event) => setDiffFrom(event.target.value),
2264
+ "aria-label": t("catalog.diff.from"),
2265
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2266
+ value: "",
2267
+ children: t("catalog.diff.from")
2268
+ }), successfulRuns.map((run) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2269
+ value: run.id,
2270
+ children: run.id
2271
+ }, run.id))]
2272
+ }),
2273
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2274
+ className: DataAgentWorkbench_module_css_default.input,
2275
+ value: diffTo,
2276
+ onChange: (event) => setDiffTo(event.target.value),
2277
+ "aria-label": t("catalog.diff.to"),
2278
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2279
+ value: "",
2280
+ children: t("catalog.diff.to")
2281
+ }), successfulRuns.map((run) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2282
+ value: run.id,
2283
+ children: run.id
2284
+ }, run.id))]
2285
+ }),
2286
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2287
+ type: "button",
2288
+ className: DataAgentWorkbench_module_css_default.ghost,
2289
+ disabled: busy || sourceId === "",
2290
+ onClick: () => {
2291
+ loadDiff();
2292
+ },
2293
+ children: t("catalog.diff")
2294
+ })
2295
+ ]
2296
+ })]
2297
+ })]
2298
+ })
2299
+ ]
2300
+ }),
2301
+ confirmFull && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2302
+ className: DataAgentWorkbench_module_css_default.catalogConfirm,
2303
+ role: "alert",
2304
+ children: [
2305
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("catalog.scan.confirm") }),
2306
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2307
+ type: "button",
2308
+ className: DataAgentWorkbench_module_css_default.primary,
2309
+ onClick: () => {
2310
+ beginScan();
2311
+ },
2312
+ children: t("catalog.scan.all")
2313
+ }),
2314
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2315
+ type: "button",
2316
+ className: DataAgentWorkbench_module_css_default.ghost,
2317
+ onClick: () => setConfirmFull(false),
2318
+ children: t("action.close")
2319
+ })
2320
+ ]
2321
+ }),
2322
+ activeRun !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2323
+ className: DataAgentWorkbench_module_css_default.catalogProgress,
2324
+ role: "status",
2325
+ children: [
2326
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: activeRun.enrichment?.status === "running" ? t("catalog.enrichment.running") : statusLabel(activeRun.status) }),
2327
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: activeRun.enrichment?.status === "running" ? t("catalog.enrichment.progress", {
2328
+ completed: activeRun.enrichment.tablesCompleted,
2329
+ total: activeRun.enrichment.tablesTotal,
2330
+ candidates: activeRun.enrichment.candidatesGenerated
2331
+ }) : t("catalog.progress", {
2332
+ schemas: activeRun.progress.schemas,
2333
+ relations: activeRun.progress.relations,
2334
+ fields: activeRun.progress.fields
2335
+ }) }),
2336
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: activeRun.id })
2337
+ ]
2338
+ }),
2339
+ error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2340
+ className: DataAgentWorkbench_module_css_default.catalogError,
2341
+ role: "alert",
2342
+ children: error
2343
+ }),
2344
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2345
+ className: DataAgentWorkbench_module_css_default.catalogNotice,
2346
+ children: t("catalog.warning.untrusted")
2347
+ }),
2348
+ sources.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2349
+ className: DataAgentWorkbench_module_css_default.emptyState,
2350
+ children: t("catalog.empty")
2351
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2352
+ className: DataAgentWorkbench_module_css_default.catalogWorkspace,
2353
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2354
+ className: DataAgentWorkbench_module_css_default.catalogResults,
2355
+ children: [
2356
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
2357
+ className: DataAgentWorkbench_module_css_default.catalogSearch,
2358
+ onSubmit: (event) => {
2359
+ event.preventDefault();
2360
+ setBusy(true);
2361
+ runSearch().catch(reportError).finally(() => setBusy(false));
2362
+ },
2363
+ children: [
2364
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2365
+ className: `${DataAgentWorkbench_module_css_default.input} ${DataAgentWorkbench_module_css_default.catalogSearchQuery}`,
2366
+ value: query,
2367
+ onChange: (event) => setQuery(event.target.value),
2368
+ placeholder: t("catalog.search"),
2369
+ "aria-label": t("catalog.search")
2370
+ }),
2371
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2372
+ className: DataAgentWorkbench_module_css_default.input,
2373
+ value: schema,
2374
+ onChange: (event) => setSchema(event.target.value),
2375
+ placeholder: t("catalog.schema"),
2376
+ "aria-label": t("catalog.schema.filter")
2377
+ }),
2378
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2379
+ className: DataAgentWorkbench_module_css_default.input,
2380
+ value: kind,
2381
+ onChange: (event) => setKind(event.target.value),
2382
+ "aria-label": t("catalog.filter.all"),
2383
+ children: [
2384
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2385
+ value: "relation",
2386
+ children: t("catalog.filter.tables")
2387
+ }),
2388
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2389
+ value: "",
2390
+ children: t("catalog.filter.all")
2391
+ }),
2392
+ [
2393
+ "schema",
2394
+ "table",
2395
+ "view",
2396
+ "column",
2397
+ "primary_key",
2398
+ "foreign_key",
2399
+ "index",
2400
+ "meaning",
2401
+ "term",
2402
+ "metric"
2403
+ ].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2404
+ value,
2405
+ children: kindLabel(value)
2406
+ }, value))
2407
+ ]
2408
+ }),
2409
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2410
+ className: DataAgentWorkbench_module_css_default.input,
2411
+ value: assetStatus,
2412
+ onChange: (event) => setAssetStatus(event.target.value),
2413
+ "aria-label": t("catalog.filter.assetStatus"),
2414
+ children: [
2415
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2416
+ value: "",
2417
+ children: t("catalog.filter.assetStatus")
2418
+ }),
2419
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2420
+ value: "observed",
2421
+ children: t("catalog.state.observed")
2422
+ }),
2423
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2424
+ value: "missing",
2425
+ children: t("catalog.state.missing")
2426
+ }),
2427
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2428
+ value: "unavailable",
2429
+ children: t("catalog.state.unavailable")
2430
+ })
2431
+ ]
2432
+ }),
2433
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2434
+ className: DataAgentWorkbench_module_css_default.input,
2435
+ value: semanticStatus,
2436
+ onChange: (event) => setSemanticStatus(event.target.value),
2437
+ "aria-label": t("catalog.filter.semanticStatus"),
2438
+ children: [
2439
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2440
+ value: "",
2441
+ children: t("catalog.filter.semanticStatus")
2442
+ }),
2443
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2444
+ value: "inferred",
2445
+ children: t("catalog.state.inferred")
2446
+ }),
2447
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2448
+ value: "verified",
2449
+ children: t("catalog.state.verified")
2450
+ }),
2451
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2452
+ value: "needs_review",
2453
+ children: t("catalog.state.needs_review")
2454
+ }),
2455
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2456
+ value: "retired",
2457
+ children: t("catalog.state.retired")
2458
+ })
2459
+ ]
2460
+ }),
2461
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2462
+ className: DataAgentWorkbench_module_css_default.catalogSearchActions,
2463
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
2464
+ className: DataAgentWorkbench_module_css_default.catalogCheck,
2465
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2466
+ type: "checkbox",
2467
+ checked: includeInferred,
2468
+ onChange: (event) => setIncludeInferred(event.target.checked)
2469
+ }), t("catalog.filter.review")]
2470
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2471
+ type: "submit",
2472
+ className: DataAgentWorkbench_module_css_default.ghost,
2473
+ disabled: busy,
2474
+ children: t("catalog.refresh")
2475
+ })]
2476
+ })
2477
+ ]
2478
+ }),
2479
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2480
+ className: DataAgentWorkbench_module_css_default.catalogList,
2481
+ role: "listbox",
2482
+ "aria-label": t("action.catalog"),
2483
+ children: [items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2484
+ type: "button",
2485
+ role: "option",
2486
+ "aria-selected": selection?.item.id === item.id,
2487
+ className: `${DataAgentWorkbench_module_css_default.catalogItem}${selection?.item.id === item.id ? ` ${DataAgentWorkbench_module_css_default.catalogItemActive}` : ""}`,
2488
+ onClick: () => {
2489
+ selectItem(item);
2490
+ },
2491
+ children: [
2492
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2493
+ className: DataAgentWorkbench_module_css_default.catalogItemHead,
2494
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: item.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusBadge, {
2495
+ value: statusLabel(item.status),
2496
+ state: item.status
2497
+ })]
2498
+ }),
2499
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
2500
+ title: item.path,
2501
+ children: parentPath(item.path, item.name)
2502
+ }),
2503
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [kindLabel(item.kind), item.summary.trim() === "" ? "" : ` · ${item.summary}`] })
2504
+ ]
2505
+ }, `${item.resultType}:${item.id}`)), items.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2506
+ className: DataAgentWorkbench_module_css_default.catalogListEmpty,
2507
+ children: busy ? t("wb.loading") : t("wb.empty")
2508
+ })]
2509
+ }),
2510
+ nextCursor !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2511
+ type: "button",
2512
+ className: DataAgentWorkbench_module_css_default.ghost,
2513
+ disabled: busy,
2514
+ onClick: () => {
2515
+ setBusy(true);
2516
+ runSearch(nextCursor, true).catch(reportError).finally(() => setBusy(false));
2517
+ },
2518
+ children: t("catalog.loadMore")
2519
+ })
2520
+ ]
2521
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2522
+ className: DataAgentWorkbench_module_css_default.catalogDetail,
2523
+ children: selection === null && diff === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2524
+ className: DataAgentWorkbench_module_css_default.emptyState,
2525
+ children: t("catalog.detail.select")
2526
+ }) : diff !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DiffView, {
2527
+ diff,
2528
+ statusLabel,
2529
+ onClose: () => setDiff(null),
2530
+ onLoadMore: () => {
2531
+ if (diff.nextCursor !== void 0) loadDiff(diff.nextCursor, true);
2532
+ },
2533
+ busy,
2534
+ t
2535
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
2536
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2537
+ className: DataAgentWorkbench_module_css_default.catalogDetailHeader,
2538
+ children: [
2539
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2540
+ className: DataAgentWorkbench_module_css_default.catalogDetailTitle,
2541
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: selection?.item.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
2542
+ title: selection?.item.path,
2543
+ children: selection?.item.path
2544
+ })] }), selection !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusBadge, {
2545
+ value: statusLabel(selection.item.status),
2546
+ state: selection.item.status
2547
+ })]
2548
+ }),
2549
+ assetDetail !== null && relationDetail && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2550
+ className: DataAgentWorkbench_module_css_default.catalogDetailCounts,
2551
+ "aria-label": t("catalog.detail.summary"),
2552
+ children: [
2553
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: fieldCount }), t("catalog.detail.fields")] }),
2554
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: assetDetail.relations.length }), t("catalog.detail.relationCount")] }),
2555
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: businessDefinitions.length }), t("catalog.detail.definitionCount")] })
2556
+ ]
2557
+ }),
2558
+ assetDetail?.asset.payload.comment && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: assetDetail.asset.payload.comment })
2559
+ ]
2560
+ }),
2561
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2562
+ className: DataAgentWorkbench_module_css_default.catalogDetailTabs,
2563
+ role: "tablist",
2564
+ children: [
2565
+ "technical",
2566
+ "business",
2567
+ "history"
2568
+ ].map((tab) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2569
+ type: "button",
2570
+ role: "tab",
2571
+ "aria-selected": detailTab === tab,
2572
+ className: detailTab === tab ? DataAgentWorkbench_module_css_default.catalogDetailTabActive : DataAgentWorkbench_module_css_default.catalogDetailTab,
2573
+ onClick: () => setDetailTab(tab),
2574
+ children: t(`catalog.detail.${tab}`)
2575
+ }, tab))
2576
+ }),
2577
+ detailTab === "technical" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2578
+ className: DataAgentWorkbench_module_css_default.catalogDetailScroll,
2579
+ children: assetDetail === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2580
+ className: DataAgentWorkbench_module_css_default.hint,
2581
+ children: t("wb.empty")
2582
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
2583
+ fieldDetail && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
2584
+ className: DataAgentWorkbench_module_css_default.catalogFacts,
2585
+ children: [
2586
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("catalog.detail.type") }),
2587
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: assetDetail.asset.payload.dataType ?? "—" }),
2588
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("catalog.detail.nullable") }),
2589
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: nullableLabel(assetDetail.asset.payload.nullable, t) }),
2590
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("catalog.detail.parentTable") }),
2591
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: assetDetail.asset.payload.identity.relation ?? "—" })
2592
+ ]
2593
+ }),
2594
+ relationDetail && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
2595
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", { children: t("catalog.detail.fields") }),
2596
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
2597
+ className: DataAgentWorkbench_module_css_default.columnsTable,
2598
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
2599
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("catalog.detail.name") }),
2600
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("catalog.detail.type") }),
2601
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", { children: t("catalog.detail.nullable") })
2602
+ ] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: technicalRows.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
2603
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: field.payload.name }),
2604
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: field.payload.dataType }),
2605
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: nullableLabel(field.payload.nullable, t) })
2606
+ ] }, field.assetId)) })]
2607
+ }),
2608
+ assetDetail.nextCursor !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2609
+ type: "button",
2610
+ className: DataAgentWorkbench_module_css_default.ghost,
2611
+ disabled: busy,
2612
+ onClick: () => {
2613
+ loadMoreFields();
2614
+ },
2615
+ children: t("catalog.loadMore")
2616
+ })
2617
+ ] }),
2618
+ assetDetail.relations.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2619
+ className: DataAgentWorkbench_module_css_default.catalogRelations,
2620
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", { children: t("catalog.detail.relations") }), assetDetail.relations.map((relation) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2621
+ className: DataAgentWorkbench_module_css_default.catalogHistoryItem,
2622
+ children: [
2623
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: kindLabel(relation.kind) }),
2624
+ " ",
2625
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: relation.name }),
2626
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("code", { children: [relation.fromAssetId, relation.toAssetId ? ` → ${relation.toAssetId}` : ""] })
2627
+ ]
2628
+ }, relation.id))]
2629
+ }),
2630
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
2631
+ className: DataAgentWorkbench_module_css_default.catalogScanFacts,
2632
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("catalog.detail.scanFacts") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
2633
+ className: DataAgentWorkbench_module_css_default.catalogFacts,
2634
+ children: [
2635
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("catalog.detail.provenance") }),
2636
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dd", { children: [
2637
+ assetDetail.asset.payload.provenance.source,
2638
+ " · ",
2639
+ assetDetail.asset.payload.provenance.dialect
2640
+ ] }),
2641
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("catalog.detail.run") }),
2642
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: assetDetail.asset.runId }) }),
2643
+ Object.entries(assetDetail.asset.payload.capabilities ?? {}).map(([capability, value]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: capability }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: statusLabel(value) })] }, capability))
2644
+ ]
2645
+ })]
2646
+ })
2647
+ ] })
2648
+ }),
2649
+ detailTab === "business" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2650
+ className: DataAgentWorkbench_module_css_default.catalogDetailScroll,
2651
+ children: [
2652
+ selection?.type === "asset" && assetDetail !== null && businessDefinitions.length === 0 && !editingMetric && !editingTerm && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2653
+ className: DataAgentWorkbench_module_css_default.catalogBusinessEmpty,
2654
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("catalog.detail.business.empty.title") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("catalog.detail.business.empty.body") })]
2655
+ }),
2656
+ relationDetail && assetDetail !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2657
+ className: DataAgentWorkbench_module_css_default.catalogMeaningReview,
2658
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2659
+ className: DataAgentWorkbench_module_css_default.catalogMeaningSection,
2660
+ "aria-labelledby": `${props.id}-table-meaning`,
2661
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
2662
+ id: `${props.id}-table-meaning`,
2663
+ children: t("catalog.meaning.table")
2664
+ }), tableMeaning === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2665
+ className: DataAgentWorkbench_module_css_default.catalogMeaningMissing,
2666
+ children: t("catalog.meaning.missing")
2667
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MeaningCard, {
2668
+ value: tableMeaning,
2669
+ busy,
2670
+ statusLabel,
2671
+ onConfirm: () => {
2672
+ confirmMeaning(tableMeaning);
2673
+ },
2674
+ onDismiss: () => {
2675
+ dismissMeaning(tableMeaning);
2676
+ },
2677
+ t
2678
+ })]
2679
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2680
+ className: DataAgentWorkbench_module_css_default.catalogMeaningSection,
2681
+ "aria-labelledby": `${props.id}-field-meanings`,
2682
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
2683
+ id: `${props.id}-field-meanings`,
2684
+ children: t("catalog.meaning.fields")
2685
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2686
+ className: DataAgentWorkbench_module_css_default.catalogMeaningFields,
2687
+ children: technicalRows.map((field) => {
2688
+ const meaning = fieldMeanings.get(field.assetId);
2689
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2690
+ className: DataAgentWorkbench_module_css_default.catalogMeaningField,
2691
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2692
+ className: DataAgentWorkbench_module_css_default.catalogMeaningFieldMeta,
2693
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: field.payload.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: field.payload.dataType ?? "—" })]
2694
+ }), meaning === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2695
+ className: DataAgentWorkbench_module_css_default.catalogMeaningMissing,
2696
+ children: t("catalog.meaning.missing")
2697
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MeaningCard, {
2698
+ value: meaning,
2699
+ compact: true,
2700
+ busy,
2701
+ statusLabel,
2702
+ onConfirm: () => {
2703
+ confirmMeaning(meaning);
2704
+ },
2705
+ onDismiss: () => {
2706
+ dismissMeaning(meaning);
2707
+ },
2708
+ t
2709
+ })]
2710
+ }, field.assetId);
2711
+ })
2712
+ })]
2713
+ })]
2714
+ }),
2715
+ selection?.type === "semantic" && semanticDetail?.definition.kind === "meaning" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MeaningCard, {
2716
+ value: semanticDetail,
2717
+ busy,
2718
+ statusLabel,
2719
+ onConfirm: () => {
2720
+ confirmMeaning(semanticDetail);
2721
+ },
2722
+ onDismiss: () => {
2723
+ dismissMeaning(semanticDetail);
2724
+ },
2725
+ t
2726
+ }),
2727
+ governedDefinitions.map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2728
+ className: DataAgentWorkbench_module_css_default.catalogDefinition,
2729
+ children: [
2730
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2731
+ className: DataAgentWorkbench_module_css_default.catalogItemHead,
2732
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: value.definition.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusBadge, {
2733
+ value: statusLabel(value.definition.status),
2734
+ state: value.definition.status
2735
+ })]
2736
+ }),
2737
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: value.definition.description }),
2738
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("code", { children: ["v", value.version] }),
2739
+ value.definition.kind === "metric" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: value.definition.formula }),
2740
+ value.definition.kind === "metric" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2741
+ type: "button",
2742
+ className: DataAgentWorkbench_module_css_default.ghost,
2743
+ onClick: () => {
2744
+ setSemanticDetail(value);
2745
+ startMetric(value);
2746
+ },
2747
+ children: t("catalog.metric.verify")
2748
+ }),
2749
+ value.definition.kind === "term" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2750
+ type: "button",
2751
+ className: DataAgentWorkbench_module_css_default.ghost,
2752
+ onClick: () => {
2753
+ setSemanticDetail(value);
2754
+ startTerm(value);
2755
+ },
2756
+ children: t("catalog.metric.verify")
2757
+ })
2758
+ ]
2759
+ }, value.id)),
2760
+ selection?.type === "asset" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2761
+ className: DataAgentWorkbench_module_css_default.actions,
2762
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2763
+ type: "button",
2764
+ className: DataAgentWorkbench_module_css_default.ghost,
2765
+ onClick: () => startTerm(),
2766
+ children: t("catalog.term.new")
2767
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2768
+ type: "button",
2769
+ className: DataAgentWorkbench_module_css_default.ghost,
2770
+ onClick: () => startMetric(),
2771
+ children: t("catalog.metric.new")
2772
+ })]
2773
+ }),
2774
+ editingMetric && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MetricEditor, {
2775
+ draft: metricDraft,
2776
+ setDraft: setMetricDraft,
2777
+ busy,
2778
+ canSave: canSaveMetric,
2779
+ canVerify: canVerifyMetric,
2780
+ canRetire: semanticDetail?.definition.status === "verified" || semanticDetail?.definition.status === "needs_review",
2781
+ onSave: () => {
2782
+ saveMetric(false);
2783
+ },
2784
+ onVerify: () => {
2785
+ saveMetric(true);
2786
+ },
2787
+ onRetire: () => {
2788
+ retireSemantic(metricDraft.revisionNote);
2789
+ },
2790
+ t
2791
+ }),
2792
+ editingTerm && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TermEditor, {
2793
+ draft: termDraft,
2794
+ setDraft: setTermDraft,
2795
+ busy,
2796
+ canSave: canSaveTerm,
2797
+ canVerify: canVerifyTerm,
2798
+ canRetire: semanticDetail?.definition.status === "verified" || semanticDetail?.definition.status === "needs_review",
2799
+ onSave: () => {
2800
+ saveTerm(false);
2801
+ },
2802
+ onVerify: () => {
2803
+ saveTerm(true);
2804
+ },
2805
+ onRetire: () => {
2806
+ retireSemantic(termDraft.revisionNote);
2807
+ },
2808
+ t
2809
+ })
2810
+ ]
2811
+ }),
2812
+ detailTab === "history" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2813
+ className: DataAgentWorkbench_module_css_default.catalogDetailScroll,
2814
+ children: [(assetDetail?.history ?? []).map((revision) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2815
+ className: DataAgentWorkbench_module_css_default.catalogHistoryItem,
2816
+ children: [
2817
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
2818
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: ["r", revision.revision] }),
2819
+ " · ",
2820
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusBadge, {
2821
+ value: statusLabel(revision.status),
2822
+ state: revision.status
2823
+ })
2824
+ ] }),
2825
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: revision.runId }),
2826
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: revision.observedAt }),
2827
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: revision.changeSummary.join(", ") })
2828
+ ]
2829
+ }, revision.id)), assetDetail === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2830
+ className: DataAgentWorkbench_module_css_default.hint,
2831
+ children: t("wb.empty")
2832
+ })]
2833
+ })
2834
+ ] })
2835
+ })]
2836
+ })
2837
+ ]
2838
+ });
2839
+ }
2840
+ function StatusBadge({ value, state }) {
2841
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2842
+ className: `${DataAgentWorkbench_module_css_default.catalogBadge} ${DataAgentWorkbench_module_css_default[`catalogBadge_${state}`] ?? ""}`,
2843
+ children: value
2844
+ });
2845
+ }
2846
+ function MeaningCard({ value, compact = false, busy, statusLabel, onConfirm, onDismiss, t }) {
2847
+ if (value.definition.kind !== "meaning") return null;
2848
+ const confirmable = value.definition.status === "inferred" || value.definition.status === "needs_review";
2849
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2850
+ className: `${DataAgentWorkbench_module_css_default.catalogMeaningCard}${compact ? ` ${DataAgentWorkbench_module_css_default.catalogMeaningCardCompact}` : ""}`,
2851
+ children: [
2852
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2853
+ className: DataAgentWorkbench_module_css_default.catalogItemHead,
2854
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusBadge, {
2855
+ value: statusLabel(value.definition.status),
2856
+ state: value.definition.status
2857
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2858
+ className: DataAgentWorkbench_module_css_default.catalogMeaningOrigin,
2859
+ children: [
2860
+ t("catalog.meaning.ai"),
2861
+ " · ",
2862
+ value.definition.generatedBy.provider,
2863
+ "/",
2864
+ value.definition.generatedBy.model
2865
+ ]
2866
+ })]
2867
+ }),
2868
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: value.definition.description }),
2869
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2870
+ className: DataAgentWorkbench_module_css_default.catalogMeaningActions,
2871
+ children: [
2872
+ confirmable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2873
+ type: "button",
2874
+ className: DataAgentWorkbench_module_css_default.primary,
2875
+ disabled: busy,
2876
+ onClick: onConfirm,
2877
+ children: t("catalog.meaning.confirm")
2878
+ }),
2879
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2880
+ type: "button",
2881
+ className: DataAgentWorkbench_module_css_default.ghost,
2882
+ disabled: busy,
2883
+ onClick: onDismiss,
2884
+ children: t("catalog.meaning.delete")
2885
+ }),
2886
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("code", {
2887
+ title: value.definition.generatedBy.runId,
2888
+ children: [
2889
+ "v",
2890
+ value.version,
2891
+ " · ",
2892
+ value.definition.generatedBy.runId
2893
+ ]
2894
+ })
2895
+ ]
2896
+ })
2897
+ ]
2898
+ });
2899
+ }
2900
+ function DiffView({ diff, statusLabel, onClose, onLoadMore, busy, t }) {
2901
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2902
+ className: DataAgentWorkbench_module_css_default.catalogDetailScroll,
2903
+ children: [
2904
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2905
+ className: DataAgentWorkbench_module_css_default.catalogItemHead,
2906
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [
2907
+ diff.fromRunId,
2908
+ " → ",
2909
+ diff.toRunId
2910
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2911
+ type: "button",
2912
+ className: DataAgentWorkbench_module_css_default.ghost,
2913
+ onClick: onClose,
2914
+ children: t("action.close")
2915
+ })]
2916
+ }),
2917
+ diff.items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2918
+ className: DataAgentWorkbench_module_css_default.catalogHistoryItem,
2919
+ children: [
2920
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
2921
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusBadge, {
2922
+ value: statusLabel(item.kind),
2923
+ state: item.kind
2924
+ }),
2925
+ " ",
2926
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: item.name })
2927
+ ] }),
2928
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: item.path }),
2929
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: item.summary.join(", ") })
2930
+ ]
2931
+ }, `${item.kind}:${item.assetId}`)),
2932
+ diff.nextCursor !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2933
+ type: "button",
2934
+ className: DataAgentWorkbench_module_css_default.ghost,
2935
+ disabled: busy,
2936
+ onClick: onLoadMore,
2937
+ children: t("catalog.loadMore")
2938
+ })
2939
+ ]
2940
+ });
2941
+ }
2942
+ function MetricEditor(props) {
2943
+ const field = (key, label, area = false) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
2944
+ className: DataAgentWorkbench_module_css_default.field,
2945
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2946
+ className: DataAgentWorkbench_module_css_default.label,
2947
+ children: props.t(label)
2948
+ }), area ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
2949
+ className: DataAgentWorkbench_module_css_default.catalogTextArea,
2950
+ value: props.draft[key],
2951
+ onChange: (event) => props.setDraft({
2952
+ ...props.draft,
2953
+ [key]: event.target.value
2954
+ })
2955
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2956
+ className: DataAgentWorkbench_module_css_default.input,
2957
+ value: props.draft[key],
2958
+ onChange: (event) => props.setDraft({
2959
+ ...props.draft,
2960
+ [key]: event.target.value
2961
+ })
2962
+ })]
2963
+ });
2964
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2965
+ className: DataAgentWorkbench_module_css_default.catalogEditor,
2966
+ children: [
2967
+ field("name", "catalog.metric.name"),
2968
+ field("aliases", "catalog.semantic.aliases"),
2969
+ field("description", "catalog.metric.description", true),
2970
+ field("sourceAssetIds", "catalog.semantic.sources", true),
2971
+ field("formula", "catalog.metric.formula", true),
2972
+ field("grain", "catalog.metric.grain"),
2973
+ field("timeFieldAssetId", "catalog.metric.timeField"),
2974
+ field("filters", "catalog.metric.filters", true),
2975
+ field("exclusions", "catalog.metric.exclusions", true),
2976
+ field("validFrom", "catalog.semantic.validFrom"),
2977
+ field("validTo", "catalog.semantic.validTo"),
2978
+ field("owner", "catalog.metric.owner"),
2979
+ field("revisionNote", "catalog.metric.note", true),
2980
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2981
+ className: DataAgentWorkbench_module_css_default.actions,
2982
+ children: [
2983
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2984
+ type: "button",
2985
+ className: DataAgentWorkbench_module_css_default.ghost,
2986
+ disabled: props.busy || !props.canSave,
2987
+ onClick: props.onSave,
2988
+ children: props.t("catalog.metric.save")
2989
+ }),
2990
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2991
+ type: "button",
2992
+ className: DataAgentWorkbench_module_css_default.primary,
2993
+ disabled: props.busy || !props.canVerify,
2994
+ onClick: props.onVerify,
2995
+ children: props.t("catalog.metric.verify")
2996
+ }),
2997
+ props.canRetire && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2998
+ type: "button",
2999
+ className: DataAgentWorkbench_module_css_default.ghost,
3000
+ disabled: props.busy || props.draft.revisionNote.trim() === "",
3001
+ onClick: props.onRetire,
3002
+ children: props.t("catalog.metric.retire")
3003
+ })
3004
+ ]
3005
+ })
3006
+ ]
3007
+ });
3008
+ }
3009
+ function TermEditor(props) {
3010
+ const field = (key, label, area = false) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3011
+ className: DataAgentWorkbench_module_css_default.field,
3012
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3013
+ className: DataAgentWorkbench_module_css_default.label,
3014
+ children: props.t(label)
3015
+ }), area ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
3016
+ className: DataAgentWorkbench_module_css_default.catalogTextArea,
3017
+ value: props.draft[key],
3018
+ onChange: (event) => props.setDraft({
3019
+ ...props.draft,
3020
+ [key]: event.target.value
3021
+ })
3022
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3023
+ className: DataAgentWorkbench_module_css_default.input,
3024
+ value: props.draft[key],
3025
+ onChange: (event) => props.setDraft({
3026
+ ...props.draft,
3027
+ [key]: event.target.value
3028
+ })
3029
+ })]
3030
+ });
3031
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3032
+ className: DataAgentWorkbench_module_css_default.catalogEditor,
3033
+ children: [
3034
+ field("name", "catalog.term.name"),
3035
+ field("aliases", "catalog.semantic.aliases"),
3036
+ field("description", "catalog.metric.description", true),
3037
+ field("sourceAssetIds", "catalog.semantic.sources", true),
3038
+ field("validFrom", "catalog.semantic.validFrom"),
3039
+ field("validTo", "catalog.semantic.validTo"),
3040
+ field("owner", "catalog.metric.owner"),
3041
+ field("revisionNote", "catalog.metric.note", true),
3042
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3043
+ className: DataAgentWorkbench_module_css_default.actions,
3044
+ children: [
3045
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3046
+ type: "button",
3047
+ className: DataAgentWorkbench_module_css_default.ghost,
3048
+ disabled: props.busy || !props.canSave,
3049
+ onClick: props.onSave,
3050
+ children: props.t("catalog.metric.save")
3051
+ }),
3052
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3053
+ type: "button",
3054
+ className: DataAgentWorkbench_module_css_default.primary,
3055
+ disabled: props.busy || !props.canVerify,
3056
+ onClick: props.onVerify,
3057
+ children: props.t("catalog.metric.verify")
3058
+ }),
3059
+ props.canRetire && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3060
+ type: "button",
3061
+ className: DataAgentWorkbench_module_css_default.ghost,
3062
+ disabled: props.busy || props.draft.revisionNote.trim() === "",
3063
+ onClick: props.onRetire,
3064
+ children: props.t("catalog.metric.retire")
3065
+ })
3066
+ ]
3067
+ })
3068
+ ]
3069
+ });
3070
+ }
3071
+ function draftFromSemantic(semantic) {
3072
+ if (semantic.definition.kind !== "metric") return EMPTY_DRAFT;
3073
+ return {
3074
+ name: semantic.definition.name,
3075
+ aliases: semantic.definition.aliases.join(", "),
3076
+ description: semantic.definition.description,
3077
+ formula: semantic.definition.formula,
3078
+ grain: semantic.definition.grain,
3079
+ sourceAssetIds: semantic.definition.sourceAssetIds.join("\n"),
3080
+ timeFieldAssetId: semantic.definition.timeFieldAssetId ?? "",
3081
+ filters: semantic.definition.filters.join("\n"),
3082
+ exclusions: semantic.definition.exclusions.join("\n"),
3083
+ validFrom: semantic.definition.validFrom ?? "",
3084
+ validTo: semantic.definition.validTo ?? "",
3085
+ owner: semantic.definition.owner ?? "",
3086
+ revisionNote: ""
3087
+ };
3088
+ }
3089
+ function termDraftFromSemantic(semantic) {
3090
+ if (semantic.definition.kind !== "term") return EMPTY_TERM_DRAFT;
3091
+ return {
3092
+ name: semantic.definition.name,
3093
+ aliases: semantic.definition.aliases.join(", "),
3094
+ description: semantic.definition.description,
3095
+ sourceAssetIds: semantic.definition.sourceAssetIds.join("\n"),
3096
+ validFrom: semantic.definition.validFrom ?? "",
3097
+ validTo: semantic.definition.validTo ?? "",
3098
+ owner: semantic.definition.owner ?? "",
3099
+ revisionNote: ""
3100
+ };
3101
+ }
3102
+ function splitList(value) {
3103
+ return value.split(/[\n,]+/).map((item) => item.trim()).filter(Boolean);
3104
+ }
3105
+ function splitLines(value) {
3106
+ return value.split(/\n+/).map((item) => item.trim()).filter(Boolean);
3107
+ }
3108
+ function defaultBrowseSchema(source) {
3109
+ return [
3110
+ "mysql",
3111
+ "clickhouse",
3112
+ "doris",
3113
+ "hive",
3114
+ "impala"
3115
+ ].includes(source.type) ? source.database : "";
3116
+ }
3117
+ function parentPath(path, name) {
3118
+ const suffix = `.${name}`;
3119
+ return path.endsWith(suffix) ? path.slice(0, -suffix.length) : path;
3120
+ }
3121
+ function nullableLabel(value, t) {
3122
+ if (value === void 0) return "—";
3123
+ return value ? t("catalog.detail.yes") : t("catalog.detail.no");
3124
+ }
3125
+ const STATUS_KEYS = {
3126
+ "catalog.state.observed": true,
3127
+ "catalog.state.inferred": true,
3128
+ "catalog.state.verified": true,
3129
+ "catalog.state.needs_review": true,
3130
+ "catalog.state.retired": true,
3131
+ "catalog.state.missing": true,
3132
+ "catalog.state.unavailable": true,
3133
+ "catalog.state.added": true,
3134
+ "catalog.state.changed": true,
3135
+ "catalog.state.restored": true,
3136
+ "catalog.state.queued": true,
3137
+ "catalog.state.running": true,
3138
+ "catalog.state.applying": true,
3139
+ "catalog.state.succeeded": true,
3140
+ "catalog.state.failed": true,
3141
+ "catalog.state.cancelled": true,
3142
+ "catalog.state.interrupted": true,
3143
+ "catalog.state.supported": true,
3144
+ "catalog.state.unsupported": true
3145
+ };
3146
+ const KIND_KEYS = {
3147
+ "catalog.kind.schema": true,
3148
+ "catalog.kind.table": true,
3149
+ "catalog.kind.view": true,
3150
+ "catalog.kind.column": true,
3151
+ "catalog.kind.primary_key": true,
3152
+ "catalog.kind.foreign_key": true,
3153
+ "catalog.kind.index": true,
3154
+ "catalog.kind.meaning": true,
3155
+ "catalog.kind.term": true,
3156
+ "catalog.kind.metric": true
164
3157
  };
165
3158
  //#endregion
166
3159
  //#region src/client/DataAgentWorkbench.tsx
@@ -170,7 +3163,7 @@ window.__ModuleLoader__.load({
170
3163
  * Only a compact database button remains mounted from the composer slot and
171
3164
  * is visually lifted into the context row above the composer card.
172
3165
  * Clicking it opens one Modal containing connection settings, the schema
173
- * explorer, and SQL runner as three tabs. Hero and active conversations share
3166
+ * explorer, data Catalog, and SQL runner as four tabs. Hero and active conversations share
174
3167
  * this exact surface; the plugin never measures or shifts host layout.
175
3168
  *
176
3169
  * Non-data-agent sessions render null before any effect or request runs.
@@ -342,15 +3335,8 @@ window.__ModuleLoader__.load({
342
3335
  });
343
3336
  }
344
3337
  /** Default port per type (used to fill the form from a saved connection). */
345
- function defaultPortOf(type) {
346
- switch (type) {
347
- case "postgres": return "5432";
348
- case "oracle": return "1521";
349
- case "hive": return "10000";
350
- case "impala": return "21050";
351
- case "sqlite": return "";
352
- case "mysql": return "3306";
353
- }
3338
+ function defaultPortOf(type, secure = false) {
3339
+ return type === "sqlite" ? "" : String(defaultDatabasePort(type, secure));
354
3340
  }
355
3341
  /** Parse one JSON route response without silently accepting an HTTP failure. */
356
3342
  async function parseJsonResponse(response) {
@@ -390,6 +3376,7 @@ window.__ModuleLoader__.load({
390
3376
  };
391
3377
  if (saved.port !== void 0) body.port = saved.port;
392
3378
  if (saved.readonly !== void 0) body.readonly = saved.readonly;
3379
+ if (saved.type === "clickhouse") body.secure = saved.secure === true;
393
3380
  if (saved.passwordRef !== void 0 && saved.passwordRef !== "") body.passwordRef = saved.passwordRef;
394
3381
  else if (saved.password !== void 0 && saved.password !== "") body.password = saved.password;
395
3382
  return body;
@@ -404,7 +3391,7 @@ window.__ModuleLoader__.load({
404
3391
  function savedMatchesSummary(saved, summary) {
405
3392
  if (saved.type !== summary.type || saved.database !== summary.database) return false;
406
3393
  if (saved.type === "sqlite") return true;
407
- return (saved.host ?? "") === (summary.host ?? "") && (saved.port ?? void 0) === (summary.port ?? void 0) && (saved.user ?? "") === (summary.user ?? "");
3394
+ return (saved.host ?? "") === (summary.host ?? "") && (saved.port ?? void 0) === (summary.port ?? void 0) && (saved.user ?? "") === (summary.user ?? "") && (saved.type !== "clickhouse" || saved.secure === true === (summary.secure === true));
408
3395
  }
409
3396
  /** The database workbench body. */
410
3397
  function DataAgentWorkbench({ sessionId, useSessions, t }) {
@@ -413,7 +3400,8 @@ window.__ModuleLoader__.load({
413
3400
  const [initialSaved] = (0, react.useState)(loadConnection);
414
3401
  const [type, setType] = (0, react.useState)(initialSaved?.type ?? "mysql");
415
3402
  const [host, setHost] = (0, react.useState)(initialSaved?.host ?? "127.0.0.1");
416
- const [port, setPort] = (0, react.useState)(initialSaved?.port !== void 0 ? String(initialSaved.port) : defaultPortOf(initialSaved?.type ?? "mysql"));
3403
+ const [secure, setSecure] = (0, react.useState)(initialSaved?.type === "clickhouse" && initialSaved.secure === true);
3404
+ const [port, setPort] = (0, react.useState)(initialSaved?.port !== void 0 ? String(initialSaved.port) : defaultPortOf(initialSaved?.type ?? "mysql", initialSaved?.secure === true));
417
3405
  const [user, setUser] = (0, react.useState)(initialSaved?.user ?? "");
418
3406
  const [password, setPassword] = (0, react.useState)(initialSaved?.password ?? "");
419
3407
  const [passwordRef, setPasswordRef] = (0, react.useState)(initialSaved?.passwordRef ?? "");
@@ -426,6 +3414,8 @@ window.__ModuleLoader__.load({
426
3414
  const [error, setError] = (0, react.useState)(null);
427
3415
  const [connected, setConnected] = (0, react.useState)(false);
428
3416
  const [reconnectRequired, setReconnectRequired] = (0, react.useState)(false);
3417
+ const [connectionProfileId, setConnectionProfileId] = (0, react.useState)();
3418
+ const [catalogAvailable, setCatalogAvailable] = (0, react.useState)(false);
429
3419
  const [workbenchOpen, setWorkbenchOpen] = (0, react.useState)(false);
430
3420
  const [activeTab, setActiveTab] = (0, react.useState)("connection");
431
3421
  const [restoring, setRestoring] = (0, react.useState)(false);
@@ -439,7 +3429,9 @@ window.__ModuleLoader__.load({
439
3429
  const [sql, setSql] = (0, react.useState)("");
440
3430
  const [sqlBusy, setSqlBusy] = (0, react.useState)(false);
441
3431
  const [sqlResult, setSqlResult] = (0, react.useState)(null);
3432
+ const sqlResultId = (0, react.useRef)(0);
442
3433
  const triggerSlotRef = (0, react.useRef)(null);
3434
+ const catalogStateKey = (0, react.useRef)({}).current;
443
3435
  const firstDraftRun = (0, react.useRef)(true);
444
3436
  (0, react.useEffect)(() => {
445
3437
  if (!isDataAgent) return;
@@ -452,6 +3444,7 @@ window.__ModuleLoader__.load({
452
3444
  database,
453
3445
  readonly,
454
3446
  credentialMode,
3447
+ ...type === "clickhouse" ? { secure } : {},
455
3448
  ...type !== "sqlite" ? {
456
3449
  host,
457
3450
  user
@@ -473,7 +3466,8 @@ window.__ModuleLoader__.load({
473
3466
  passwordRef,
474
3467
  credentialMode,
475
3468
  rememberPassword,
476
- readonly
3469
+ readonly,
3470
+ secure
477
3471
  ]);
478
3472
  (0, react.useEffect)(() => {
479
3473
  if (!isDataAgent) return;
@@ -487,6 +3481,7 @@ window.__ModuleLoader__.load({
487
3481
  const matchesSaved = saved !== null && summary !== void 0 && savedMatchesSummary(saved, summary);
488
3482
  if (summary !== void 0) {
489
3483
  setType(summary.type);
3484
+ setSecure(summary.type === "clickhouse" && summary.secure === true);
490
3485
  setHost(summary.host ?? "");
491
3486
  setPort(summary.port !== void 0 ? String(summary.port) : "");
492
3487
  setUser(summary.user ?? "");
@@ -495,6 +3490,7 @@ window.__ModuleLoader__.load({
495
3490
  setPasswordRef(summary.passwordRef ?? "");
496
3491
  setCredentialMode(summary.credentialMode === "reference" || summary.passwordRef !== void 0 ? "reference" : "password");
497
3492
  setCredentialStatus(summary.credential);
3493
+ setConnectionProfileId(summary.profileId);
498
3494
  if (!matchesSaved) {
499
3495
  setPassword("");
500
3496
  setRememberPassword(false);
@@ -513,6 +3509,7 @@ window.__ModuleLoader__.load({
513
3509
  setConnected(true);
514
3510
  setReconnectRequired(false);
515
3511
  setCredentialStatus(result.summary?.credential);
3512
+ setConnectionProfileId(result.summary?.profileId);
516
3513
  } else setError(`连接恢复失败:${result.error ?? "unknown error"}`);
517
3514
  } catch (cause) {
518
3515
  if (!cancelled) setError(`连接恢复失败:${cause instanceof Error ? cause.message : String(cause)}`);
@@ -564,6 +3561,7 @@ window.__ModuleLoader__.load({
564
3561
  if (port !== "") body.port = Number(port);
565
3562
  body.user = user;
566
3563
  body.database = database;
3564
+ if (type === "clickhouse") body.secure = secure;
567
3565
  if (credentialMode === "reference") {
568
3566
  if (passwordRef !== "") body.passwordRef = passwordRef;
569
3567
  } else if (password !== "") body.password = password;
@@ -574,6 +3572,7 @@ window.__ModuleLoader__.load({
574
3572
  setConnected(true);
575
3573
  setReconnectRequired(false);
576
3574
  setCredentialStatus(result.summary?.credential);
3575
+ setConnectionProfileId(result.summary?.profileId);
577
3576
  if (result.summary?.credentialMode === "none" && !sqlite) saveConnection({
578
3577
  type,
579
3578
  host,
@@ -581,6 +3580,7 @@ window.__ModuleLoader__.load({
581
3580
  user,
582
3581
  database,
583
3582
  readonly,
3583
+ ...type === "clickhouse" ? { secure } : {},
584
3584
  credentialMode: "none",
585
3585
  savedAt: (/* @__PURE__ */ new Date()).toISOString()
586
3586
  });
@@ -606,8 +3606,9 @@ window.__ModuleLoader__.load({
606
3606
  setConnected(false);
607
3607
  setReconnectRequired(false);
608
3608
  setCredentialStatus(void 0);
3609
+ setConnectionProfileId(void 0);
609
3610
  setReadonly(false);
610
- setActiveTab("connection");
3611
+ if (activeTab !== "catalog") setActiveTab("connection");
611
3612
  setSchemas([]);
612
3613
  schemasLoaded.current = false;
613
3614
  setActiveSchema(null);
@@ -672,19 +3673,31 @@ window.__ModuleLoader__.load({
672
3673
  })
673
3674
  }));
674
3675
  if (result.ok && result.result !== void 0) {
675
- const parts = [];
676
- if (result.result.stdout !== "") parts.push(result.result.stdout);
677
- if (result.result.stderr !== "") parts.push(`[stderr]\n${result.result.stderr}`);
678
- if (result.result.truncated) parts.push("… 输出超过上限,已截断");
679
- if (result.result.exitCode !== 0) parts.push(`[exit code: ${result.result.exitCode ?? "signal"}]`);
680
- setSqlResult(parts.join("\n"));
681
- } else setSqlResult(`Error: ${result.error ?? "unknown error"}`);
3676
+ sqlResultId.current += 1;
3677
+ setSqlResult(result.result);
3678
+ } else setSqlResult({
3679
+ kind: "error",
3680
+ message: result.error ?? "unknown error"
3681
+ });
682
3682
  } catch (cause) {
683
- setSqlResult(`Error: ${cause instanceof Error ? cause.message : String(cause)}`);
3683
+ setSqlResult({
3684
+ kind: "error",
3685
+ message: cause instanceof Error ? cause.message : String(cause)
3686
+ });
684
3687
  } finally {
685
3688
  setSqlBusy(false);
686
3689
  }
687
3690
  };
3691
+ const tableResult = sqlResult?.kind === "table" ? sqlResult : null;
3692
+ let messageResult = "";
3693
+ if (sqlResult?.kind === "message") {
3694
+ const parts = [];
3695
+ if (sqlResult.stdout !== "") parts.push(sqlResult.stdout);
3696
+ if (sqlResult.stderr !== "") parts.push(`[stderr]\n${sqlResult.stderr}`);
3697
+ if (sqlResult.truncated) parts.push(t("wb.sql.result.outputTruncated"));
3698
+ if (sqlResult.exitCode !== 0) parts.push(`[exit code: ${sqlResult.exitCode ?? "signal"}]`);
3699
+ messageResult = parts.join("\n") || t("wb.sql.command.done");
3700
+ } else if (sqlResult?.kind === "error") messageResult = sqlResult.message;
688
3701
  const composerPlaceholder = connected ? t("composer.placeholder.connected") : reconnectRequired ? t("composer.placeholder.reconnectRequired") : t("composer.placeholder.disconnected");
689
3702
  (0, react.useLayoutEffect)(() => {
690
3703
  if (!isDataAgent) return;
@@ -714,6 +3727,11 @@ window.__ModuleLoader__.load({
714
3727
  label: t("action.browse"),
715
3728
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TableIcon, {})
716
3729
  },
3730
+ {
3731
+ id: "catalog",
3732
+ label: t("action.catalog"),
3733
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FolderIcon, {})
3734
+ },
717
3735
  {
718
3736
  id: "sql",
719
3737
  label: t("wb.sql"),
@@ -767,7 +3785,7 @@ window.__ModuleLoader__.load({
767
3785
  (connected || reconnectRequired) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
768
3786
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
769
3787
  className: DataAgentWorkbench_module_css_default.summaryType,
770
- children: t(`type.${type}`)
3788
+ children: t(databaseTypeDescriptor(type).localeKey)
771
3789
  }),
772
3790
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
773
3791
  className: DataAgentWorkbench_module_css_default.summaryDb,
@@ -787,7 +3805,7 @@ window.__ModuleLoader__.load({
787
3805
  role: "tablist",
788
3806
  "aria-label": t("wb.workbench.tabs"),
789
3807
  children: tabs.map((tab) => {
790
- const disabled = tab.id !== "connection" && !connected;
3808
+ const disabled = tab.id === "catalog" ? !connected && !catalogAvailable : tab.id !== "connection" && !connected;
791
3809
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
792
3810
  id: `${tabsId}-${tab.id}-tab`,
793
3811
  type: "button",
@@ -817,41 +3835,22 @@ window.__ModuleLoader__.load({
817
3835
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
818
3836
  className: DataAgentWorkbench_module_css_default.label,
819
3837
  children: t("form.type")
820
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
3838
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
821
3839
  className: DataAgentWorkbench_module_css_default.input,
822
3840
  value: type,
823
3841
  disabled: formDisabled,
824
3842
  onChange: (event) => {
825
3843
  const next = event.target.value;
3844
+ const previousDefault = defaultPortOf(type, secure);
3845
+ const nextSecure = next === "clickhouse" && secure;
3846
+ if (port === "" || port === previousDefault) setPort(defaultPortOf(next, nextSecure));
826
3847
  setType(next);
827
- setPort(next === "postgres" ? "5432" : next === "mysql" ? "3306" : next === "oracle" ? "1521" : next === "hive" ? "10000" : next === "impala" ? "21050" : "");
3848
+ if (next !== "clickhouse") setSecure(false);
828
3849
  },
829
- children: [
830
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
831
- value: "mysql",
832
- children: t("type.mysql")
833
- }),
834
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
835
- value: "postgres",
836
- children: t("type.postgres")
837
- }),
838
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
839
- value: "sqlite",
840
- children: t("type.sqlite")
841
- }),
842
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
843
- value: "oracle",
844
- children: t("type.oracle")
845
- }),
846
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
847
- value: "hive",
848
- children: t("type.hive")
849
- }),
850
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
851
- value: "impala",
852
- children: t("type.impala")
853
- })
854
- ]
3850
+ children: DATABASE_TYPES.map((databaseType) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3851
+ value: databaseType,
3852
+ children: t(databaseTypeDescriptor(databaseType).localeKey)
3853
+ }, databaseType))
855
3854
  })]
856
3855
  }),
857
3856
  !sqlite && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -884,6 +3883,27 @@ window.__ModuleLoader__.load({
884
3883
  })]
885
3884
  })]
886
3885
  }),
3886
+ type === "clickhouse" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3887
+ className: DataAgentWorkbench_module_css_default.rememberRow,
3888
+ children: [
3889
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3890
+ type: "checkbox",
3891
+ checked: secure,
3892
+ disabled: formDisabled,
3893
+ onChange: (event) => {
3894
+ const next = event.target.checked;
3895
+ const previousDefault = defaultPortOf("clickhouse", secure);
3896
+ if (port === "" || port === previousDefault) setPort(defaultPortOf("clickhouse", next));
3897
+ setSecure(next);
3898
+ }
3899
+ }),
3900
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("form.secure") }),
3901
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3902
+ className: DataAgentWorkbench_module_css_default.rememberHint,
3903
+ children: t("form.secure.hint")
3904
+ })
3905
+ ]
3906
+ }),
887
3907
  !sqlite && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
888
3908
  className: DataAgentWorkbench_module_css_default.fieldRow2,
889
3909
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
@@ -1140,7 +4160,7 @@ window.__ModuleLoader__.load({
1140
4160
  value: sql,
1141
4161
  rows: 9,
1142
4162
  spellCheck: false,
1143
- placeholder: t("wb.sql.placeholder"),
4163
+ placeholder: t(type === "sqlserver" ? "wb.sql.placeholder.sqlserver" : "wb.sql.placeholder"),
1144
4164
  onChange: (event) => setSql(event.target.value),
1145
4165
  onKeyDown: (event) => {
1146
4166
  if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
@@ -1164,12 +4184,29 @@ window.__ModuleLoader__.load({
1164
4184
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PlayIcon, {}), sqlBusy ? t("wb.sql.running") : t("wb.sql.run")]
1165
4185
  })]
1166
4186
  }),
1167
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
1168
- className: DataAgentWorkbench_module_css_default.sqlResult,
1169
- children: sqlResult ?? t("wb.sql.empty")
4187
+ sqlResult === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4188
+ className: DataAgentWorkbench_module_css_default.sqlResultEmpty,
4189
+ children: t("wb.sql.empty")
4190
+ }) : tableResult !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QueryResultTable, {
4191
+ result: tableResult,
4192
+ t
4193
+ }, sqlResultId.current) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
4194
+ className: `${DataAgentWorkbench_module_css_default.sqlMessage} ${sqlResult.kind === "error" ? DataAgentWorkbench_module_css_default.sqlMessageError : ""}`,
4195
+ children: messageResult
1170
4196
  })
1171
4197
  ]
1172
4198
  }),
4199
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CatalogPanel, {
4200
+ id: `${tabsId}-catalog-panel`,
4201
+ labelledBy: `${tabsId}-catalog-tab`,
4202
+ active: activeTab === "catalog",
4203
+ sessionId,
4204
+ connected,
4205
+ connectionProfileId,
4206
+ stateKey: catalogStateKey,
4207
+ t,
4208
+ onAvailabilityChange: setCatalogAvailable
4209
+ }),
1173
4210
  error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1174
4211
  className: DataAgentWorkbench_module_css_default.errorBar,
1175
4212
  role: "alert",
@@ -22695,7 +25732,7 @@ window.__ModuleLoader__.load({
22695
25732
  //#region node_modules/zrender/lib/core/WeakMap.js
22696
25733
  var wmUniqueIndex = Math.round(Math.random() * 9);
22697
25734
  var supportDefineProperty = typeof Object.defineProperty === "function";
22698
- var WeakMap = function() {
25735
+ var WeakMap$1 = function() {
22699
25736
  function WeakMap() {
22700
25737
  this._id = "__ec_inner_" + wmUniqueIndex++;
22701
25738
  }
@@ -23516,7 +26553,7 @@ window.__ModuleLoader__.load({
23516
26553
  /**
23517
26554
  * AUTO-GENERATED FILE. DO NOT MODIFY.
23518
26555
  */
23519
- var decalMap = new WeakMap();
26556
+ var decalMap = new WeakMap$1();
23520
26557
  var decalCache = new LRU(100);
23521
26558
  var decalKeys = [
23522
26559
  "symbol",
@@ -42537,40 +45574,40 @@ window.__ModuleLoader__.load({
42537
45574
  document.head.appendChild(tag);
42538
45575
  }
42539
45576
  var AnalysisDashboard_module_css_default = {
42540
- "viewHalf": "_1tppBG_viewHalf",
42541
- "table": "_1tppBG_table",
42542
- "modalHeader": "_1tppBG_modalHeader",
42543
- "view": "_1tppBG_view",
42544
- "rowInterrupted": "_1tppBG_rowInterrupted",
42545
- "viewTitle": "_1tppBG_viewTitle",
42546
- "modalSummary": "_1tppBG_modalSummary",
42547
- "rowError": "_1tppBG_rowError",
45577
+ "visuallyHidden": "_1tppBG_visuallyHidden",
42548
45578
  "metricLabel": "_1tppBG_metricLabel",
42549
- "modalClose": "_1tppBG_modalClose",
42550
- "grid": "_1tppBG_grid",
42551
45579
  "empty": "_1tppBG_empty",
42552
- "rowSummary": "_1tppBG_rowSummary",
42553
- "row": "_1tppBG_row",
42554
- "modalShell": "_1tppBG_modalShell",
45580
+ "rowInterrupted": "_1tppBG_rowInterrupted",
45581
+ "modal": "_1tppBG_modal",
45582
+ "modalHeader": "_1tppBG_modalHeader",
42555
45583
  "metricBand": "_1tppBG_metricBand",
42556
- "rowTitle": "_1tppBG_rowTitle",
42557
- "metricValue": "_1tppBG_metricValue",
42558
- "modalTitleWrap": "_1tppBG_modalTitleWrap",
42559
45584
  "chart": "_1tppBG_chart",
42560
- "tableWrap": "_1tppBG_tableWrap",
45585
+ "modalShell": "_1tppBG_modalShell",
45586
+ "modalTitleWrap": "_1tppBG_modalTitleWrap",
45587
+ "rowSummary": "_1tppBG_rowSummary",
45588
+ "grid": "_1tppBG_grid",
45589
+ "preview": "_1tppBG_preview",
42561
45590
  "viewFull": "_1tppBG_viewFull",
42562
- "modal": "_1tppBG_modal",
42563
- "visuallyHidden": "_1tppBG_visuallyHidden",
42564
- "modalTitle": "_1tppBG_modalTitle",
42565
- "modalBody": "_1tppBG_modalBody",
42566
- "chartCanvas": "_1tppBG_chartCanvas",
42567
- "metric": "_1tppBG_metric",
42568
- "modalCount": "_1tppBG_modalCount",
45591
+ "viewTitle": "_1tppBG_viewTitle",
45592
+ "metricValue": "_1tppBG_metricValue",
45593
+ "view": "_1tppBG_view",
45594
+ "viewHalf": "_1tppBG_viewHalf",
45595
+ "rowError": "_1tppBG_rowError",
42569
45596
  "rowHead": "_1tppBG_rowHead",
45597
+ "modalBody": "_1tppBG_modalBody",
45598
+ "tableWrap": "_1tppBG_tableWrap",
42570
45599
  "rowActions": "_1tppBG_rowActions",
45600
+ "rowTitle": "_1tppBG_rowTitle",
45601
+ "table": "_1tppBG_table",
45602
+ "modalCount": "_1tppBG_modalCount",
45603
+ "row": "_1tppBG_row",
45604
+ "metric": "_1tppBG_metric",
45605
+ "modalClose": "_1tppBG_modalClose",
42571
45606
  "emptyText": "_1tppBG_emptyText",
42572
- "rowButton": "_1tppBG_rowButton",
42573
- "preview": "_1tppBG_preview"
45607
+ "modalSummary": "_1tppBG_modalSummary",
45608
+ "chartCanvas": "_1tppBG_chartCanvas",
45609
+ "modalTitle": "_1tppBG_modalTitle",
45610
+ "rowButton": "_1tppBG_rowButton"
42574
45611
  };
42575
45612
  //#endregion
42576
45613
  //#region src/client/AnalysisChart.tsx
@@ -42995,6 +46032,9 @@ window.__ModuleLoader__.load({
42995
46032
  "type.oracle": "Oracle",
42996
46033
  "type.hive": "Hive",
42997
46034
  "type.impala": "Impala",
46035
+ "type.clickhouse": "ClickHouse",
46036
+ "type.doris": "Apache Doris",
46037
+ "type.sqlserver": "SQL Server",
42998
46038
  "form.host": "主机",
42999
46039
  "form.port": "端口",
43000
46040
  "form.user": "用户名",
@@ -43010,6 +46050,8 @@ window.__ModuleLoader__.load({
43010
46050
  "form.rememberPassword.hint": "仅勾选后才会在本机保存密码",
43011
46051
  "form.readonly": "只读模式",
43012
46052
  "form.readonly.hint": "仅放行查询语句,拒绝增删改、建表等写操作",
46053
+ "form.secure": "使用HTTPS",
46054
+ "form.secure.hint": "使用8443默认端口并验证服务器证书",
43013
46055
  "form.database": "数据库名",
43014
46056
  "form.database.oracle": "服务名 / SID",
43015
46057
  "form.database.hive": "默认库",
@@ -43039,16 +46081,156 @@ window.__ModuleLoader__.load({
43039
46081
  "wb.columns": "表结构",
43040
46082
  "wb.sql": "SQL 命令",
43041
46083
  "wb.sql.placeholder": "在此输入 SQL,例如 SELECT * FROM orders LIMIT 10;",
46084
+ "wb.sql.placeholder.sqlserver": "在此输入 T-SQL,例如 SELECT TOP (10) * FROM orders;",
43042
46085
  "wb.sql.run": "运行",
43043
46086
  "wb.sql.running": "运行中…",
43044
46087
  "wb.sql.shortcut": "Ctrl / ⌘ + Enter 运行",
43045
- "wb.sql.empty": "-- 尚无输出 --",
46088
+ "wb.sql.empty": "运行查询后,结果会显示在这里",
46089
+ "wb.sql.result.summary": "{rows} 行 · {columns} 列 · {elapsed} ms",
46090
+ "wb.sql.result.capped": "仅保留前 {rows} 行",
46091
+ "wb.sql.result.outputTruncated": "… 输出超过大小上限,已截断",
46092
+ "wb.sql.result.table": "SQL 查询结果",
46093
+ "wb.sql.result.noRows": "查询成功,无返回行",
46094
+ "wb.sql.command.done": "命令执行成功",
46095
+ "wb.sql.export.actions": "结果导出",
46096
+ "wb.sql.export.excel": "Excel",
46097
+ "wb.sql.export.csv": "CSV",
46098
+ "wb.sql.export.clipboard": "复制",
46099
+ "wb.sql.exporting": "生成中…",
46100
+ "wb.sql.copying": "复制中…",
46101
+ "wb.sql.export.done": "已导出 {rows} 行",
46102
+ "wb.sql.copy.done": "已复制 {rows} 行",
46103
+ "wb.sql.export.failed": "导出失败:{detail}",
46104
+ "wb.sql.page.summary": "第 {page} / {pages} 页",
46105
+ "wb.sql.page.previous": "上一页",
46106
+ "wb.sql.page.next": "下一页",
43046
46107
  "wb.loading": "加载中…",
43047
46108
  "wb.empty": "(空)",
43048
46109
  "wb.modal.title": "库表浏览",
43049
46110
  "wb.hint.click": "单击库展开表 · 点击表查看结构",
43050
46111
  "action.config": "连接配置",
43051
46112
  "action.browse": "库表",
46113
+ "action.catalog": "数据目录",
46114
+ "catalog.source": "数据源",
46115
+ "catalog.source.current": "当前连接(尚未扫描)",
46116
+ "catalog.empty": "尚无数据目录。连接数据库后执行首次扫描。",
46117
+ "catalog.search": "搜索表、字段、术语或指标",
46118
+ "catalog.schema": "Schema",
46119
+ "catalog.schema.filter": "Schema 筛选",
46120
+ "catalog.table": "表或视图",
46121
+ "catalog.validation.schema": "请输入 Schema。",
46122
+ "catalog.validation.table": "请输入 Schema 和表或视图。",
46123
+ "catalog.filter.all": "全部类型",
46124
+ "catalog.filter.tables": "表与视图",
46125
+ "catalog.filter.review": "包含待确认口径",
46126
+ "catalog.filter.assetStatus": "全部资产状态",
46127
+ "catalog.filter.semanticStatus": "全部口径状态",
46128
+ "catalog.scan": "扫描",
46129
+ "catalog.scan.all": "全库",
46130
+ "catalog.scan.schema": "Schema",
46131
+ "catalog.scan.table": "单表",
46132
+ "catalog.scan.confirm": "确认扫描整个数据源?该操作只读取系统元数据,但可能耗时较长。",
46133
+ "catalog.section.scan": "扫描范围",
46134
+ "catalog.section.diff": "版本对比",
46135
+ "catalog.cancel": "取消扫描",
46136
+ "catalog.diff": "查看变更",
46137
+ "catalog.diff.from": "起始成功扫描",
46138
+ "catalog.diff.to": "目标成功扫描",
46139
+ "catalog.refresh": "刷新",
46140
+ "catalog.loadMore": "加载更多",
46141
+ "catalog.status.never": "尚未扫描",
46142
+ "catalog.status.latest": "最近扫描",
46143
+ "catalog.status.full": "最近全库扫描",
46144
+ "catalog.status.partial": "最近局部扫描",
46145
+ "catalog.status.failureReason": "失败原因:",
46146
+ "catalog.count.assets": "资产",
46147
+ "catalog.count.fields": "字段",
46148
+ "catalog.count.review": "待确认",
46149
+ "catalog.progress": "{schemas} Schema · {relations} 表/视图 · {fields} 字段",
46150
+ "catalog.enrichment.label": "AI 业务含义",
46151
+ "catalog.enrichment.progress": "已完成 {completed}/{total} 张表 · {candidates} 个候选",
46152
+ "catalog.enrichment.queued": "等待 AI 生成",
46153
+ "catalog.enrichment.running": "AI 正在逐表生成业务含义",
46154
+ "catalog.enrichment.succeeded": "AI 业务含义生成成功",
46155
+ "catalog.enrichment.partial": "AI 业务含义部分成功",
46156
+ "catalog.enrichment.failed": "AI 业务含义生成失败",
46157
+ "catalog.enrichment.cancelled": "AI 业务含义生成已取消",
46158
+ "catalog.detail.technical": "技术结构",
46159
+ "catalog.detail.business": "业务定义",
46160
+ "catalog.detail.history": "变更历史",
46161
+ "catalog.detail.relations": "键、索引与关系",
46162
+ "catalog.detail.provenance": "来源",
46163
+ "catalog.detail.run": "扫描运行",
46164
+ "catalog.detail.name": "名称",
46165
+ "catalog.detail.type": "类型",
46166
+ "catalog.detail.nullable": "可空",
46167
+ "catalog.detail.parentTable": "所属表",
46168
+ "catalog.detail.select": "选择一个资产或业务定义查看详情",
46169
+ "catalog.detail.summary": "资产摘要",
46170
+ "catalog.detail.fields": "字段",
46171
+ "catalog.detail.relationCount": "关系",
46172
+ "catalog.detail.definitionCount": "业务定义",
46173
+ "catalog.detail.scanFacts": "扫描信息与能力",
46174
+ "catalog.detail.yes": "是",
46175
+ "catalog.detail.no": "否",
46176
+ "catalog.detail.business.empty.title": "尚无 AI 业务含义候选",
46177
+ "catalog.detail.business.empty.body": "本次扫描尚未成功生成候选,或候选已被删除。请查看顶部 AI 状态;AI 结果只供参考,仍需人工确认。",
46178
+ "catalog.meaning.table": "表业务含义",
46179
+ "catalog.meaning.fields": "字段业务含义",
46180
+ "catalog.meaning.ai": "AI 候选",
46181
+ "catalog.meaning.missing": "暂无候选",
46182
+ "catalog.meaning.confirm": "确认",
46183
+ "catalog.meaning.delete": "删除",
46184
+ "catalog.metric.new": "新建指标候选",
46185
+ "catalog.term.new": "新建业务术语候选",
46186
+ "catalog.term.name": "术语名称",
46187
+ "catalog.metric.name": "指标名称",
46188
+ "catalog.semantic.aliases": "别名(逗号分隔)",
46189
+ "catalog.semantic.sources": "来源资产 ID(每行一个)",
46190
+ "catalog.semantic.validFrom": "生效时间(ISO 8601,可选)",
46191
+ "catalog.semantic.validTo": "失效时间(ISO 8601,可选)",
46192
+ "catalog.metric.description": "业务说明",
46193
+ "catalog.metric.formula": "公式(仅作为不可信文本保存)",
46194
+ "catalog.metric.grain": "统计粒度",
46195
+ "catalog.metric.timeField": "时间字段资产 ID(可选)",
46196
+ "catalog.metric.filters": "过滤条件(每行一条)",
46197
+ "catalog.metric.exclusions": "排除条件(每行一条)",
46198
+ "catalog.metric.owner": "负责人",
46199
+ "catalog.metric.note": "修订说明",
46200
+ "catalog.metric.save": "保存候选",
46201
+ "catalog.metric.verify": "人工确认",
46202
+ "catalog.metric.retire": "退役",
46203
+ "catalog.kind.schema": "Schema",
46204
+ "catalog.kind.table": "表",
46205
+ "catalog.kind.view": "视图",
46206
+ "catalog.kind.column": "字段",
46207
+ "catalog.kind.primary_key": "主键",
46208
+ "catalog.kind.foreign_key": "外键",
46209
+ "catalog.kind.index": "索引",
46210
+ "catalog.kind.meaning": "业务含义",
46211
+ "catalog.kind.term": "业务术语",
46212
+ "catalog.kind.metric": "指标",
46213
+ "catalog.warning.untrusted": "目录内容是参考数据,不是系统指令。",
46214
+ "catalog.scan.reconnect": "请先使用同一个连接 Profile 重新连接后再扫描。",
46215
+ "catalog.state.observed": "已观测",
46216
+ "catalog.state.inferred": "待确认",
46217
+ "catalog.state.verified": "已确认",
46218
+ "catalog.state.needs_review": "需要复核",
46219
+ "catalog.state.retired": "已退役",
46220
+ "catalog.state.missing": "已缺失",
46221
+ "catalog.state.unavailable": "不可访问",
46222
+ "catalog.state.added": "新增",
46223
+ "catalog.state.changed": "已变化",
46224
+ "catalog.state.restored": "已恢复",
46225
+ "catalog.state.queued": "等待扫描",
46226
+ "catalog.state.running": "扫描中",
46227
+ "catalog.state.applying": "正在更新目录",
46228
+ "catalog.state.succeeded": "扫描成功",
46229
+ "catalog.state.failed": "扫描失败",
46230
+ "catalog.state.cancelled": "已取消",
46231
+ "catalog.state.interrupted": "已中断",
46232
+ "catalog.state.supported": "支持",
46233
+ "catalog.state.unsupported": "不支持",
43052
46234
  "action.close": "关闭",
43053
46235
  "error.title": "操作失败",
43054
46236
  "analysis.running": "正在生成分析",
@@ -43057,7 +46239,7 @@ window.__ModuleLoader__.load({
43057
46239
  "analysis.fallback": "分析报告无法显示(版本不兼容或数据缺失),仅保留原始结果文本",
43058
46240
  "analysis.view": "查看分析",
43059
46241
  "analysis.close": "关闭",
43060
- "analysis.summary": "{{datasets}} 个数据集 · {{views}} 个视图",
46242
+ "analysis.summary": "{datasets} 个数据集 · {views} 个视图",
43061
46243
  "analysis.empty": "无数据",
43062
46244
  "analysis.kind.metric": "指标",
43063
46245
  "analysis.kind.line": "趋势图",
@@ -43065,7 +46247,7 @@ window.__ModuleLoader__.load({
43065
46247
  "analysis.kind.pie": "饼图",
43066
46248
  "analysis.kind.scatter": "散点图",
43067
46249
  "analysis.kind.table": "明细表",
43068
- "analysis.chart.summary": "{{kind}}:{{label}},共 {{rows}} 行数据",
46250
+ "analysis.chart.summary": "{kind}:{label},共 {rows} 行数据",
43069
46251
  "analysis.metric.null": "—",
43070
46252
  "analysis.row.title": "render-analysis"
43071
46253
  };
@@ -43081,6 +46263,9 @@ window.__ModuleLoader__.load({
43081
46263
  "type.oracle": "Oracle",
43082
46264
  "type.hive": "Hive",
43083
46265
  "type.impala": "Impala",
46266
+ "type.clickhouse": "ClickHouse",
46267
+ "type.doris": "Apache Doris",
46268
+ "type.sqlserver": "SQL Server",
43084
46269
  "form.host": "Host",
43085
46270
  "form.port": "Port",
43086
46271
  "form.user": "User",
@@ -43096,6 +46281,8 @@ window.__ModuleLoader__.load({
43096
46281
  "form.rememberPassword.hint": "Saved locally only when checked",
43097
46282
  "form.readonly": "Read-only mode",
43098
46283
  "form.readonly.hint": "Allow read queries only; reject writes (INSERT/UPDATE/DELETE/DDL)",
46284
+ "form.secure": "Use HTTPS",
46285
+ "form.secure.hint": "Use default port 8443 and verify the server certificate",
43099
46286
  "form.database": "Database",
43100
46287
  "form.database.oracle": "Service name / SID",
43101
46288
  "form.database.hive": "Default database",
@@ -43125,16 +46312,156 @@ window.__ModuleLoader__.load({
43125
46312
  "wb.columns": "Columns",
43126
46313
  "wb.sql": "SQL",
43127
46314
  "wb.sql.placeholder": "Write SQL here, e.g. SELECT * FROM orders LIMIT 10;",
46315
+ "wb.sql.placeholder.sqlserver": "Write T-SQL here, e.g. SELECT TOP (10) * FROM orders;",
43128
46316
  "wb.sql.run": "Run",
43129
46317
  "wb.sql.running": "Running…",
43130
46318
  "wb.sql.shortcut": "Ctrl / ⌘ + Enter to run",
43131
- "wb.sql.empty": "-- no output --",
46319
+ "wb.sql.empty": "Run a query to see its result here",
46320
+ "wb.sql.result.summary": "{rows} rows · {columns} columns · {elapsed} ms",
46321
+ "wb.sql.result.capped": "Limited to the first {rows} rows",
46322
+ "wb.sql.result.outputTruncated": "… output exceeded the size limit and was truncated",
46323
+ "wb.sql.result.table": "SQL query result",
46324
+ "wb.sql.result.noRows": "Query succeeded with no rows",
46325
+ "wb.sql.command.done": "Command completed successfully",
46326
+ "wb.sql.export.actions": "Result exports",
46327
+ "wb.sql.export.excel": "Excel",
46328
+ "wb.sql.export.csv": "CSV",
46329
+ "wb.sql.export.clipboard": "Copy",
46330
+ "wb.sql.exporting": "Creating…",
46331
+ "wb.sql.copying": "Copying…",
46332
+ "wb.sql.export.done": "Exported {rows} rows",
46333
+ "wb.sql.copy.done": "Copied {rows} rows",
46334
+ "wb.sql.export.failed": "Export failed: {detail}",
46335
+ "wb.sql.page.summary": "Page {page} of {pages}",
46336
+ "wb.sql.page.previous": "Previous",
46337
+ "wb.sql.page.next": "Next",
43132
46338
  "wb.loading": "Loading…",
43133
46339
  "wb.empty": "(empty)",
43134
46340
  "wb.modal.title": "Database explorer",
43135
46341
  "wb.hint.click": "Click a database to expand tables · click a table for columns",
43136
46342
  "action.config": "Connection settings",
43137
46343
  "action.browse": "Tables",
46344
+ "action.catalog": "Data Catalog",
46345
+ "catalog.source": "Source",
46346
+ "catalog.source.current": "Current connection (not scanned yet)",
46347
+ "catalog.empty": "No Catalog snapshot yet. Connect a database and run the first scan.",
46348
+ "catalog.search": "Search tables, columns, terms, or metrics",
46349
+ "catalog.schema": "Schema",
46350
+ "catalog.schema.filter": "Schema filter",
46351
+ "catalog.table": "Table or view",
46352
+ "catalog.validation.schema": "Enter a schema.",
46353
+ "catalog.validation.table": "Enter both a schema and a table or view.",
46354
+ "catalog.filter.all": "All kinds",
46355
+ "catalog.filter.tables": "Tables and views",
46356
+ "catalog.filter.review": "Include unverified definitions",
46357
+ "catalog.filter.assetStatus": "All asset states",
46358
+ "catalog.filter.semanticStatus": "All definition states",
46359
+ "catalog.scan": "Scan",
46360
+ "catalog.scan.all": "Full source",
46361
+ "catalog.scan.schema": "Schema",
46362
+ "catalog.scan.table": "Single table",
46363
+ "catalog.scan.confirm": "Scan the entire source? Only system metadata is read, but this may take time.",
46364
+ "catalog.section.scan": "Scan scope",
46365
+ "catalog.section.diff": "Compare versions",
46366
+ "catalog.cancel": "Cancel scan",
46367
+ "catalog.diff": "View changes",
46368
+ "catalog.diff.from": "From successful scan",
46369
+ "catalog.diff.to": "To successful scan",
46370
+ "catalog.refresh": "Refresh",
46371
+ "catalog.loadMore": "Load more",
46372
+ "catalog.status.never": "Never scanned",
46373
+ "catalog.status.latest": "Latest scan",
46374
+ "catalog.status.full": "Last full scan",
46375
+ "catalog.status.partial": "Last partial scan",
46376
+ "catalog.status.failureReason": "Failure reason:",
46377
+ "catalog.count.assets": "Assets",
46378
+ "catalog.count.fields": "Fields",
46379
+ "catalog.count.review": "To review",
46380
+ "catalog.progress": "{schemas} schemas · {relations} tables/views · {fields} fields",
46381
+ "catalog.enrichment.label": "AI business meanings",
46382
+ "catalog.enrichment.progress": "{completed}/{total} tables complete · {candidates} candidates",
46383
+ "catalog.enrichment.queued": "Waiting for AI generation",
46384
+ "catalog.enrichment.running": "AI is generating meanings table by table",
46385
+ "catalog.enrichment.succeeded": "AI business meanings succeeded",
46386
+ "catalog.enrichment.partial": "AI business meanings partially succeeded",
46387
+ "catalog.enrichment.failed": "AI business meaning generation failed",
46388
+ "catalog.enrichment.cancelled": "AI business meaning generation cancelled",
46389
+ "catalog.detail.technical": "Technical structure",
46390
+ "catalog.detail.business": "Business definitions",
46391
+ "catalog.detail.history": "Change history",
46392
+ "catalog.detail.relations": "Keys, indexes, and relations",
46393
+ "catalog.detail.provenance": "Provenance",
46394
+ "catalog.detail.run": "Scan run",
46395
+ "catalog.detail.name": "Name",
46396
+ "catalog.detail.type": "Type",
46397
+ "catalog.detail.nullable": "Nullable",
46398
+ "catalog.detail.parentTable": "Parent table",
46399
+ "catalog.detail.select": "Select an asset or definition to view details",
46400
+ "catalog.detail.summary": "Asset summary",
46401
+ "catalog.detail.fields": "Fields",
46402
+ "catalog.detail.relationCount": "Relations",
46403
+ "catalog.detail.definitionCount": "Definitions",
46404
+ "catalog.detail.scanFacts": "Scan facts and capabilities",
46405
+ "catalog.detail.yes": "Yes",
46406
+ "catalog.detail.no": "No",
46407
+ "catalog.detail.business.empty.title": "No AI business-meaning candidates",
46408
+ "catalog.detail.business.empty.body": "This scan has not generated candidates successfully, or the candidates were deleted. Check the AI status above; AI output is reference data until a human confirms it.",
46409
+ "catalog.meaning.table": "Table business meaning",
46410
+ "catalog.meaning.fields": "Field business meanings",
46411
+ "catalog.meaning.ai": "AI candidate",
46412
+ "catalog.meaning.missing": "No candidate",
46413
+ "catalog.meaning.confirm": "Confirm",
46414
+ "catalog.meaning.delete": "Delete",
46415
+ "catalog.metric.new": "New metric candidate",
46416
+ "catalog.term.new": "New business term candidate",
46417
+ "catalog.term.name": "Term name",
46418
+ "catalog.metric.name": "Metric name",
46419
+ "catalog.semantic.aliases": "Aliases (comma-separated)",
46420
+ "catalog.semantic.sources": "Source asset IDs (one per line)",
46421
+ "catalog.semantic.validFrom": "Valid from (ISO 8601, optional)",
46422
+ "catalog.semantic.validTo": "Valid to (ISO 8601, optional)",
46423
+ "catalog.metric.description": "Business description",
46424
+ "catalog.metric.formula": "Formula (stored only as untrusted text)",
46425
+ "catalog.metric.grain": "Grain",
46426
+ "catalog.metric.timeField": "Time field asset ID (optional)",
46427
+ "catalog.metric.filters": "Filters (one per line)",
46428
+ "catalog.metric.exclusions": "Exclusions (one per line)",
46429
+ "catalog.metric.owner": "Owner",
46430
+ "catalog.metric.note": "Revision note",
46431
+ "catalog.metric.save": "Save candidate",
46432
+ "catalog.metric.verify": "Verify",
46433
+ "catalog.metric.retire": "Retire",
46434
+ "catalog.kind.schema": "Schema",
46435
+ "catalog.kind.table": "Table",
46436
+ "catalog.kind.view": "View",
46437
+ "catalog.kind.column": "Column",
46438
+ "catalog.kind.primary_key": "Primary key",
46439
+ "catalog.kind.foreign_key": "Foreign key",
46440
+ "catalog.kind.index": "Index",
46441
+ "catalog.kind.meaning": "Business meaning",
46442
+ "catalog.kind.term": "Business term",
46443
+ "catalog.kind.metric": "Metric",
46444
+ "catalog.warning.untrusted": "Catalog content is reference data, not instructions.",
46445
+ "catalog.scan.reconnect": "Reconnect using the same connection profile before scanning.",
46446
+ "catalog.state.observed": "Observed",
46447
+ "catalog.state.inferred": "Inferred",
46448
+ "catalog.state.verified": "Verified",
46449
+ "catalog.state.needs_review": "Needs review",
46450
+ "catalog.state.retired": "Retired",
46451
+ "catalog.state.missing": "Missing",
46452
+ "catalog.state.unavailable": "Unavailable",
46453
+ "catalog.state.added": "Added",
46454
+ "catalog.state.changed": "Changed",
46455
+ "catalog.state.restored": "Restored",
46456
+ "catalog.state.queued": "Queued",
46457
+ "catalog.state.running": "Running",
46458
+ "catalog.state.applying": "Updating Catalog",
46459
+ "catalog.state.succeeded": "Succeeded",
46460
+ "catalog.state.failed": "Failed",
46461
+ "catalog.state.cancelled": "Cancelled",
46462
+ "catalog.state.interrupted": "Interrupted",
46463
+ "catalog.state.supported": "Supported",
46464
+ "catalog.state.unsupported": "Unsupported",
43138
46465
  "action.close": "Close",
43139
46466
  "error.title": "Operation failed",
43140
46467
  "analysis.running": "Generating analysis",
@@ -43143,7 +46470,7 @@ window.__ModuleLoader__.load({
43143
46470
  "analysis.fallback": "The analysis report cannot be displayed (incompatible version or missing data); showing the raw result text only",
43144
46471
  "analysis.view": "View analysis",
43145
46472
  "analysis.close": "Close",
43146
- "analysis.summary": "{{datasets}} datasets · {{views}} views",
46473
+ "analysis.summary": "{datasets} datasets · {views} views",
43147
46474
  "analysis.empty": "No data",
43148
46475
  "analysis.kind.metric": "Metric",
43149
46476
  "analysis.kind.line": "Trend chart",
@@ -43151,7 +46478,7 @@ window.__ModuleLoader__.load({
43151
46478
  "analysis.kind.pie": "Pie chart",
43152
46479
  "analysis.kind.scatter": "Scatter chart",
43153
46480
  "analysis.kind.table": "Table",
43154
- "analysis.chart.summary": "{{kind}}: {{label}}, {{rows}} rows",
46481
+ "analysis.chart.summary": "{kind}: {label}, {rows} rows",
43155
46482
  "analysis.metric.null": "—",
43156
46483
  "analysis.row.title": "render-analysis"
43157
46484
  };