@webskill/sdk 0.27.1 → 0.28.1

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.
@@ -1,4 +1,4 @@
1
- import { u as interactionToFormModel } from "./miniChart-D0nYMzz8.js";
1
+ import { r as renderMiniChart, u as interactionToFormModel } from "./miniChart-k95Dpy0q.js";
2
2
  import { toJSONSchema, z } from "zod";
3
3
 
4
4
  //#region ../ui/src/chart/echart.ts
@@ -10,23 +10,20 @@ const KINDS = /* @__PURE__ */ new Set([
10
10
  "pie",
11
11
  "scatter",
12
12
  "stacked-bar",
13
- "dual-axis"
13
+ "dual-axis",
14
+ "bar-line"
14
15
  ]);
15
- const list = (value) => Array.isArray(value) ? value : [];
16
- /**
17
- * catalog `Chart` 节点 props → `ChartSpec`。四档共用这一份转换:
18
- * 此前 native / OpenUI / json-render / A2UI 各抄了一遍,改一处就会漂移。
19
- * 非法枚举**原样保留**,由 `toEchartsOption` 给出可见降级提示——
20
- * 此前偷偷改写成 `'line'`,画出的图与模型的意图无关且不可察觉。
21
- */
16
+ const list$1 = (value) => Array.isArray(value) ? value : [];
17
+ /** catalog `Chart` 节点 props → `ChartSpec`。非法枚举保留,由 `toEchartsOption` 给出可见降级提示。 */
22
18
  function chartSpecFromProps(props) {
23
- const series = list(props["series"]);
19
+ const series = list$1(props["series"]);
24
20
  return {
25
21
  kind: typeof props["type"] === "string" ? props["type"] : "",
26
- labels: list(props["labels"]),
22
+ labels: list$1(props["labels"]),
27
23
  series: series.map((item) => ({
28
24
  ...typeof item.name === "string" ? { name: item.name } : {},
29
- data: list(item.values)
25
+ data: list$1(item.values),
26
+ ...item.type === "bar" || item.type === "line" ? { type: item.type } : {}
30
27
  })),
31
28
  ...typeof props["title"] === "string" ? { title: props["title"] } : {}
32
29
  };
@@ -206,7 +203,7 @@ function toEchartsOption(chart, fontSizes, colors) {
206
203
  value: series.data[index] ?? 0
207
204
  }))
