@webskill/sdk 0.7.0 → 0.8.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.
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/browser.d.ts +151 -4
- package/dist/browser.js +250 -25
- package/dist/{catalogComponents-Dr5dFMAb-DKH_7VPI.js → catalogComponents-DfxxfUvn-D55Gbb2l.js} +3435 -437
- package/dist/{dist-8oQRa8Xz.js → dist-59XlqDuv.js} +93 -6
- package/dist/{dist-DnYG2-eY.js → dist-CJqQsIm9.js} +498 -118
- package/dist/{dist-D0qW6e40.js → dist-DmI5SBBF.js} +192 -17
- package/dist/{eventTypes-DjIQpt8Y-Bj3vghj4.js → eventTypes-g1BXL6x5-CibcOftR.js} +7 -2
- package/dist/governance.d.ts +16 -3
- package/dist/governance.js +24 -5
- package/dist/{index-DkbABR43.d.ts → index-K-eewlGL.d.ts} +138 -75
- package/dist/{index-BwsK9lGk.d.ts → index-P9J2LTfU.d.ts} +163 -6
- package/dist/{index-Ba3xFtfz.d.ts → index-fLskQfAS.d.ts} +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/mcp.d.ts +8 -2
- package/dist/mcp.js +12 -2
- package/dist/{memoryArtifactStore-52Zn9npI-BMPYwvoy.js → memoryArtifactStore-52Zn9npI-upv5OWYf.js} +1 -1
- package/dist/node.d.ts +3 -3
- package/dist/node.js +3 -3
- package/dist/{openUiLibrary-Bdrji9qK-D2LxmM-a.js → openUiLibrary-DURlAxjk-CU6AzfSW.js} +3 -3
- package/dist/{skillVersionStore-Bl-ElD45-CWPvGvoq.d.ts → skillVersionStore-Bl-ElD45-gRfSaAby.d.ts} +1 -1
- package/dist/{testing-CYTFqkDm.js → testing-BCUO5gZR.js} +2 -2
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +2 -2
- package/dist/{types-CcxRLdJG-DCXyw1US.d.ts → types-B3n0cMZu-BdcqQ35O.d.ts} +46 -6
- package/dist/ui-react.d.ts +13 -6
- package/dist/ui-react.js +153 -84
- package/dist/ui-vue.d.ts +1 -1
- package/dist/ui-vue.js +2 -2
- package/dist/ui.d.ts +4 -4
- package/dist/ui.js +3 -3
- package/dist/{webskillLitCatalog-_mugzRHx-B_54vxum.js → webskillLitCatalog-DwTwSBFt-DiXXpNZA.js} +22 -3
- package/package.json +2 -2
|
@@ -1,7 +1,137 @@
|
|
|
1
|
-
import { m as WebSkillError } from "./dist-
|
|
1
|
+
import { m as WebSkillError } from "./dist-59XlqDuv.js";
|
|
2
2
|
import { toJSONSchema, z } from "zod";
|
|
3
3
|
|
|
4
|
-
//#region ../ui/dist/webskillCatalog-
|
|
4
|
+
//#region ../ui/dist/webskillCatalog-CKM0bu47.js
|
|
5
|
+
const DEFAULT_INTERACTION_TEXTS = {
|
|
6
|
+
submit: "Submit",
|
|
7
|
+
cancel: "Cancel",
|
|
8
|
+
confirm: "Confirm",
|
|
9
|
+
select: "Select",
|
|
10
|
+
allow: "Allow",
|
|
11
|
+
deny: "Deny",
|
|
12
|
+
chooseFile: "Choose file",
|
|
13
|
+
decline: "Decline",
|
|
14
|
+
required: "This field is required",
|
|
15
|
+
suggested: "Suggested:",
|
|
16
|
+
useSuggestion: "Use"
|
|
17
|
+
};
|
|
18
|
+
function resolveInteractionTexts(texts) {
|
|
19
|
+
return texts ? {
|
|
20
|
+
...DEFAULT_INTERACTION_TEXTS,
|
|
21
|
+
...texts
|
|
22
|
+
} : DEFAULT_INTERACTION_TEXTS;
|
|
23
|
+
}
|
|
24
|
+
/** 可复用的部分取自 DEFAULT_INTERACTION_TEXTS,不另抄一份(AC-G10) */
|
|
25
|
+
const DEFAULT_SURFACE_FORM_TEXTS = {
|
|
26
|
+
required: DEFAULT_INTERACTION_TEXTS.required,
|
|
27
|
+
submit: DEFAULT_INTERACTION_TEXTS.submit,
|
|
28
|
+
cancel: DEFAULT_INTERACTION_TEXTS.cancel,
|
|
29
|
+
addItem: "Add",
|
|
30
|
+
removeItem: "Remove",
|
|
31
|
+
arrayFirstItemOnly: "This renderer shows only the first item of a repeatable group.",
|
|
32
|
+
readOnlySnapshot: "This is a saved record — its actions are no longer available."
|
|
33
|
+
};
|
|
34
|
+
function resolveSurfaceFormTexts(texts) {
|
|
35
|
+
return texts ? {
|
|
36
|
+
...DEFAULT_SURFACE_FORM_TEXTS,
|
|
37
|
+
...texts
|
|
38
|
+
} : DEFAULT_SURFACE_FORM_TEXTS;
|
|
39
|
+
}
|
|
40
|
+
/** 提交值按请求类型归形(WebFormBridge 与框架组件库共享单一来源) */
|
|
41
|
+
function shapeInteractionValue(model, values) {
|
|
42
|
+
switch (model.kind) {
|
|
43
|
+
case "ask": return values["answer"];
|
|
44
|
+
case "confirm": return values["confirmed"] === true;
|
|
45
|
+
case "select": return values["selected"];
|
|
46
|
+
case "authorize": return true;
|
|
47
|
+
case "file-pick": return values["file"];
|
|
48
|
+
case "form": return values;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** 五类 InteractionRequest → 统一中间模型(框架无关) */
|
|
52
|
+
function interactionToFormModel(request, texts) {
|
|
53
|
+
const t = resolveInteractionTexts(texts);
|
|
54
|
+
switch (request.type) {
|
|
55
|
+
case "ask": return {
|
|
56
|
+
kind: "ask",
|
|
57
|
+
message: request.message,
|
|
58
|
+
controls: [{
|
|
59
|
+
name: "answer",
|
|
60
|
+
label: request.message,
|
|
61
|
+
control: "text",
|
|
62
|
+
required: true,
|
|
63
|
+
...request.suggestion ? { suggestion: request.suggestion } : {}
|
|
64
|
+
}],
|
|
65
|
+
submitLabel: t.submit,
|
|
66
|
+
cancelLabel: t.cancel
|
|
67
|
+
};
|
|
68
|
+
case "confirm": return {
|
|
69
|
+
kind: "confirm",
|
|
70
|
+
message: request.message,
|
|
71
|
+
controls: [{
|
|
72
|
+
name: "confirmed",
|
|
73
|
+
label: request.message,
|
|
74
|
+
control: "boolean",
|
|
75
|
+
defaultValue: request.defaultValue ?? true
|
|
76
|
+
}],
|
|
77
|
+
submitLabel: t.confirm,
|
|
78
|
+
cancelLabel: t.cancel
|
|
79
|
+
};
|
|
80
|
+
case "form": return {
|
|
81
|
+
kind: "form",
|
|
82
|
+
...request.title ? { title: request.title } : {},
|
|
83
|
+
controls: request.fields.map((f) => ({
|
|
84
|
+
name: f.name,
|
|
85
|
+
label: f.label,
|
|
86
|
+
control: f.type,
|
|
87
|
+
...f.required ? { required: true } : {},
|
|
88
|
+
...f.description ? { description: f.description } : {},
|
|
89
|
+
...f.defaultValue !== void 0 ? { defaultValue: f.defaultValue } : {},
|
|
90
|
+
...f.suggestion ? { suggestion: f.suggestion } : {},
|
|
91
|
+
...f.options ? { options: f.options } : {}
|
|
92
|
+
})),
|
|
93
|
+
submitLabel: t.submit,
|
|
94
|
+
cancelLabel: t.cancel
|
|
95
|
+
};
|
|
96
|
+
case "select": return {
|
|
97
|
+
kind: "select",
|
|
98
|
+
message: request.message,
|
|
99
|
+
controls: [{
|
|
100
|
+
name: "selected",
|
|
101
|
+
label: request.message,
|
|
102
|
+
control: "select",
|
|
103
|
+
required: true,
|
|
104
|
+
options: request.options,
|
|
105
|
+
...request.suggestion ? { suggestion: request.suggestion } : {}
|
|
106
|
+
}],
|
|
107
|
+
submitLabel: t.select,
|
|
108
|
+
cancelLabel: t.cancel
|
|
109
|
+
};
|
|
110
|
+
case "authorize": return {
|
|
111
|
+
kind: "authorize",
|
|
112
|
+
title: "Authorization required",
|
|
113
|
+
message: request.message,
|
|
114
|
+
controls: [],
|
|
115
|
+
submitLabel: t.allow,
|
|
116
|
+
cancelLabel: t.deny
|
|
117
|
+
};
|
|
118
|
+
case "file-pick": return {
|
|
119
|
+
kind: "file-pick",
|
|
120
|
+
title: "File requested",
|
|
121
|
+
message: request.message,
|
|
122
|
+
controls: [{
|
|
123
|
+
name: "file",
|
|
124
|
+
label: request.field ?? "file",
|
|
125
|
+
control: "file",
|
|
126
|
+
required: true,
|
|
127
|
+
...request.accept ? { accept: request.accept } : {},
|
|
128
|
+
...request.multiple ? { multiple: true } : {}
|
|
129
|
+
}],
|
|
130
|
+
submitLabel: t.chooseFile,
|
|
131
|
+
cancelLabel: t.decline
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
5
135
|
/**
|
|
6
136
|
* 最小子集 markdown → DOM:标题(#..###)、无序列表、代码块(```)、加粗、链接。
|
|
7
137
|
* 全部内容经 textContent 写入,用户内容天然转义防 HTML 注入。
|
|
@@ -192,6 +322,139 @@ function mountEchart(container) {
|
|
|
192
322
|
}
|
|
193
323
|
};
|
|
194
324
|
}
|
|
325
|
+
function isRecord$1$1(value) {
|
|
326
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* 逐节点降级(FR-23.3)。
|
|
330
|
+
*
|
|
331
|
+
* 与 `validate` 的关系见 `UiCatalog.sanitize` 的注释:一个整块拒绝、一个逐节点救。
|
|
332
|
+
*
|
|
333
|
+
* **不写回 `safeParse` 的结果**是刻意的:zod 会剥离未声明的键,
|
|
334
|
+
* 而渲染层确实在读若干未进 zod 的 prop(如 `suggestion`,由 SDK 侧下发而非模型生成)。
|
|
335
|
+
* 写回等于把它们悄悄删掉。这里只删「确实解析失败」的那几个键。
|
|
336
|
+
*/
|
|
337
|
+
function sanitizeNode(catalog, byName, node, path, degradations) {
|
|
338
|
+
if (!isRecord$1$1(node)) {
|
|
339
|
+
degradations.push({
|
|
340
|
+
path,
|
|
341
|
+
kind: "node-dropped",
|
|
342
|
+
component: "unknown",
|
|
343
|
+
detail: "Node is not an object."
|
|
344
|
+
});
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
const name = node["component"];
|
|
348
|
+
if (typeof name !== "string") {
|
|
349
|
+
degradations.push({
|
|
350
|
+
path,
|
|
351
|
+
kind: "node-dropped",
|
|
352
|
+
component: "unknown",
|
|
353
|
+
detail: "Node has no \"component\" name."
|
|
354
|
+
});
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const def = byName.get(name);
|
|
358
|
+
if (!def) {
|
|
359
|
+
degradations.push({
|
|
360
|
+
path,
|
|
361
|
+
kind: "unknown-component",
|
|
362
|
+
component: name,
|
|
363
|
+
detail: `Unknown component "${name}"; the catalog declares: ${catalog.components.map((c) => c.name).join(", ")}`
|
|
364
|
+
});
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const rawProps = isRecord$1$1(node["props"]) ? node["props"] : {};
|
|
368
|
+
let props = rawProps;
|
|
369
|
+
const parsed = def.props.safeParse(rawProps);
|
|
370
|
+
if (!parsed.success) {
|
|
371
|
+
const offending = new Set(parsed.error.issues.map((issue) => String(issue.path[0] ?? "")).filter((key) => key !== ""));
|
|
372
|
+
const kept = {};
|
|
373
|
+
for (const [key, value] of Object.entries(rawProps)) if (!offending.has(key)) kept[key] = value;
|
|
374
|
+
const retry = def.props.safeParse(kept);
|
|
375
|
+
if (!retry.success) {
|
|
376
|
+
degradations.push({
|
|
377
|
+
path,
|
|
378
|
+
kind: "node-dropped",
|
|
379
|
+
component: name,
|
|
380
|
+
detail: `Props cannot be repaired by dropping invalid keys: ${retry.error.issues.map((i) => i.message).join("; ")}`
|
|
381
|
+
});
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
for (const key of offending) degradations.push({
|
|
385
|
+
path: `${path}.props.${key}`,
|
|
386
|
+
kind: "prop-dropped",
|
|
387
|
+
component: name,
|
|
388
|
+
detail: `Dropped invalid prop "${key}".`
|
|
389
|
+
});
|
|
390
|
+
props = kept;
|
|
391
|
+
}
|
|
392
|
+
const sanitized = {
|
|
393
|
+
component: name,
|
|
394
|
+
props
|
|
395
|
+
};
|
|
396
|
+
if (typeof node["id"] === "string") sanitized.id = node["id"];
|
|
397
|
+
const children = node["children"];
|
|
398
|
+
if (children === void 0) return sanitized;
|
|
399
|
+
if (!Array.isArray(children)) {
|
|
400
|
+
degradations.push({
|
|
401
|
+
path: `${path}.children`,
|
|
402
|
+
kind: "constraint-ignored",
|
|
403
|
+
component: name,
|
|
404
|
+
detail: "children is not an array; rendered without children."
|
|
405
|
+
});
|
|
406
|
+
return sanitized;
|
|
407
|
+
}
|
|
408
|
+
if (def.children === void 0) {
|
|
409
|
+
degradations.push({
|
|
410
|
+
path: `${path}.children`,
|
|
411
|
+
kind: "constraint-ignored",
|
|
412
|
+
component: name,
|
|
413
|
+
detail: `Component "${name}" is a leaf; its children were dropped.`
|
|
414
|
+
});
|
|
415
|
+
return sanitized;
|
|
416
|
+
}
|
|
417
|
+
const allowed = def.children;
|
|
418
|
+
const singletons = /* @__PURE__ */ new Map();
|
|
419
|
+
const kept = [];
|
|
420
|
+
children.forEach((child, index) => {
|
|
421
|
+
const childPath = `${path}.children[${index}]`;
|
|
422
|
+
const childName = isRecord$1$1(child) && typeof child["component"] === "string" ? child["component"] : void 0;
|
|
423
|
+
if (allowed !== "any" && childName !== void 0 && !allowed.includes(childName)) {
|
|
424
|
+
degradations.push({
|
|
425
|
+
path: childPath,
|
|
426
|
+
kind: byName.has(childName) ? "node-dropped" : "unknown-component",
|
|
427
|
+
component: childName,
|
|
428
|
+
detail: byName.has(childName) ? `Component "${name}" only accepts children: ${[...allowed].join(", ")}` : `Unknown component "${childName}"; the catalog declares: ${catalog.components.map((c) => c.name).join(", ")}`
|
|
429
|
+
});
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
if (childName !== void 0 && byName.get(childName)?.singletonPerContainer === true) {
|
|
433
|
+
const seen = (singletons.get(childName) ?? 0) + 1;
|
|
434
|
+
singletons.set(childName, seen);
|
|
435
|
+
if (seen > 1) {
|
|
436
|
+
degradations.push({
|
|
437
|
+
path: childPath,
|
|
438
|
+
kind: "node-dropped",
|
|
439
|
+
component: childName,
|
|
440
|
+
detail: `At most one "${childName}" per container; the extra one was dropped.`
|
|
441
|
+
});
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
const sanitizedChild = sanitizeNode(catalog, byName, child, childPath, degradations);
|
|
446
|
+
if (sanitizedChild) kept.push(sanitizedChild);
|
|
447
|
+
});
|
|
448
|
+
sanitized.children = kept;
|
|
449
|
+
return sanitized;
|
|
450
|
+
}
|
|
451
|
+
function sanitizeUiSpec(catalog, byName, spec) {
|
|
452
|
+
const degradations = [];
|
|
453
|
+
return {
|
|
454
|
+
node: sanitizeNode(catalog, byName, spec, "root", degradations),
|
|
455
|
+
degradations
|
|
456
|
+
};
|
|
457
|
+
}
|
|
195
458
|
function componentSchema(def) {
|
|
196
459
|
const props = toJSONSchema(def.props, { io: "input" });
|
|
197
460
|
const node = {
|
|
@@ -220,7 +483,7 @@ function componentSchema(def) {
|
|
|
220
483
|
};
|
|
221
484
|
return node;
|
|
222
485
|
}
|
|
223
|
-
function isRecord$
|
|
486
|
+
function isRecord$2(value) {
|
|
224
487
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
225
488
|
}
|
|
226
489
|
function typeOf(schema) {
|
|
@@ -260,7 +523,7 @@ function promptFor(catalog, options) {
|
|
|
260
523
|
return lines.join("\n").trimEnd();
|
|
261
524
|
}
|
|
262
525
|
function validateNode(catalog, byName, node, path, issues) {
|
|
263
|
-
if (!isRecord$
|
|
526
|
+
if (!isRecord$2(node)) {
|
|
264
527
|
issues.push({
|
|
265
528
|
path,
|
|
266
529
|
message: "Node must be an object"
|
|
@@ -308,7 +571,7 @@ function validateNode(catalog, byName, node, path, issues) {
|
|
|
308
571
|
const singletons = /* @__PURE__ */ new Map();
|
|
309
572
|
children.forEach((child, index) => {
|
|
310
573
|
const childPath = `${path}.children[${index}]`;
|
|
311
|
-
if (allowed !== "any" && isRecord$
|
|
574
|
+
if (allowed !== "any" && isRecord$2(child) && typeof child["component"] === "string") {
|
|
312
575
|
if (!allowed.includes(child["component"])) {
|
|
313
576
|
issues.push({
|
|
314
577
|
path: childPath,
|
|
@@ -317,7 +580,7 @@ function validateNode(catalog, byName, node, path, issues) {
|
|
|
317
580
|
return;
|
|
318
581
|
}
|
|
319
582
|
}
|
|
320
|
-
if (isRecord$
|
|
583
|
+
if (isRecord$2(child) && typeof child["component"] === "string") {
|
|
321
584
|
const childName = child["component"];
|
|
322
585
|
if (byName.get(childName)?.singletonPerContainer === true) {
|
|
323
586
|
const seen = (singletons.get(childName) ?? 0) + 1;
|
|
@@ -362,7 +625,8 @@ function defineUiCatalog(input) {
|
|
|
362
625
|
ok: false,
|
|
363
626
|
issues
|
|
364
627
|
};
|
|
365
|
-
}
|
|
628
|
+
},
|
|
629
|
+
sanitize: (spec) => sanitizeUiSpec(input, byName, spec)
|
|
366
630
|
};
|
|
367
631
|
}
|
|
368
632
|
const tone = z.enum([
|
|
@@ -397,8 +661,38 @@ const DATA = [
|
|
|
397
661
|
const INPUT = [
|
|
398
662
|
"Form",
|
|
399
663
|
"Field",
|
|
664
|
+
"FieldArray",
|
|
400
665
|
"Button"
|
|
401
666
|
];
|
|
667
|
+
/**
|
|
668
|
+
* `visibleWhen` 的结构化条件(设计 23 §1.2)。用 `z.lazy` 自引用;
|
|
669
|
+
* 语义深度上限不在 zod 里卡,由 `evaluateFieldCondition` 按 `MAX_CONDITION_DEPTH` 降级处理。
|
|
670
|
+
*/
|
|
671
|
+
const fieldCondition = z.lazy(() => z.union([
|
|
672
|
+
z.object({
|
|
673
|
+
field: z.string(),
|
|
674
|
+
equals: z.union([
|
|
675
|
+
z.string(),
|
|
676
|
+
z.number(),
|
|
677
|
+
z.boolean()
|
|
678
|
+
])
|
|
679
|
+
}),
|
|
680
|
+
z.object({
|
|
681
|
+
field: z.string(),
|
|
682
|
+
in: z.array(z.union([z.string(), z.number()]))
|
|
683
|
+
}),
|
|
684
|
+
z.object({
|
|
685
|
+
field: z.string(),
|
|
686
|
+
notEmpty: z.literal(true)
|
|
687
|
+
}),
|
|
688
|
+
z.object({ allOf: z.array(fieldCondition).min(1) }),
|
|
689
|
+
z.object({ anyOf: z.array(fieldCondition).min(1) })
|
|
690
|
+
]));
|
|
691
|
+
/** 选项既可以写死,也可以声明成异步取值(取值通道属分册 24) */
|
|
692
|
+
const fieldOptions = z.array(z.object({
|
|
693
|
+
label: z.string(),
|
|
694
|
+
value: z.union([z.string(), z.number()])
|
|
695
|
+
}));
|
|
402
696
|
/** Tabs 的面板与 Grid 的格子必须自成容器,否则「每容器至多一个表单」就没有落脚点 */
|
|
403
697
|
const PANEL = ["Card", "Stack"];
|
|
404
698
|
/**
|
|
@@ -634,13 +928,16 @@ const uiCatalog = defineUiCatalog({
|
|
|
634
928
|
group: "data",
|
|
635
929
|
description: "Tabular data with explicit columns. Prefer it over Markdown tables.",
|
|
636
930
|
props: z.object({
|
|
931
|
+
title: z.string().optional(),
|
|
637
932
|
columns: z.array(z.string()).min(1),
|
|
638
933
|
rows: z.array(z.array(z.union([
|
|
639
934
|
z.string(),
|
|
640
935
|
z.number(),
|
|
641
936
|
z.boolean(),
|
|
642
937
|
z.null()
|
|
643
|
-
])))
|
|
938
|
+
]))),
|
|
939
|
+
/** 列宽权重,长度需与 columns 一致;不一致时整项忽略而不拒绝渲染 */
|
|
940
|
+
columnWidths: z.array(z.number().positive()).optional()
|
|
644
941
|
}),
|
|
645
942
|
example: {
|
|
646
943
|
component: "Table",
|
|
@@ -738,7 +1035,7 @@ const uiCatalog = defineUiCatalog({
|
|
|
738
1035
|
submitLabel: z.string().default("Submit"),
|
|
739
1036
|
cancelLabel: z.string().optional()
|
|
740
1037
|
}),
|
|
741
|
-
children: ["Field"],
|
|
1038
|
+
children: ["Field", "FieldArray"],
|
|
742
1039
|
singletonPerContainer: true,
|
|
743
1040
|
constraints: ["At most one Form per container", "Every Field name must be unique inside the Form"],
|
|
744
1041
|
example: {
|
|
@@ -770,17 +1067,22 @@ const uiCatalog = defineUiCatalog({
|
|
|
770
1067
|
"select",
|
|
771
1068
|
"multi-select",
|
|
772
1069
|
"toggle",
|
|
773
|
-
"file"
|
|
1070
|
+
"file",
|
|
1071
|
+
"password"
|
|
774
1072
|
]),
|
|
775
1073
|
required: z.boolean().optional(),
|
|
776
1074
|
description: z.string().optional(),
|
|
777
1075
|
defaultValue: z.unknown().optional(),
|
|
778
|
-
options:
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
1076
|
+
options: fieldOptions.optional(),
|
|
1077
|
+
/** 声明后选项由宕主异步提供;与写死的 options 互斥 */
|
|
1078
|
+
optionsSource: z.string().optional(),
|
|
1079
|
+
visibleWhen: fieldCondition.optional()
|
|
782
1080
|
}),
|
|
783
|
-
constraints: [
|
|
1081
|
+
constraints: [
|
|
1082
|
+
"select / multi-select must provide options or optionsSource",
|
|
1083
|
+
"password values are never persisted, never echoed and never enter the user profile",
|
|
1084
|
+
"visibleWhen may only reference fields declared in the same Form"
|
|
1085
|
+
],
|
|
784
1086
|
example: {
|
|
785
1087
|
component: "Field",
|
|
786
1088
|
props: {
|
|
@@ -791,6 +1093,37 @@ const uiCatalog = defineUiCatalog({
|
|
|
791
1093
|
}
|
|
792
1094
|
}
|
|
793
1095
|
},
|
|
1096
|
+
{
|
|
1097
|
+
name: "FieldArray",
|
|
1098
|
+
group: "input",
|
|
1099
|
+
description: "A repeatable group of fields. Only valid inside a Form; children must be Field nodes.",
|
|
1100
|
+
props: z.object({
|
|
1101
|
+
name: z.string(),
|
|
1102
|
+
label: z.string(),
|
|
1103
|
+
minItems: z.number().int().min(0).optional(),
|
|
1104
|
+
maxItems: z.number().int().min(1).optional(),
|
|
1105
|
+
addLabel: z.string().optional(),
|
|
1106
|
+
removeLabel: z.string().optional()
|
|
1107
|
+
}),
|
|
1108
|
+
children: ["Field"],
|
|
1109
|
+
constraints: ["Only valid inside a Form", "Submitted as an array of objects keyed by the inner Field names"],
|
|
1110
|
+
example: {
|
|
1111
|
+
component: "FieldArray",
|
|
1112
|
+
props: {
|
|
1113
|
+
name: "recipients",
|
|
1114
|
+
label: "Recipients",
|
|
1115
|
+
minItems: 1
|
|
1116
|
+
},
|
|
1117
|
+
children: [{
|
|
1118
|
+
component: "Field",
|
|
1119
|
+
props: {
|
|
1120
|
+
name: "email",
|
|
1121
|
+
label: "Email",
|
|
1122
|
+
type: "text"
|
|
1123
|
+
}
|
|
1124
|
+
}]
|
|
1125
|
+
}
|
|
1126
|
+
},
|
|
794
1127
|
{
|
|
795
1128
|
name: "Button",
|
|
796
1129
|
group: "input",
|
|
@@ -935,7 +1268,7 @@ function a2uiComponentShapes(catalog) {
|
|
|
935
1268
|
childList: def.children !== void 0,
|
|
936
1269
|
...childrenDescription ? { childListDescription: childrenDescription } : {},
|
|
937
1270
|
actionProps: keys.filter((key) => key === ACTION_PROP),
|
|
938
|
-
valueProps: def.group === "input" && keys.includes(NAME_PROP) ? [A2UI_VALUE_PROP] : [],
|
|
1271
|
+
valueProps: def.group === "input" && def.children === void 0 && keys.includes(NAME_PROP) ? [A2UI_VALUE_PROP] : [],
|
|
939
1272
|
...keys.includes(SUBMIT_LABEL_PROP) ? { submitLabelProp: SUBMIT_LABEL_PROP } : {},
|
|
940
1273
|
...keys.includes(CANCEL_LABEL_PROP) ? { cancelLabelProp: CANCEL_LABEL_PROP } : {}
|
|
941
1274
|
};
|
|
@@ -985,101 +1318,7 @@ function buildA2uiCatalogDefinition(catalog) {
|
|
|
985
1318
|
|
|
986
1319
|
//#endregion
|
|
987
1320
|
//#region ../ui/dist/index.js
|
|
988
|
-
|
|
989
|
-
function shapeInteractionValue(model, values) {
|
|
990
|
-
switch (model.kind) {
|
|
991
|
-
case "ask": return values["answer"];
|
|
992
|
-
case "confirm": return values["confirmed"] === true;
|
|
993
|
-
case "select": return values["selected"];
|
|
994
|
-
case "authorize": return true;
|
|
995
|
-
case "file-pick": return values["file"];
|
|
996
|
-
case "form": return values;
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
/** 五类 InteractionRequest → 统一中间模型(框架无关) */
|
|
1000
|
-
function interactionToFormModel(request) {
|
|
1001
|
-
switch (request.type) {
|
|
1002
|
-
case "ask": return {
|
|
1003
|
-
kind: "ask",
|
|
1004
|
-
message: request.message,
|
|
1005
|
-
controls: [{
|
|
1006
|
-
name: "answer",
|
|
1007
|
-
label: request.message,
|
|
1008
|
-
control: "text",
|
|
1009
|
-
required: true,
|
|
1010
|
-
...request.suggestion ? { suggestion: request.suggestion } : {}
|
|
1011
|
-
}],
|
|
1012
|
-
submitLabel: "Submit",
|
|
1013
|
-
cancelLabel: "Cancel"
|
|
1014
|
-
};
|
|
1015
|
-
case "confirm": return {
|
|
1016
|
-
kind: "confirm",
|
|
1017
|
-
message: request.message,
|
|
1018
|
-
controls: [{
|
|
1019
|
-
name: "confirmed",
|
|
1020
|
-
label: request.message,
|
|
1021
|
-
control: "boolean",
|
|
1022
|
-
defaultValue: request.defaultValue ?? true
|
|
1023
|
-
}],
|
|
1024
|
-
submitLabel: "Confirm",
|
|
1025
|
-
cancelLabel: "Cancel"
|
|
1026
|
-
};
|
|
1027
|
-
case "form": return {
|
|
1028
|
-
kind: "form",
|
|
1029
|
-
...request.title ? { title: request.title } : {},
|
|
1030
|
-
controls: request.fields.map((f) => ({
|
|
1031
|
-
name: f.name,
|
|
1032
|
-
label: f.label,
|
|
1033
|
-
control: f.type,
|
|
1034
|
-
...f.required ? { required: true } : {},
|
|
1035
|
-
...f.description ? { description: f.description } : {},
|
|
1036
|
-
...f.defaultValue !== void 0 ? { defaultValue: f.defaultValue } : {},
|
|
1037
|
-
...f.suggestion ? { suggestion: f.suggestion } : {},
|
|
1038
|
-
...f.options ? { options: f.options } : {}
|
|
1039
|
-
})),
|
|
1040
|
-
submitLabel: "Submit",
|
|
1041
|
-
cancelLabel: "Cancel"
|
|
1042
|
-
};
|
|
1043
|
-
case "select": return {
|
|
1044
|
-
kind: "select",
|
|
1045
|
-
message: request.message,
|
|
1046
|
-
controls: [{
|
|
1047
|
-
name: "selected",
|
|
1048
|
-
label: request.message,
|
|
1049
|
-
control: "select",
|
|
1050
|
-
required: true,
|
|
1051
|
-
options: request.options,
|
|
1052
|
-
...request.suggestion ? { suggestion: request.suggestion } : {}
|
|
1053
|
-
}],
|
|
1054
|
-
submitLabel: "Select",
|
|
1055
|
-
cancelLabel: "Cancel"
|
|
1056
|
-
};
|
|
1057
|
-
case "authorize": return {
|
|
1058
|
-
kind: "authorize",
|
|
1059
|
-
title: "Authorization required",
|
|
1060
|
-
message: request.message,
|
|
1061
|
-
controls: [],
|
|
1062
|
-
submitLabel: "Allow",
|
|
1063
|
-
cancelLabel: "Deny"
|
|
1064
|
-
};
|
|
1065
|
-
case "file-pick": return {
|
|
1066
|
-
kind: "file-pick",
|
|
1067
|
-
title: "File requested",
|
|
1068
|
-
message: request.message,
|
|
1069
|
-
controls: [{
|
|
1070
|
-
name: "file",
|
|
1071
|
-
label: request.field ?? "file",
|
|
1072
|
-
control: "file",
|
|
1073
|
-
required: true,
|
|
1074
|
-
...request.accept ? { accept: request.accept } : {},
|
|
1075
|
-
...request.multiple ? { multiple: true } : {}
|
|
1076
|
-
}],
|
|
1077
|
-
submitLabel: "Choose file",
|
|
1078
|
-
cancelLabel: "Decline"
|
|
1079
|
-
};
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
const isEmpty = (v) => v === void 0 || v === "";
|
|
1321
|
+
const isEmpty$1 = (v) => v === void 0 || v === "";
|
|
1083
1322
|
/**
|
|
1084
1323
|
* 控件名 → 属性选择器:优先 CSS.escape(标识符形式,免引号转义);
|
|
1085
1324
|
* 无 CSS.escape 的环境退化为引号包裹 + 转义反斜杠/双引号(防选择器注入崩溃)
|
|
@@ -1118,7 +1357,7 @@ function collectValues(controls, container) {
|
|
|
1118
1357
|
value = raw === "" ? void 0 : raw;
|
|
1119
1358
|
}
|
|
1120
1359
|
values[control.name] = value;
|
|
1121
|
-
if (control.required && isEmpty(value)) missingRequired.push(control.name);
|
|
1360
|
+
if (control.required && isEmpty$1(value)) missingRequired.push(control.name);
|
|
1122
1361
|
}
|
|
1123
1362
|
return {
|
|
1124
1363
|
values,
|
|
@@ -1489,17 +1728,21 @@ var WebFormBridge = class {
|
|
|
1489
1728
|
#doc;
|
|
1490
1729
|
#styles;
|
|
1491
1730
|
#progressEl;
|
|
1731
|
+
#texts;
|
|
1732
|
+
#interactionTexts;
|
|
1492
1733
|
/** 等待中的 request 取消句柄(id → 触发 cancelled 并卸载 DOM) */
|
|
1493
1734
|
#pending = /* @__PURE__ */ new Map();
|
|
1494
1735
|
constructor(options) {
|
|
1495
1736
|
this.#mount = options.mount;
|
|
1496
1737
|
this.#doc = options.document ?? options.mount.ownerDocument;
|
|
1497
1738
|
this.#styles = options.styles ?? true;
|
|
1739
|
+
this.#interactionTexts = options.texts;
|
|
1740
|
+
this.#texts = resolveSurfaceFormTexts(options.texts);
|
|
1498
1741
|
}
|
|
1499
1742
|
request(input) {
|
|
1500
1743
|
if (this.#styles) ensureStyles(this.#doc);
|
|
1501
1744
|
this.#clearProgress();
|
|
1502
|
-
const model = interactionToFormModel(input);
|
|
1745
|
+
const model = interactionToFormModel(input, this.#interactionTexts);
|
|
1503
1746
|
const { form, cleanup } = this.#renderForm(model);
|
|
1504
1747
|
return new Promise((resolve) => {
|
|
1505
1748
|
const cancel = () => {
|
|
@@ -1655,7 +1898,7 @@ var WebFormBridge = class {
|
|
|
1655
1898
|
error.className = "webskill-form__error";
|
|
1656
1899
|
error.id = errorId;
|
|
1657
1900
|
error.setAttribute("role", "alert");
|
|
1658
|
-
error.textContent =
|
|
1901
|
+
error.textContent = this.#texts.required;
|
|
1659
1902
|
wrapper.appendChild(error);
|
|
1660
1903
|
return wrapper;
|
|
1661
1904
|
}
|
|
@@ -1758,6 +2001,142 @@ function collectScopedValues(values, scope) {
|
|
|
1758
2001
|
}
|
|
1759
2002
|
return out;
|
|
1760
2003
|
}
|
|
2004
|
+
/**
|
|
2005
|
+
* 条件树的语义深度上限。
|
|
2006
|
+
* `MAX_JSON_DEPTH` 管的是 props 的 JSON 深度,管不到这里——超它之前就能先把栈打爆。
|
|
2007
|
+
*/
|
|
2008
|
+
const MAX_CONDITION_DEPTH = 8;
|
|
2009
|
+
const isRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2010
|
+
const isEmpty = (value) => value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
|
|
2011
|
+
function invalid(path, detail) {
|
|
2012
|
+
return {
|
|
2013
|
+
visible: true,
|
|
2014
|
+
degraded: {
|
|
2015
|
+
path,
|
|
2016
|
+
kind: "condition-invalid",
|
|
2017
|
+
detail
|
|
2018
|
+
}
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
2021
|
+
function evaluate(condition, context, depth) {
|
|
2022
|
+
if (depth > 8) return invalid(context.path, `Condition nesting exceeds 8 levels.`);
|
|
2023
|
+
if (!isRecord$1(condition)) return invalid(context.path, "Condition must be an object.");
|
|
2024
|
+
if (Array.isArray(condition["allOf"]) || Array.isArray(condition["anyOf"])) {
|
|
2025
|
+
const isAll = Array.isArray(condition["allOf"]);
|
|
2026
|
+
const branches = isAll ? condition["allOf"] : condition["anyOf"];
|
|
2027
|
+
if (branches.length === 0) return invalid(context.path, `"${isAll ? "allOf" : "anyOf"}" must not be empty.`);
|
|
2028
|
+
let visible = isAll;
|
|
2029
|
+
for (const branch of branches) {
|
|
2030
|
+
const result = evaluate(branch, context, depth + 1);
|
|
2031
|
+
if (result.degraded) return result;
|
|
2032
|
+
visible = isAll ? visible && result.visible : visible || result.visible;
|
|
2033
|
+
}
|
|
2034
|
+
return { visible };
|
|
2035
|
+
}
|
|
2036
|
+
const field = condition["field"];
|
|
2037
|
+
if (typeof field !== "string" || field === "") return invalid(context.path, "Condition needs a \"field\" name.");
|
|
2038
|
+
const value = context.resolve(field);
|
|
2039
|
+
if ("equals" in condition) {
|
|
2040
|
+
const expected = condition["equals"];
|
|
2041
|
+
if (typeof expected !== "string" && typeof expected !== "number" && typeof expected !== "boolean") return invalid(context.path, "\"equals\" must be a string, number or boolean.");
|
|
2042
|
+
return { visible: value === expected };
|
|
2043
|
+
}
|
|
2044
|
+
if ("in" in condition) {
|
|
2045
|
+
const options = condition["in"];
|
|
2046
|
+
if (!Array.isArray(options)) return invalid(context.path, "\"in\" must be an array.");
|
|
2047
|
+
return { visible: options.some((option) => option === value) };
|
|
2048
|
+
}
|
|
2049
|
+
if ("notEmpty" in condition) {
|
|
2050
|
+
if (condition["notEmpty"] !== true) return invalid(context.path, "\"notEmpty\" must be true.");
|
|
2051
|
+
return { visible: !isEmpty(value) };
|
|
2052
|
+
}
|
|
2053
|
+
return invalid(context.path, "Condition has no recognised operator (equals / in / notEmpty / allOf / anyOf).");
|
|
2054
|
+
}
|
|
2055
|
+
/**
|
|
2056
|
+
* 全仓唯一的条件求值实现(AC-23.4)。纯函数、无 React 依赖——
|
|
2057
|
+
* `useSurfaceForm` 在 ui-react 且是 hook,ui-vue 用不了它。
|
|
2058
|
+
*/
|
|
2059
|
+
function evaluateFieldCondition(condition, values, options = {}) {
|
|
2060
|
+
const resolveField = options.resolveField;
|
|
2061
|
+
return evaluate(condition, {
|
|
2062
|
+
values,
|
|
2063
|
+
resolve: (field) => values[resolveField ? resolveField(field) : field],
|
|
2064
|
+
path: options.path ?? "visibleWhen"
|
|
2065
|
+
}, 1);
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* 生成式表格的列模型(分册 15-03 定义 `priority`,分册 25 在同一结构上追加 `weight`)。
|
|
2069
|
+
*
|
|
2070
|
+
* 四个渲染档共用这一份:native / json-render / OpenUI 走 TS,a2ui 是 Lit,
|
|
2071
|
+
* 后者读不到 TS 常量,所以最小列宽以 **CSS 变量**交付,两侧引用同一个名字。
|
|
2072
|
+
*/
|
|
2073
|
+
/** 最小列宽的分档取值。`desktop` 沿用历史值,改它会动所有既有表格的视觉基线 */
|
|
2074
|
+
const SPEC_TABLE_MIN_COLUMN_WIDTH = {
|
|
2075
|
+
desktop: "8rem",
|
|
2076
|
+
mobile: "5rem"
|
|
2077
|
+
};
|
|
2078
|
+
/** CSS 侧的引用名:`surfaces.css` 与 a2ui 的 Lit 样式都只写这个变量,不写字面量 */
|
|
2079
|
+
const SPEC_TABLE_MIN_COLUMN_VAR = "--webskill-table-min-col";
|
|
2080
|
+
/**
|
|
2081
|
+
* 校验并归一化 `columnWidths`。
|
|
2082
|
+
*
|
|
2083
|
+
* **整项忽略**是刻意的:部分采纳(例如只丢掉那个负数)会让模型拿到一个
|
|
2084
|
+
* 「看起来生效了」的结果,更难发现自己写错了(FR-25.3)。
|
|
2085
|
+
*/
|
|
2086
|
+
function normalizeColumnWidths(raw, columnCount) {
|
|
2087
|
+
const equal = () => Array.from({ length: columnCount }, () => 1);
|
|
2088
|
+
if (raw === void 0) return { weights: equal() };
|
|
2089
|
+
if (raw.length !== columnCount) return {
|
|
2090
|
+
weights: equal(),
|
|
2091
|
+
rejected: "length-mismatch"
|
|
2092
|
+
};
|
|
2093
|
+
if (raw.some((value) => typeof value !== "number" || !Number.isFinite(value))) return {
|
|
2094
|
+
weights: equal(),
|
|
2095
|
+
rejected: "non-finite"
|
|
2096
|
+
};
|
|
2097
|
+
if (raw.some((value) => value < 0)) return {
|
|
2098
|
+
weights: equal(),
|
|
2099
|
+
rejected: "negative"
|
|
2100
|
+
};
|
|
2101
|
+
if (raw.every((value) => value === 0)) return {
|
|
2102
|
+
weights: equal(),
|
|
2103
|
+
rejected: "all-zero"
|
|
2104
|
+
};
|
|
2105
|
+
return { weights: [...raw] };
|
|
2106
|
+
}
|
|
2107
|
+
/**
|
|
2108
|
+
* 按权重分配列宽,且每列不低于 `minWidth`。
|
|
2109
|
+
*
|
|
2110
|
+
* 朴素实现(按权重算一遍、低于下限的抬到下限)会让总宽超出容器,
|
|
2111
|
+
* 白白产生本可避免的横滚。这里迭代到不动点:每轮把触底的列钉住,
|
|
2112
|
+
* 剩余空间在剩余列间按权重重新分配(FR-25.2)。
|
|
2113
|
+
*
|
|
2114
|
+
* 容器本身放不下 `columnCount * minWidth` 时无解——此时全部取下限并返回,
|
|
2115
|
+
* 由调用方决定横滚(AC-25.4)。
|
|
2116
|
+
*/
|
|
2117
|
+
function resolveColumnWidths(weights, available, minWidth) {
|
|
2118
|
+
const count = weights.length;
|
|
2119
|
+
if (count === 0) return [];
|
|
2120
|
+
if (available <= count * minWidth) return Array.from({ length: count }, () => minWidth);
|
|
2121
|
+
const result = Array.from({ length: count }, () => 0);
|
|
2122
|
+
const pinned = new Array(count).fill(false);
|
|
2123
|
+
for (let round = 0; round <= count; round += 1) {
|
|
2124
|
+
const freeIndexes = result.map((_, index) => index).filter((index) => !pinned[index]);
|
|
2125
|
+
const remaining = available - result.reduce((sum, value, index) => pinned[index] ? sum + value : sum, 0);
|
|
2126
|
+
const weightTotal = freeIndexes.reduce((sum, index) => sum + (weights[index] ?? 0), 0);
|
|
2127
|
+
let changed = false;
|
|
2128
|
+
for (const index of freeIndexes) {
|
|
2129
|
+
const share = weightTotal > 0 ? remaining * (weights[index] ?? 0) / weightTotal : remaining / freeIndexes.length;
|
|
2130
|
+
if (share < minWidth) {
|
|
2131
|
+
result[index] = minWidth;
|
|
2132
|
+
pinned[index] = true;
|
|
2133
|
+
changed = true;
|
|
2134
|
+
} else result[index] = share;
|
|
2135
|
+
}
|
|
2136
|
+
if (!changed) break;
|
|
2137
|
+
}
|
|
2138
|
+
return result;
|
|
2139
|
+
}
|
|
1761
2140
|
/** 五类场景预设(FR-6.4)。@experimental */
|
|
1762
2141
|
const UI_PRESETS = [
|
|
1763
2142
|
{
|
|
@@ -2044,14 +2423,15 @@ function toJsonRenderSpec(spec) {
|
|
|
2044
2423
|
elements
|
|
2045
2424
|
};
|
|
2046
2425
|
}
|
|
2047
|
-
/** ControlModel 的控件词汇 → catalog `Field.type`(catalog 的
|
|
2426
|
+
/** ControlModel 的控件词汇 → catalog `Field.type`(catalog 的 9 种是超集) */
|
|
2048
2427
|
const FIELD_TYPE = {
|
|
2049
2428
|
text: "text",
|
|
2050
2429
|
number: "number",
|
|
2051
2430
|
boolean: "toggle",
|
|
2052
2431
|
select: "select",
|
|
2053
2432
|
textarea: "textarea",
|
|
2054
|
-
file: "file"
|
|
2433
|
+
file: "file",
|
|
2434
|
+
password: "password"
|
|
2055
2435
|
};
|
|
2056
2436
|
function toOptions(options) {
|
|
2057
2437
|
return (options ?? []).map((option) => ({
|
|
@@ -2491,7 +2871,7 @@ function fromA2uiSpecAction(event) {
|
|
|
2491
2871
|
*/
|
|
2492
2872
|
async function loadWebSkillLitCatalog() {
|
|
2493
2873
|
try {
|
|
2494
|
-
const { webskillLitCatalog } = await import("./webskillLitCatalog-
|
|
2874
|
+
const { webskillLitCatalog } = await import("./webskillLitCatalog-DwTwSBFt-DiXXpNZA.js");
|
|
2495
2875
|
return webskillLitCatalog();
|
|
2496
2876
|
} catch (cause) {
|
|
2497
2877
|
throw new WebSkillError("UI_UNAVAILABLE", "The WebSkill A2UI catalog is unavailable; install @a2ui/lit, @a2ui/web_core and lit to render catalog surfaces with A2UI", cause);
|
|
@@ -2516,4 +2896,4 @@ async function loadOpenUiPeers() {
|
|
|
2516
2896
|
}
|
|
2517
2897
|
|
|
2518
2898
|
//#endregion
|
|
2519
|
-
export {
|
|
2899
|
+
export { UI_CATALOG_PROMPT_BUDGET_BYTES as $, fromUiSurfaceActionDispatch as A, resolveColumnWidths as B, collectSpecActions as C, evaluateFieldCondition as D, ensureStyles as E, normalizeColumnWidths as F, toUiSurfaceActionDispatch as G, toA2uiSurfaceAction as H, qualifyFieldName as I, A2UI_CHILDREN_PROP as J, toVercelToolInvocation as K, renderBlocks as L, interactionToUiSpec as M, loadOpenUiPeers as N, fromA2uiSpecAction as O, loadWebSkillLitCatalog as P, UI_CATALOG_GROUPS as Q, renderMiniChart as R, collectScopedValues as S, createUiCatalogToolSource as T, toJsonRenderSpec as U, toA2uiSpecMessages as V, toOpenUiSpecLang as W, DEFAULT_INTERACTION_TEXTS as X, A2UI_COMMON_TYPES as Y, DEFAULT_SURFACE_FORM_TEXTS as Z, WEBSKILL_SURFACE_ACTION as _, A2UI_VERSION as a, defineUiCatalog as at, chartToTable as b, MAX_CONDITION_DEPTH as c, renderMiniMarkdown as ct, SPEC_TABLE_MIN_COLUMN_WIDTH as d, shapeInteractionValue as dt, WEBSKILL_A2UI_CATALOG_ID as et, UI_PRESETS as f, uiCatalog as ft, WEBSKILL_STYLES_CSS as g, VercelUiBridge as h, A2UI_SURFACE_ACTION as i, chartSpecFromProps as it, fromVercelToolResult as j, fromA2uiSurfaceAction as k, RENDER_UI_TOOL as l, resolveInteractionTexts as lt, VERCEL_INTERACTION_TOOL_NAME as m, A2UI_SPEC_ACTION as n, a2uiComponentShapes as nt, CHART_PALETTE as o, interactionToFormModel as ot, UI_PRESET_NAMES as p, uiPreset as q, A2UI_SPEC_FORM_PATH as r, buildA2uiCatalogDefinition as rt, DESCRIBE_UI_PRESET_TOOL as s, mountEchart as st, A2UI_BASIC_CATALOG_ID as t, a2uiComponentSchema as tt, SPEC_TABLE_MIN_COLUMN_VAR as u, resolveSurfaceFormTexts as ut, WebFormBridge as v, collectValues as w, collectFormScopes as x, applySuggestion as y, renderRenderResult as z };
|