208
205
  })) : chart.series.map((series, index) => ({
209
- ...shape,
206
+ ...chart.kind === "bar-line" ? SERIES_SHAPE[series.type ?? (index === 0 ? "bar" : "line")] : shape,
210
207
  name: series.name,
211
208
  data: series.data,
212
209
  ...chart.kind === "dual-axis" ? { yAxisIndex: index === 0 ? 0 : 1 } : {}
@@ -230,6 +227,9 @@ function applyChartDomContract(container, chart) {
230
227
  */
231
228
  let echartsModule;
232
229
  const loadEcharts = () => echartsModule ??= import("./echarts-BE7oV_Dl.js");
230
+ const resetEchartsModule = () => {
231
+ echartsModule = void 0;
232
+ };
233
233
  const sameColors = (a, b) => a === b || a !== void 0 && b !== void 0 && a.title === b.title && a.axisLabel === b.axisLabel && a.legend === b.legend && a.axisLine === b.axisLine && a.splitLine === b.splitLine;
234
234
  /**
235
235
  * 框架无关的 echarts 挂载点:三档的 React 组件与 A2UI 档的 Lit 元素共用同一实现,
@@ -306,6 +306,391 @@ function mountEchart(container) {
306
306
  };
307
307
  }
308
308
 
309
+ //#endregion
310
+ //#region ../ui/src/chart/fallback.ts
311
+ const isRecord$4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
312
+ const list = (value) => Array.isArray(value) ? value : [];
313
+ const text = (value) => typeof value === "string" ? value : String(value ?? "");
314
+ function axisLabels(option) {
315
+ const xAxis = option["xAxis"];
316
+ const axis = Array.isArray(xAxis) ? xAxis[0] : xAxis;
317
+ if (isRecord$4(axis) && Array.isArray(axis["data"])) return axis["data"].map(text);
318
+ const dataset = option["dataset"];
319
+ const source = isRecord$4(dataset) ? dataset["source"] : void 0;
320
+ if (Array.isArray(source)) return source.slice(0, 20).map((row) => Array.isArray(row) ? text(row[0]) : "");
321
+ return [];
322
+ }
323
+ function dataValues(series, datasetValues, datasetColumn) {
324
+ const encode = isRecord$4(series["encode"]) ? series["encode"]["y"] : void 0;
325
+ const dimension = Array.isArray(encode) ? encode[0] : encode;
326
+ const column = typeof dimension === "number" ? dimension : typeof dimension === "string" ? Number(dimension) : void 0;
327
+ if (datasetValues.length > 0) return datasetValues.map((row) => Number(row[column ?? datasetColumn]) || 0);
328
+ return list(series["data"]).map((entry) => {
329
+ if (typeof entry === "number") return entry;
330
+ if (Array.isArray(entry)) return Number(entry[column ?? 0]) || 0;
331
+ if (isRecord$4(entry)) {
332
+ const value = entry["value"];
333
+ if (typeof value === "number") return value;
334
+ if (Array.isArray(value)) return Number(value[column ?? 0]) || 0;
335
+ }
336
+ return 0;
337
+ });
338
+ }
339
+ function datasetRows(option) {
340
+ const dataset = option["dataset"];
341
+ const source = isRecord$4(dataset) ? dataset["source"] : void 0;
342
+ return Array.isArray(source) ? source.filter(Array.isArray).slice(0, 20) : [];
343
+ }
344
+ function chartSpecFromEchartsOption(option) {
345
+ const series = list(option["series"]).filter(isRecord$4);
346
+ if (series.length === 0) return void 0;
347
+ const labels = axisLabels(option);
348
+ if (labels.length === 0) return void 0;
349
+ const types = new Set(series.map((entry) => entry["type"] ?? "bar"));
350
+ if ([...types].some((type) => ![
351
+ "bar",
352
+ "line",
353
+ "area",
354
+ "scatter",
355
+ "pie"
356
+ ].includes(String(type)))) return void 0;
357
+ const datasetValues = datasetRows(option);
358
+ const converted = series.map((entry, index) => ({
359
+ name: text(entry["name"]),
360
+ data: dataValues(entry, datasetValues, index + 1)
361
+ }));
362
+ if (types.size > 1 && [...types].some((type) => type !== "bar" && type !== "line")) return void 0;
363
+ const kind = types.size > 1 ? "bar-line" : String([...types][0]);
364
+ return chartSpecFromProps({
365
+ type: kind,
366
+ labels,
367
+ series: converted.map((entry, index) => ({
368
+ name: entry.name,
369
+ values: entry.data,
370
+ ...kind === "bar-line" ? { type: series[index]["type"] === "line" ? "line" : "bar" } : {}
371
+ }))
372
+ });
373
+ }
374
+ function append(doc, parent, name, value) {
375
+ const element = doc.createElement(name);
376
+ element.textContent = value;
377
+ parent.appendChild(element);
378
+ return element;
379
+ }
380
+ function renderTable(option, doc) {
381
+ const table = doc.createElement("table");
382
+ table.setAttribute("data-webskill-echart-fallback", "table");
383
+ const series = list(option["series"]).filter(isRecord$4);
384
+ const caption = append(doc, table, "caption", `ECharts fallback: ${series.map((entry) => text(entry["type"])).join(", ")}`);
385
+ caption.className = "text-sm text-muted-foreground";
386
+ const headRow = append(doc, append(doc, table, "thead", ""), "tr", "");
387
+ for (const label of [
388
+ "Series",
389
+ "Type",
390
+ "Data (first 8 entries)"
391
+ ]) append(doc, headRow, "th", label);
392
+ const body = append(doc, table, "tbody", "");
393
+ for (const [index, entry] of series.entries()) {
394
+ const row = append(doc, body, "tr", "");
395
+ append(doc, row, "td", text(entry["name"]) || `Series ${index + 1}`);
396
+ append(doc, row, "td", text(entry["type"]));
397
+ append(doc, row, "td", list(entry["data"]).slice(0, 8).map((value) => JSON.stringify(value)).join(", "));
398
+ }
399
+ return table;
400
+ }
401
+ function renderEchartFallback(option, doc, fallback = "auto") {
402
+ const spec = fallback === "auto" ? chartSpecFromEchartsOption(option) : void 0;
403
+ return spec === void 0 ? renderTable(option, doc) : renderMiniChart(spec, doc);
404
+ }
405
+
406
+ //#endregion
407
+ //#region ../ui/src/chart/option.ts
408
+ const ECHART_SERIES_TYPES = /* @__PURE__ */ new Set([
409
+ "bar",
410
+ "line",
411
+ "scatter",
412
+ "effectScatter",
413
+ "candlestick",
414
+ "heatmap",
415
+ "boxplot",
416
+ "pictorialBar",
417
+ "pie",
418
+ "gauge",
419
+ "radar",
420
+ "funnel",
421
+ "treemap",
422
+ "sunburst",
423
+ "tree",
424
+ "sankey",
425
+ "graph",
426
+ "themeRiver",
427
+ "parallel",
428
+ "map",
429
+ "lines"
430
+ ]);
431
+ const EVENT_KEYS = /* @__PURE__ */ new Set([
432
+ "on",
433
+ "once",
434
+ "event",
435
+ "events",
436
+ "eventlistener",
437
+ "eventlisteners",
438
+ "triggerevent",
439
+ "silent",
440
+ "selectedmode",
441
+ "cursor",
442
+ "onclick",
443
+ "ondblclick",
444
+ "onmouseover",
445
+ "onmouseout",
446
+ "onmousedown",
447
+ "onmouseup",
448
+ "onmousemove",
449
+ "oncontextmenu"
450
+ ]);
451
+ const PROTOTYPE_KEYS = /* @__PURE__ */ new Set([
452
+ "__proto__",
453
+ "prototype",
454
+ "constructor"
455
+ ]);
456
+ const MAX_DEPTH = 100;
457
+ const isRecord$3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
458
+ function sanitizeEchartOption(raw) {
459
+ const degradations = [];
460
+ const drop = (path, detail) => {
461
+ degradations.push({
462
+ path,
463
+ detail
464
+ });
465
+ };
466
+ const visit = (value, path, depth) => {
467
+ if (value === void 0) {
468
+ drop(path, "Undefined value was dropped.");
469
+ return;
470
+ }
471
+ if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") {
472
+ drop(path, `${typeof value === "function" ? "Function" : "Non-JSON value"} was dropped.`);
473
+ return;
474
+ }
475
+ if (typeof value === "number" && !Number.isFinite(value)) {
476
+ drop(path, "Non-finite number was replaced with null.");
477
+ return null;
478
+ }
479
+ if (value === null || typeof value !== "object") return value;
480
+ if (depth >= MAX_DEPTH) {
481
+ drop(path, `Configuration deeper than ${MAX_DEPTH} levels was dropped.`);
482
+ return;
483
+ }
484
+ if (Array.isArray(value)) {
485
+ const out = [];
486
+ value.forEach((entry, index) => {
487
+ const cleaned = visit(entry, `${path}[${index}]`, depth + 1);
488
+ if (cleaned !== void 0) out.push(cleaned);
489
+ });
490
+ return out;
491
+ }
492
+ if (!isRecord$3(value)) {
493
+ drop(path, "Non-plain object was dropped.");
494
+ return;
495
+ }
496
+ const out = {};
497
+ for (const [key, entry] of Object.entries(value)) {
498
+ if (PROTOTYPE_KEYS.has(key) || EVENT_KEYS.has(key.toLowerCase()) || /^on[A-Z]/.test(key)) {
499
+ drop(`${path}.${key}`, "Event handler or unsafe key was dropped.");
500
+ continue;
501
+ }
502
+ const cleaned = visit(entry, `${path}.${key}`, depth + 1);
503
+ if (cleaned !== void 0) out[key] = cleaned;
504
+ }
505
+ return out;
506
+ };
507
+ if (!isRecord$3(raw)) return {
508
+ option: {},
509
+ degradations: [{
510
+ path: "option",
511
+ detail: "ECharts option must be an object; an empty option was used."
512
+ }]
513
+ };
514
+ const option = visit(raw, "option", 0);
515
+ const keepSeries = (series, path) => {
516
+ if (!isRecord$3(series)) {
517
+ drop(path, "Series entry must be an object and was dropped.");
518
+ return false;
519
+ }
520
+ const type = series["type"];
521
+ if (type === "custom") {
522
+ drop(`${path}.type`, "Custom series requires executable code and was dropped.");
523
+ return false;
524
+ }
525
+ if (typeof type !== "string" || !ECHART_SERIES_TYPES.has(type)) {
526
+ drop(`${path}.type`, `Unsupported series type "${String(type)}" was dropped.`);
527
+ return false;
528
+ }
529
+ return true;
530
+ };
531
+ const applyRules = (option, path) => {
532
+ const rawSeries = option["series"];
533
+ if (Array.isArray(rawSeries)) option["series"] = rawSeries.filter((series, index) => keepSeries(series, `${path}.series[${index}]`));
534
+ else if (rawSeries !== void 0 && !keepSeries(rawSeries, `${path}.series`)) delete option["series"];
535
+ if (isRecord$3(option["tooltip"])) {
536
+ const tooltip = option["tooltip"];
537
+ if (tooltip["renderMode"] !== "richText") {
538
+ if (tooltip["renderMode"] !== void 0) drop(`${path}.tooltip.renderMode`, "HTML tooltip was replaced with rich text to prevent HTML injection.");
539
+ tooltip["renderMode"] = "richText";
540
+ }
541
+ }
542
+ for (const [key, value] of Object.entries(option)) if (Array.isArray(value)) value.forEach((entry, index) => {
543
+ if (isRecord$3(entry)) applyRules(entry, `${path}.${key}[${index}]`);
544
+ });
545
+ else if (isRecord$3(value)) applyRules(value, `${path}.${key}`);
546
+ };
547
+ applyRules(option, "option");
548
+ return {
549
+ option,
550
+ degradations
551
+ };
552
+ }
553
+ function echartOptionFromProps(props) {
554
+ const fallback = props["fallback"] === "table" ? "table" : "auto";
555
+ const { option, degradations } = sanitizeEchartOption(props["option"]);
556
+ return {
557
+ option,
558
+ fallback,
559
+ degradations
560
+ };
561
+ }
562
+
563
+ //#endregion
564
+ //#region ../ui/src/chart/optionMount.ts
565
+ function optionRecord(value) {
566
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
567
+ }
568
+ function styleEchartAxis(axis, font, color) {
569
+ if (typeof axis !== "object" || axis === null || Array.isArray(axis)) return;
570
+ const target = axis;
571
+ target["axisLabel"] = {
572
+ ...optionRecord(target["axisLabel"]),
573
+ fontSize: font.axisLabel,
574
+ color: color.axisLabel
575
+ };
576
+ const axisLine = optionRecord(target["axisLine"]);
577
+ const axisLineStyle = optionRecord(axisLine["lineStyle"]);
578
+ target["axisLine"] = {
579
+ ...axisLine,
580
+ lineStyle: {
581
+ ...axisLineStyle,
582
+ color: color.axisLine
583
+ }
584
+ };
585
+ const splitLine = optionRecord(target["splitLine"]);
586
+ const splitLineStyle = optionRecord(splitLine["lineStyle"]);
587
+ target["splitLine"] = {
588
+ ...splitLine,
589
+ lineStyle: {
590
+ ...splitLineStyle,
591
+ color: color.splitLine
592
+ }
593
+ };
594
+ }
595
+ function applyEchartTheme(input, fontSizes, colors) {
596
+ const font = resolveChartFontSizes(fontSizes);
597
+ const color = resolveChartColors(colors);
598
+ const option = sanitizeEchartOption(input).option;
599
+ const title = option["title"];
600
+ if (typeof title === "object" && title !== null && !Array.isArray(title)) {
601
+ const titleRecord = title;
602
+ titleRecord["textStyle"] = {
603
+ ...optionRecord(titleRecord["textStyle"]),
604
+ fontSize: font.title,
605
+ color: color.title
606
+ };
607
+ }
608
+ const legend = option["legend"];
609
+ if (typeof legend === "object" && legend !== null && !Array.isArray(legend)) {
610
+ const legendRecord = legend;
611
+ legendRecord["textStyle"] = {
612
+ ...optionRecord(legendRecord["textStyle"]),
613
+ fontSize: font.legend,
614
+ color: color.legend
615
+ };
616
+ }
617
+ for (const key of ["xAxis", "yAxis"]) {
618
+ const axis = option[key];
619
+ if (Array.isArray(axis)) axis.forEach((entry) => styleEchartAxis(entry, font, color));
620
+ else styleEchartAxis(axis, font, color);
621
+ }
622
+ return option;
623
+ }
624
+ function mountEchartOption(container) {
625
+ let disposed = false;
626
+ let instance;
627
+ let observer;
628
+ let themeObserver;
629
+ let inherited;
630
+ let queued;
631
+ const apply = (option, fontSizes, colors) => {
632
+ inherited = chartColorsFromContainer(container);
633
+ const effective = colors ? {
634
+ ...inherited,
635
+ ...colors
636
+ } : inherited;
637
+ instance?.setOption(applyEchartTheme(option, fontSizes, effective), {
638
+ notMerge: true,
639
+ lazyUpdate: true
640
+ });
641
+ };
642
+ const watchAncestors = () => {
643
+ if (typeof MutationObserver === "undefined") return;
644
+ themeObserver = new MutationObserver(() => {
645
+ if (disposed || queued === void 0) return;
646
+ if (sameColors(chartColorsFromContainer(container), inherited)) return;
647
+ apply(queued.option, queued.fontSizes, queued.colors);
648
+ });
649
+ for (let node = container; node; node = node.parentElement) themeObserver.observe(node, {
650
+ attributes: true,
651
+ attributeFilter: [
652
+ "class",
653
+ "style",
654
+ "data-theme"
655
+ ]
656
+ });
657
+ };
658
+ loadEcharts().then((echarts) => {
659
+ if (disposed) return;
660
+ instance = echarts.init(container);
661
+ if (typeof ResizeObserver !== "undefined") {
662
+ observer = new ResizeObserver(() => instance?.resize());
663
+ observer.observe(container);
664
+ }
665
+ watchAncestors();
666
+ if (queued) apply(queued.option, queued.fontSizes, queued.colors);
667
+ }).catch(() => {
668
+ resetEchartsModule();
669
+ if (!disposed && queued) container.replaceChildren(renderEchartFallback(queued.option, container.ownerDocument, queued.fallback));
670
+ });
671
+ return {
672
+ setOption(option, fontSizes, colors, fallback = "auto") {
673
+ container.setAttribute("data-webskill-echart", "option");
674
+ queued = {
675
+ option: sanitizeEchartOption(option).option,
676
+ ...fontSizes ? { fontSizes } : {},
677
+ ...colors ? { colors } : {},
678
+ fallback
679
+ };
680
+ apply(queued.option, queued.fontSizes, queued.colors);
681
+ },
682
+ dispose() {
683
+ disposed = true;
684
+ observer?.disconnect();
685
+ observer = void 0;
686
+ themeObserver?.disconnect();
687
+ themeObserver = void 0;
688
+ instance?.dispose();
689
+ instance = void 0;
690
+ }
691
+ };
692
+ }
693
+
309
694
  //#endregion
310
695
  //#region ../ui/src/catalog/gauge.ts
311
696
  /**
@@ -368,9 +753,13 @@ const CATALOG_BUDGET_STAGE = "final";
368
753
  * 三次上调合计把单请求成本从 21.7 KB 抬到约 35.3 KB。
369
754
  * **AC-G20 原文「超了砍组件、不抬阈值」在这三处被推翻,每次都限于当版;
370
755
  * 后续再撞顶仍须回到需求方,本版同样不得成为第四次上调的先例。**
756
+ *
757
+ * 4. 22 500 → 22 700(0.28.0,需求方要求开放声明式 ECharts option):新增独立 `EChart` 组件,
758
+ * 需要同时向模型开放 `option` 与 `fallback`,无法复用旧 `Chart` 的图型枚举。
759
+ * 实测 schema 22 646;上调只覆盖本次落地,未预留一个平均组件的增量。
371
760
  */
372
761
  const CATALOG_PROMPT_MAX = 13650;
373
- const CATALOG_SCHEMA_MAX = 22500;
762
+ const CATALOG_SCHEMA_MAX = 22700;
374
763
  /**
375
764
  * **尚未落地**的计划增量。0.15.0 分册 13 已落地,故仍归零;
376
765
  * `CATALOG_BUDGET_STAGE` 保持 `'final'`,余量改由「小于一个平均组件」判定。
@@ -482,6 +871,19 @@ function sanitizeNode(catalog, byName, node, path, degradations) {
482
871
  }
483
872
  props = kept;
484
873
  }
874
+ if (name === "EChart" && isRecord$2(props["option"])) {
875
+ const cleaned = sanitizeEchartOption(props["option"]);
876
+ props = {
877
+ ...props,
878
+ option: cleaned.option
879
+ };
880
+ for (const degradation of cleaned.degradations) degradations.push({
881
+ path: `${path}.props.${degradation.path}`,
882
+ kind: "prop-dropped",
883
+ component: name,
884
+ detail: degradation.detail
885
+ });
886
+ }
485
887
  const sanitized = {
486
888
  component: name,
487
889
  props
@@ -1187,7 +1589,7 @@ const uiCatalog = defineUiCatalog({
1187
1589
  {
1188
1590
  name: "Chart",
1189
1591
  group: "data",
1190
- description: "A bar, line, area, pie, scatter, stacked or dual-axis chart over labelled series.",
1592
+ description: "Simple chart.",
1191
1593
  props: z.object({
1192
1594
  type: z.enum([
1193
1595
  "bar",
@@ -1196,13 +1598,15 @@ const uiCatalog = defineUiCatalog({
1196
1598
  "pie",
1197
1599
  "scatter",
1198
1600
  "stacked-bar",
1199
- "dual-axis"
1601
+ "dual-axis",
1602
+ "bar-line"
1200
1603
  ]),
1201
1604
  title: z.string().optional(),
1202
1605
  labels: z.array(z.string()).min(1),
1203
1606
  series: z.array(z.object({
1204
1607
  name: z.string(),
1205
- values: z.array(z.number())
1608
+ values: z.array(z.number()),
1609
+ type: z.enum(["bar", "line"]).optional()
1206
1610
  })).min(1)
1207
1611
  }),
1208
1612
  example: {
@@ -1217,10 +1621,19 @@ const uiCatalog = defineUiCatalog({
1217
1621
  }
1218
1622
  }
1219
1623
  },
1624
+ {
1625
+ name: "EChart",
1626
+ group: "data",
1627
+ description: "ECharts option with labels, mixed series.",
1628
+ props: z.object({
1629
+ option: z.unknown(),
1630
+ fallback: z.enum(["auto", "table"]).optional()
1631
+ })
1632
+ },
1220
1633
  {
1221
1634
  name: "Timeline",
1222
1635
  group: "data",
1223
- description: "Ordered steps or events, earliest first.",
1636
+ description: "Ordered steps or events.",
1224
1637
  props: z.object({ items: z.array(z.object({
1225
1638
  title: z.string(),
1226
1639
  time: z.string().optional(),
@@ -2035,4 +2448,4 @@ function toOpenUiSpecLang(spec, catalog = uiCatalog) {
2035
2448
  }
2036
2449
 
2037
2450
  //#endregion
2038
- export { DEFAULT_CHART_COLORS as C, resolveChartColors as D, mountEchart as E, resolveChartFontSizes as O, gaugePercent as S, chartSpecFromProps as T, defineUiCatalog as _, SPEC_TABLE_MIN_COLUMN_VAR as a, CATALOG_SCHEMA_MAX as b, resolveColumnWidths as c, collectFormScopes as d, collectScopedValues as f, uiCatalog as g, UI_CATALOG_PROMPT_BUDGET_BYTES as h, normalizeFieldOptions as i, toEchartsOption as k, MAX_CONDITION_DEPTH as l, UI_CATALOG_GROUPS as m, interactionToUiSpec as n, SPEC_TABLE_MIN_COLUMN_WIDTH as o, qualifyFieldName as p, toJsonRenderSpec as r, normalizeColumnWidths as s, toOpenUiSpecLang as t, evaluateFieldCondition as u, CATALOG_BUDGET_STAGE as v, DEFAULT_CHART_FONT_SIZES as w, PLANNED_INCREMENT as x, CATALOG_PROMPT_MAX as y };
2451
+ export { DEFAULT_CHART_COLORS as A, applyEchartTheme as C, sanitizeEchartOption as D, echartOptionFromProps as E, resolveChartFontSizes as F, toEchartsOption as I, chartSpecFromProps as M, mountEchart as N, chartSpecFromEchartsOption as O, resolveChartColors as P, gaugePercent as S, ECHART_SERIES_TYPES as T, defineUiCatalog as _, SPEC_TABLE_MIN_COLUMN_VAR as a, CATALOG_SCHEMA_MAX as b, resolveColumnWidths as c, collectFormScopes as d, collectScopedValues as f, uiCatalog as g, UI_CATALOG_PROMPT_BUDGET_BYTES as h, normalizeFieldOptions as i, DEFAULT_CHART_FONT_SIZES as j, renderEchartFallback as k, MAX_CONDITION_DEPTH as l, UI_CATALOG_GROUPS as m, interactionToUiSpec as n, SPEC_TABLE_MIN_COLUMN_WIDTH as o, qualifyFieldName as p, toJsonRenderSpec as r, normalizeColumnWidths as s, toOpenUiSpecLang as t, evaluateFieldCondition as u, CATALOG_BUDGET_STAGE as v, mountEchartOption as w, PLANNED_INCREMENT as x, CATALOG_PROMPT_MAX as y };
@@ -86,16 +86,19 @@ function extractChartSpec(data) {
86
86
  const raw = data["$chart"];
87
87
  if (!isRecord(raw)) return void 0;
88
88
  const { kind, labels, series } = raw;
89
- if (kind !== "bar" && kind !== "line" && kind !== "pie") return void 0;
89
+ if (kind !== "bar" && kind !== "line" && kind !== "pie" && kind !== "bar-line") return void 0;
90
90
  if (!Array.isArray(labels) || !labels.every((l) => typeof l === "string")) return void 0;
91
91
  if (!Array.isArray(series)) return void 0;
92
92
  const validSeries = [];
93
93
  for (const item of series) {
94
94
  if (!isRecord(item) || !Array.isArray(item["data"]) || !item["data"].every((n) => typeof n === "number")) return;
95
95
  const name = item["name"];
96
+ const type = item["type"];
97
+ if (type !== void 0 && type !== "bar" && type !== "line") return void 0;
96
98
  validSeries.push({
97
99
  ...typeof name === "string" ? { name } : {},
98
- data: item["data"]
100
+ data: item["data"],
101
+ ...type === "bar" || type === "line" ? { type } : {}
99
102
  });
100
103
  }
101
104
  const title = raw["title"];
@@ -1,4 +1,4 @@
1
- import { K as FileSystemProvider, St as SkillManifest, et as Page, ht as SkillCatalogEntry, tt as PageQuery } from "./types-CpDRZ0rA-CFQ-vdKz.js";
1
+ import { K as FileSystemProvider, St as SkillManifest, et as Page, ht as SkillCatalogEntry, tt as PageQuery } from "./types-wKp3YBSM-167azx1H.js";
2
2
  //#region ../governance/dist/skillVersionStore-S4_HJ_Fl.d.ts
3
3
  //#region src/types.d.ts
4
4
  type CandidateStatus = 'draft' | 'pending-review' | 'approved' | 'published' | 'rejected';
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as UiBridge, c as InteractionResponse, l as LlmClient, m as LlmStreamEvent, n as ArtifactStore, p as LlmResponse, s as InteractionRequest, t as Artifact, u as LlmCompleteInput, v as MemoryStore } from "./types-CpDRZ0rA-CFQ-vdKz.js";
1
+ import { S as UiBridge, c as InteractionResponse, l as LlmClient, m as LlmStreamEvent, n as ArtifactStore, p as LlmResponse, s as InteractionRequest, t as Artifact, u as LlmCompleteInput, v as MemoryStore } from "./types-wKp3YBSM-167azx1H.js";
2
2
  import { a as loadGoogleConfigFromEnv, i as loadAnthropicConfigFromEnv, n as LlmEnvConfig, o as loadLlmConfigFromEnv, r as ProviderEnvConfig } from "./env-AK3cSMEA-Dli6QU5E.js";
3
3
  //#region ../runtime/dist/testing.d.ts
4
4
  //#region src/llm/mockLlmClient.d.ts
@@ -245,6 +245,8 @@ interface FileSystemProvider {
245
245
  * 只是内存峰值回到全量读取的水平(FR-18.2b)。
246
246
  */
247
247
  createWriteStream?(path: string): Promise<FileWriteStream>;
248
+ /** 可选:分块读取。每次调用返回一个独立游标,供大文件重复扫描;缺省时调用方回退到 readBinary。 */
249
+ createReadStream?(path: string): Promise<AsyncIterable<Uint8Array>>;
248
250
  exists(path: string): Promise<boolean>;
249
251
  stat(path: string): Promise<FileStat>;
250
252
  list(path: string): Promise<FileStat[]>;
@@ -388,6 +390,7 @@ declare class MemoryFS implements FileSystemProvider {
388
390
  writeText(path: string, content: string): Promise<void>;
389
391
  appendText(path: string, content: string): Promise<void>;
390
392
  readBinary(path: string): Promise<Uint8Array>;
393
+ createReadStream(path: string): Promise<AsyncIterable<Uint8Array>>;
391
394
  writeBinary(path: string, content: Uint8Array): Promise<void>;
392
395
  /**
393
396
  * 分块写入(FR-18.2c)。内存实现只能先攒着,`close()` 时才合并落表——
@@ -803,7 +806,7 @@ declare function escapeXml(text: string): string;
803
806
  declare function renderAvailableSkillsXml(catalog: SkillCatalog): string;
804
807
  declare const xmlRenderer: CatalogRenderer;
805
808
  //#endregion
806
- //#region ../runtime/dist/types-CpDRZ0rA.d.ts
809
+ //#region ../runtime/dist/types-wKp3YBSM.d.ts
807
810
  //#region src/llm/streamTypes.d.ts
808
811
  /** 流式 LLM 事件(OpenAI SSE / Vercel fullStream 统一映射) */
809
812
  type LlmStreamEvent = {
@@ -1085,12 +1088,13 @@ interface InteractionSuggestion {
1085
1088
  /** 图表规格($chart 约定的校验后形态;渲染单一来源在 ui/chart/miniChart) */
1086
1089
  interface ChartSpec {
1087
1090
  /** 取值与 catalog `Chart` 的 props 枚举逐字一致(`ui/catalog/uiCatalog.ts`) */
1088
- kind: 'bar' | 'line' | 'area' | 'pie' | 'scatter' | 'stacked-bar' | 'dual-axis';
1091
+ kind: 'bar' | 'line' | 'area' | 'pie' | 'scatter' | 'stacked-bar' | 'dual-axis' | 'bar-line';
1089
1092
  title?: string;
1090
1093
  labels: string[];
1091
1094
  series: Array<{
1092
1095
  name?: string;
1093
1096
  data: number[];
1097
+ type?: 'bar' | 'line';
1094
1098
  }>;
1095
1099
  }
1096
1100
  type RenderBlock = {
@@ -1,6 +1,6 @@
1
- import { C as UiSpecActionCapability, D as UiSpecSnapshot, Nt as UiSpecNode, O as UiSurfaceActionRequest, S as UiBridge, T as UiSpecEvent, b as RenderResultRequest, c as InteractionResponse, k as UiSurfaceActionResponse, s as InteractionRequest, w as UiSpecDrafts } from "./types-CpDRZ0rA-CFQ-vdKz.js";
2
- import { P as DocumentSurfacePort } from "./index-D6eSrEi5.js";
3
- import { L as InteractionSpecLabels, X as SurfaceFormTexts, Z as SurfaceHostControlTexts, v as ChartColors, y as ChartFontSizes } from "./index-C8-9-8zo.js";
1
+ import { C as UiSpecActionCapability, D as UiSpecSnapshot, Nt as UiSpecNode, O as UiSurfaceActionRequest, S as UiBridge, T as UiSpecEvent, b as RenderResultRequest, c as InteractionResponse, k as UiSurfaceActionResponse, s as InteractionRequest, w as UiSpecDrafts } from "./types-wKp3YBSM-167azx1H.js";
2
+ import { P as DocumentSurfacePort } from "./index-DU8sKyQq.js";
3
+ import { H as InteractionSpecLabels, nt as SurfaceFormTexts, rt as SurfaceHostControlTexts, v as ChartColors, y as ChartFontSizes } from "./index-DJeYqzlE.js";
4
4
  import { z } from "zod";
5
5
  import React$1, { ComponentType, ReactNode } from "react";
6
6
  import "react/jsx-runtime";