@webskill/sdk 0.0.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.
@@ -0,0 +1,239 @@
1
+ import { _ as interactionToFormModel, f as collectValues, x as shapeInteractionValue, y as renderMiniMarkdown } from "./dist-RcqvzAGF.js";
2
+ import { useLayoutEffect, useRef, useState, useSyncExternalStore } from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+
5
+ //#region ../ui-react/dist/index.js
6
+ /**
7
+ * React 桥接状态:UiBridge 实现 + useSyncExternalStore 兼容订阅。
8
+ * 应用创建实例传给 Runtime 与组件:<InteractionForm bridge={bridge} />。
9
+ */
10
+ var ReactBridgeState = class {
11
+ pending = null;
12
+ latestResult = null;
13
+ streamingText = "";
14
+ #listeners = /* @__PURE__ */ new Set();
15
+ #resolvers = /* @__PURE__ */ new Map();
16
+ /** React useSyncExternalStore 兼容订阅 */
17
+ subscribe = (listener) => {
18
+ this.#listeners.add(listener);
19
+ return () => this.#listeners.delete(listener);
20
+ };
21
+ #emit() {
22
+ for (const listener of [...this.#listeners]) listener();
23
+ }
24
+ request(input) {
25
+ this.pending = input;
26
+ this.#emit();
27
+ return new Promise((resolve) => {
28
+ this.#resolvers.set(input.id, resolve);
29
+ });
30
+ }
31
+ /** 组件提交/取消回调 */
32
+ resolve(response) {
33
+ const resolver = this.#resolvers.get(response.id);
34
+ if (!resolver) return;
35
+ this.#resolvers.delete(response.id);
36
+ this.pending = null;
37
+ this.#emit();
38
+ resolver(response);
39
+ }
40
+ async renderResult(input) {
41
+ this.latestResult = input;
42
+ this.#emit();
43
+ }
44
+ async onTextDelta(_runId, delta) {
45
+ this.streamingText += delta;
46
+ this.#emit();
47
+ }
48
+ };
49
+ function Control({ control }) {
50
+ const label = /* @__PURE__ */ jsxs("label", {
51
+ className: "webskill-form__label",
52
+ children: [control.label, control.required ? " *" : ""]
53
+ });
54
+ const description = control.description ? /* @__PURE__ */ jsx("div", {
55
+ className: "webskill-form__description",
56
+ children: control.description
57
+ }) : null;
58
+ switch (control.control) {
59
+ case "boolean": return /* @__PURE__ */ jsxs("div", {
60
+ className: "webskill-form__control",
61
+ "data-control-name": control.name,
62
+ children: [
63
+ label,
64
+ description,
65
+ /* @__PURE__ */ jsx("input", {
66
+ type: "checkbox",
67
+ className: "webskill-form__input",
68
+ "data-webskill-control": control.name,
69
+ defaultChecked: control.defaultValue === true
70
+ })
71
+ ]
72
+ });
73
+ case "select": return /* @__PURE__ */ jsxs("div", {
74
+ className: "webskill-form__control",
75
+ "data-control-name": control.name,
76
+ children: [
77
+ label,
78
+ description,
79
+ /* @__PURE__ */ jsx("select", {
80
+ className: "webskill-form__input",
81
+ "data-webskill-control": control.name,
82
+ children: (control.options ?? []).map((option, i) => /* @__PURE__ */ jsx("option", {
83
+ value: JSON.stringify(option.value),
84
+ ...control.defaultValue !== void 0 && JSON.stringify(control.defaultValue) === JSON.stringify(option.value) ? { selected: true } : {},
85
+ children: option.label
86
+ }, i))
87
+ })
88
+ ]
89
+ });
90
+ case "textarea": return /* @__PURE__ */ jsxs("div", {
91
+ className: "webskill-form__control",
92
+ "data-control-name": control.name,
93
+ children: [
94
+ label,
95
+ description,
96
+ /* @__PURE__ */ jsx("textarea", {
97
+ className: "webskill-form__input",
98
+ "data-webskill-control": control.name,
99
+ defaultValue: control.defaultValue !== void 0 ? String(control.defaultValue) : ""
100
+ })
101
+ ]
102
+ });
103
+ default: return /* @__PURE__ */ jsxs("div", {
104
+ className: "webskill-form__control",
105
+ "data-control-name": control.name,
106
+ children: [
107
+ label,
108
+ description,
109
+ /* @__PURE__ */ jsx("input", {
110
+ type: control.control === "number" ? "number" : "text",
111
+ className: "webskill-form__input",
112
+ "data-webskill-control": control.name,
113
+ defaultValue: control.defaultValue !== void 0 ? String(control.defaultValue) : ""
114
+ })
115
+ ]
116
+ });
117
+ }
118
+ }
119
+ /** 订阅 bridge.pending 渲染交互表单;提交/取消经 bridge.resolve 回传 */
120
+ function InteractionForm({ bridge }) {
121
+ const pending = useSyncExternalStore(bridge.subscribe, () => bridge.pending);
122
+ const formRef = useRef(null);
123
+ const [invalid, setInvalid] = useState([]);
124
+ if (!pending) return null;
125
+ const model = interactionToFormModel(pending);
126
+ return /* @__PURE__ */ jsxs("form", {
127
+ ref: formRef,
128
+ className: "webskill-form",
129
+ noValidate: true,
130
+ onSubmit: (event) => {
131
+ event.preventDefault();
132
+ if (!formRef.current) return;
133
+ const { values, missingRequired } = collectValues(model.controls, formRef.current);
134
+ if (missingRequired.length > 0) {
135
+ setInvalid(missingRequired);
136
+ return;
137
+ }
138
+ bridge.resolve({
139
+ id: pending.id,
140
+ value: shapeInteractionValue(model, values)
141
+ });
142
+ },
143
+ children: [
144
+ model.title ? /* @__PURE__ */ jsx("div", {
145
+ className: "webskill-form__title",
146
+ children: model.title
147
+ }) : null,
148
+ model.message && model.kind === "form" ? /* @__PURE__ */ jsx("p", {
149
+ className: "webskill-form__message",
150
+ children: model.message
151
+ }) : null,
152
+ model.controls.map((control) => /* @__PURE__ */ jsxs("div", {
153
+ className: invalid.includes(control.name) ? "webskill-form__control--invalid" : void 0,
154
+ children: [/* @__PURE__ */ jsx(Control, { control }), invalid.includes(control.name) ? /* @__PURE__ */ jsx("div", {
155
+ className: "webskill-form__error",
156
+ children: "This field is required"
157
+ }) : null]
158
+ }, control.name)),
159
+ /* @__PURE__ */ jsxs("div", {
160
+ className: "webskill-form__actions",
161
+ children: [/* @__PURE__ */ jsx("button", {
162
+ type: "submit",
163
+ className: "webskill-form__button webskill-form__button--primary",
164
+ children: model.submitLabel
165
+ }), model.cancelLabel ? /* @__PURE__ */ jsx("button", {
166
+ type: "button",
167
+ className: "webskill-form__button webskill-form__button--ghost",
168
+ "data-webskill-cancel": true,
169
+ onClick: () => bridge.resolve({
170
+ id: pending.id,
171
+ cancelled: true
172
+ }),
173
+ children: model.cancelLabel
174
+ }) : null]
175
+ })
176
+ ]
177
+ });
178
+ }
179
+ function MarkdownBlock({ text }) {
180
+ const ref = useRef(null);
181
+ useLayoutEffect(() => {
182
+ const el = ref.current;
183
+ if (!el) return;
184
+ el.replaceChildren(renderMiniMarkdown(text, el.ownerDocument));
185
+ }, [text]);
186
+ return /* @__PURE__ */ jsx("div", { ref });
187
+ }
188
+ function Block({ block }) {
189
+ switch (block.type) {
190
+ case "markdown": return /* @__PURE__ */ jsx(MarkdownBlock, { text: block.text });
191
+ case "json": return /* @__PURE__ */ jsx("pre", {
192
+ className: "webskill-result__json",
193
+ children: JSON.stringify(block.data, null, 2)
194
+ });
195
+ case "table": return /* @__PURE__ */ jsxs("table", { children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: block.columns.map((column) => /* @__PURE__ */ jsx("th", { children: column }, column)) }) }), /* @__PURE__ */ jsx("tbody", { children: block.rows.map((row, i) => /* @__PURE__ */ jsx("tr", { children: row.map((cell, j) => /* @__PURE__ */ jsx("td", { children: typeof cell === "object" ? JSON.stringify(cell) : String(cell ?? "") }, j)) }, i)) })] });
196
+ case "image": return /* @__PURE__ */ jsx("img", {
197
+ src: block.url,
198
+ alt: block.alt ?? ""
199
+ });
200
+ case "file": {
201
+ const meta = [block.mimeType, block.size !== void 0 ? `${block.size} bytes` : void 0].filter(Boolean).join(", ");
202
+ return /* @__PURE__ */ jsx("div", {
203
+ className: "webskill-result__file",
204
+ children: meta ? `${block.path} (${meta})` : block.path
205
+ });
206
+ }
207
+ }
208
+ }
209
+ /** 订阅 bridge.latestResult 渲染五种 RenderBlock */
210
+ function ResultBlocks({ bridge }) {
211
+ const result = useSyncExternalStore(bridge.subscribe, () => bridge.latestResult);
212
+ if (!result) return null;
213
+ return /* @__PURE__ */ jsxs("div", {
214
+ className: "webskill-result",
215
+ children: [
216
+ result.title ? /* @__PURE__ */ jsx("div", {
217
+ className: "webskill-form__title",
218
+ children: result.title
219
+ }) : null,
220
+ result.summary ? /* @__PURE__ */ jsx("div", {
221
+ className: "webskill-result__summary",
222
+ children: result.summary
223
+ }) : null,
224
+ result.blocks.map((block, i) => /* @__PURE__ */ jsx(Block, { block }, i))
225
+ ]
226
+ });
227
+ }
228
+ /** 订阅 bridge.streamingText 增量渲染流式文本 */
229
+ function StreamingText({ bridge }) {
230
+ const text = useSyncExternalStore(bridge.subscribe, () => bridge.streamingText);
231
+ if (text === "") return null;
232
+ return /* @__PURE__ */ jsx("div", {
233
+ className: "webskill-streaming-text",
234
+ children: text
235
+ });
236
+ }
237
+
238
+ //#endregion
239
+ export { InteractionForm, ReactBridgeState, ResultBlocks, StreamingText };
@@ -0,0 +1,72 @@
1
+ import { C as InteractionRequest, X as RenderResultRequest, pt as UiBridge, w as InteractionResponse } from "./index-88KNOnbr.js";
2
+ import { PropType } from "vue";
3
+ //#region ../ui-vue/dist/index.d.ts
4
+ //#region src/bridgeState.d.ts
5
+ interface VueBridgeSnapshot {
6
+ pending: InteractionRequest | null;
7
+ latestResult: RenderResultRequest | null;
8
+ streamingText: string;
9
+ }
10
+ /**
11
+ * Vue 桥接状态:UiBridge 实现 + reactive 快照。
12
+ * 应用创建实例传给 Runtime 与组件(组件经 props 接收 bridge)。
13
+ */
14
+ declare class VueBridgeState implements UiBridge {
15
+ #private;
16
+ readonly state: VueBridgeSnapshot;
17
+ request(input: InteractionRequest): Promise<InteractionResponse>;
18
+ /** 组件提交/取消回调 */
19
+ resolve(response: InteractionResponse): void;
20
+ renderResult(input: RenderResultRequest): Promise<void>;
21
+ onTextDelta(_runId: string, delta: string): Promise<void>;
22
+ }
23
+ //#endregion
24
+ //#region src/components/interactionForm.d.ts
25
+ /** 订阅 bridge.state.pending 渲染交互表单(h() 渲染函数,无 SFC) */
26
+ declare const InteractionForm: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
27
+ bridge: {
28
+ type: PropType<VueBridgeState>;
29
+ required: true;
30
+ };
31
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
32
+ [key: string]: any;
33
+ }> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
34
+ bridge: {
35
+ type: PropType<VueBridgeState>;
36
+ required: true;
37
+ };
38
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
39
+ //#endregion
40
+ //#region src/components/resultBlocks.d.ts
41
+ /** 订阅 bridge.state.latestResult 渲染五种 RenderBlock */
42
+ declare const ResultBlocks: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
43
+ bridge: {
44
+ type: PropType<VueBridgeState>;
45
+ required: true;
46
+ };
47
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
48
+ [key: string]: any;
49
+ }> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
50
+ bridge: {
51
+ type: PropType<VueBridgeState>;
52
+ required: true;
53
+ };
54
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
55
+ //#endregion
56
+ //#region src/components/streamingText.d.ts
57
+ /** 订阅 bridge.state.streamingText 增量渲染流式文本 */
58
+ declare const StreamingText: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
59
+ bridge: {
60
+ type: PropType<VueBridgeState>;
61
+ required: true;
62
+ };
63
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
64
+ [key: string]: any;
65
+ }> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
66
+ bridge: {
67
+ type: PropType<VueBridgeState>;
68
+ required: true;
69
+ };
70
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
71
+ //#endregion
72
+ export { InteractionForm, ResultBlocks, StreamingText, type VueBridgeSnapshot, VueBridgeState };
package/dist/ui-vue.js ADDED
@@ -0,0 +1,196 @@
1
+ import { _ as interactionToFormModel, f as collectValues, x as shapeInteractionValue, y as renderMiniMarkdown } from "./dist-RcqvzAGF.js";
2
+ import { defineComponent, h, reactive, ref } from "vue";
3
+
4
+ //#region ../ui-vue/dist/index.js
5
+ /**
6
+ * Vue 桥接状态:UiBridge 实现 + reactive 快照。
7
+ * 应用创建实例传给 Runtime 与组件(组件经 props 接收 bridge)。
8
+ */
9
+ var VueBridgeState = class {
10
+ state = reactive({
11
+ pending: null,
12
+ latestResult: null,
13
+ streamingText: ""
14
+ });
15
+ #resolvers = /* @__PURE__ */ new Map();
16
+ request(input) {
17
+ this.state.pending = input;
18
+ return new Promise((resolve) => {
19
+ this.#resolvers.set(input.id, resolve);
20
+ });
21
+ }
22
+ /** 组件提交/取消回调 */
23
+ resolve(response) {
24
+ const resolver = this.#resolvers.get(response.id);
25
+ if (!resolver) return;
26
+ this.#resolvers.delete(response.id);
27
+ this.state.pending = null;
28
+ resolver(response);
29
+ }
30
+ async renderResult(input) {
31
+ this.state.latestResult = input;
32
+ }
33
+ async onTextDelta(_runId, delta) {
34
+ this.state.streamingText += delta;
35
+ }
36
+ };
37
+ function renderControl(control) {
38
+ const label = h("label", { class: "webskill-form__label" }, [control.label, ...control.required ? [" *"] : []]);
39
+ const description = control.description ? h("div", { class: "webskill-form__description" }, control.description) : null;
40
+ let input;
41
+ switch (control.control) {
42
+ case "boolean":
43
+ input = h("input", {
44
+ type: "checkbox",
45
+ class: "webskill-form__input",
46
+ "data-webskill-control": control.name,
47
+ checked: control.defaultValue === true
48
+ });
49
+ break;
50
+ case "select":
51
+ input = h("select", {
52
+ class: "webskill-form__input",
53
+ "data-webskill-control": control.name
54
+ }, (control.options ?? []).map((option) => h("option", {
55
+ value: JSON.stringify(option.value),
56
+ selected: control.defaultValue !== void 0 && JSON.stringify(control.defaultValue) === JSON.stringify(option.value)
57
+ }, option.label)));
58
+ break;
59
+ case "textarea":
60
+ input = h("textarea", {
61
+ class: "webskill-form__input",
62
+ "data-webskill-control": control.name,
63
+ value: control.defaultValue !== void 0 ? String(control.defaultValue) : ""
64
+ });
65
+ break;
66
+ default: input = h("input", {
67
+ type: control.control === "number" ? "number" : "text",
68
+ class: "webskill-form__input",
69
+ "data-webskill-control": control.name,
70
+ value: control.defaultValue !== void 0 ? String(control.defaultValue) : ""
71
+ });
72
+ }
73
+ return h("div", {
74
+ class: "webskill-form__control",
75
+ "data-control-name": control.name
76
+ }, [
77
+ label,
78
+ description,
79
+ input
80
+ ]);
81
+ }
82
+ /** 订阅 bridge.state.pending 渲染交互表单(h() 渲染函数,无 SFC) */
83
+ const InteractionForm = defineComponent({
84
+ name: "WebSkillInteractionForm",
85
+ props: { bridge: {
86
+ type: Object,
87
+ required: true
88
+ } },
89
+ setup(props) {
90
+ const formRef = ref(null);
91
+ const invalid = ref([]);
92
+ return () => {
93
+ const pending = props.bridge.state.pending;
94
+ if (!pending) return null;
95
+ const model = interactionToFormModel(pending);
96
+ return h("form", {
97
+ ref: formRef,
98
+ class: "webskill-form",
99
+ novalidate: true,
100
+ onSubmit: (event) => {
101
+ event.preventDefault();
102
+ if (!formRef.value) return;
103
+ const { values, missingRequired } = collectValues(model.controls, formRef.value);
104
+ if (missingRequired.length > 0) {
105
+ invalid.value = missingRequired;
106
+ return;
107
+ }
108
+ props.bridge.resolve({
109
+ id: pending.id,
110
+ value: shapeInteractionValue(model, values)
111
+ });
112
+ }
113
+ }, [
114
+ model.title ? h("div", { class: "webskill-form__title" }, model.title) : null,
115
+ model.message && model.kind === "form" ? h("p", { class: "webskill-form__message" }, model.message) : null,
116
+ ...model.controls.map((control) => h("div", { key: control.name }, [renderControl(control), invalid.value.includes(control.name) ? h("div", { class: "webskill-form__error" }, "This field is required") : null])),
117
+ h("div", { class: "webskill-form__actions" }, [h("button", {
118
+ type: "submit",
119
+ class: "webskill-form__button webskill-form__button--primary"
120
+ }, model.submitLabel), model.cancelLabel ? h("button", {
121
+ type: "button",
122
+ class: "webskill-form__button webskill-form__button--ghost",
123
+ "data-webskill-cancel": "",
124
+ onClick: () => props.bridge.resolve({
125
+ id: pending.id,
126
+ cancelled: true
127
+ })
128
+ }, model.cancelLabel) : null])
129
+ ]);
130
+ };
131
+ }
132
+ });
133
+ function renderBlock(block, key) {
134
+ switch (block.type) {
135
+ case "markdown": return h("div", {
136
+ key,
137
+ onVnodeMounted: (vnode) => {
138
+ const el = vnode.el;
139
+ if (el) el.replaceChildren(renderMiniMarkdown(block.text, el.ownerDocument));
140
+ }
141
+ });
142
+ case "json": return h("pre", {
143
+ key,
144
+ class: "webskill-result__json"
145
+ }, JSON.stringify(block.data, null, 2));
146
+ case "table": return h("table", { key }, [h("thead", [h("tr", block.columns.map((column) => h("th", column)))]), h("tbody", block.rows.map((row, i) => h("tr", { key: i }, row.map((cell, j) => h("td", { key: j }, typeof cell === "object" ? JSON.stringify(cell) : String(cell ?? ""))))))]);
147
+ case "image": return h("img", {
148
+ key,
149
+ src: block.url,
150
+ alt: block.alt ?? ""
151
+ });
152
+ case "file": {
153
+ const meta = [block.mimeType, block.size !== void 0 ? `${block.size} bytes` : void 0].filter(Boolean).join(", ");
154
+ return h("div", {
155
+ key,
156
+ class: "webskill-result__file"
157
+ }, meta ? `${block.path} (${meta})` : block.path);
158
+ }
159
+ }
160
+ }
161
+ /** 订阅 bridge.state.latestResult 渲染五种 RenderBlock */
162
+ const ResultBlocks = defineComponent({
163
+ name: "WebSkillResultBlocks",
164
+ props: { bridge: {
165
+ type: Object,
166
+ required: true
167
+ } },
168
+ setup(props) {
169
+ return () => {
170
+ const result = props.bridge.state.latestResult;
171
+ if (!result) return null;
172
+ return h("div", { class: "webskill-result" }, [
173
+ result.title ? h("div", { class: "webskill-form__title" }, result.title) : null,
174
+ result.summary ? h("div", { class: "webskill-result__summary" }, result.summary) : null,
175
+ ...result.blocks.map((block, i) => renderBlock(block, i))
176
+ ]);
177
+ };
178
+ }
179
+ });
180
+ /** 订阅 bridge.state.streamingText 增量渲染流式文本 */
181
+ const StreamingText = defineComponent({
182
+ name: "WebSkillStreamingText",
183
+ props: { bridge: {
184
+ type: Object,
185
+ required: true
186
+ } },
187
+ setup(props) {
188
+ return () => {
189
+ const text = props.bridge.state.streamingText;
190
+ return text === "" ? null : h("div", { class: "webskill-streaming-text" }, text);
191
+ };
192
+ }
193
+ });
194
+
195
+ //#endregion
196
+ export { InteractionForm, ResultBlocks, StreamingText, VueBridgeState };
package/dist/ui.d.ts ADDED
@@ -0,0 +1,171 @@
1
+ import { C as InteractionRequest, X as RenderResultRequest, Y as RenderBlock, pt as UiBridge, vt as buildRenderResult, w as InteractionResponse } from "./index-88KNOnbr.js";
2
+ //#region ../ui/dist/index.d.ts
3
+ //#region src/model/formModel.d.ts
4
+ interface FormModel {
5
+ kind: 'ask' | 'confirm' | 'form' | 'select';
6
+ title?: string;
7
+ message?: string;
8
+ controls: ControlModel[];
9
+ submitLabel: string;
10
+ cancelLabel?: string;
11
+ }
12
+ interface ControlModel {
13
+ name: string;
14
+ label: string;
15
+ control: 'text' | 'number' | 'boolean' | 'select' | 'textarea';
16
+ required?: boolean;
17
+ description?: string;
18
+ defaultValue?: unknown;
19
+ options?: Array<{
20
+ label: string;
21
+ value: unknown;
22
+ }>;
23
+ }
24
+ /** 提交值按请求类型归形(WebFormBridge 与框架组件库共享单一来源) */
25
+ declare function shapeInteractionValue(model: FormModel, values: Record<string, unknown>): unknown;
26
+ /** 四类 InteractionRequest → 统一中间模型(框架无关) */
27
+ declare function interactionToFormModel(request: InteractionRequest): FormModel;
28
+ //#endregion
29
+ //#region src/model/collectValues.d.ts
30
+ interface CollectedValues {
31
+ values: Record<string, unknown>;
32
+ /** required 但为空的控件名(阻止提交) */
33
+ missingRequired: string[];
34
+ }
35
+ /**
36
+ * 严格类型化控件值收集:
37
+ * - number 空串 → undefined(非 0)
38
+ * - select 用 option 值本身经 JSON 编码比对命中(对象值可正确命中)
39
+ * - required 空值列入 missingRequired(由调用方阻止提交并标记)
40
+ */
41
+ declare function collectValues(controls: ControlModel[], container: ParentNode): CollectedValues;
42
+ //#endregion
43
+ //#region src/markdown/miniMarkdown.d.ts
44
+ /**
45
+ * 最小子集 markdown → DOM:标题(#..###)、无序列表、代码块(```)、加粗、链接。
46
+ * 全部内容经 textContent 写入,用户内容天然转义防 HTML 注入。
47
+ */
48
+ declare function renderMiniMarkdown(text: string, doc: Document): HTMLElement;
49
+ //#endregion
50
+ //#region src/web/webFormBridge.d.ts
51
+ /**
52
+ * 框架无关原生 DOM 的 UiBridge:request 渲染表单并返回 Promise
53
+ * (提交 resolve / 取消 {cancelled:true}),完成后卸载 DOM。
54
+ * document 可注入(jsdom 测试);BEM class 样式可覆写。
55
+ */
56
+ declare class WebFormBridge implements UiBridge {
57
+ #private;
58
+ constructor(options: {
59
+ mount: HTMLElement;
60
+ document?: Document;
61
+ styles?: boolean;
62
+ });
63
+ request(input: InteractionRequest): Promise<InteractionResponse>;
64
+ renderResult(input: RenderResultRequest): Promise<void>;
65
+ progress(input: {
66
+ runId: string;
67
+ message: string;
68
+ value?: number;
69
+ }): Promise<void>;
70
+ }
71
+ //#endregion
72
+ //#region src/web/resultRenderer.d.ts
73
+ /** RenderBlock → DOM(markdown/json/table/image/file 五种) */
74
+ declare function renderBlocks(container: HTMLElement, blocks: RenderBlock[], doc: Document): void;
75
+ /** 完整 RenderResultRequest → DOM(summary 头 + blocks) */
76
+ declare function renderRenderResult(request: RenderResultRequest, doc: Document): HTMLElement;
77
+ //#endregion
78
+ //#region src/web/styles.d.ts
79
+ /** 最小样式(BEM class,应用可整体覆写) */
80
+ declare const WEBSKILL_STYLES_CSS = "\n.webskill-form { display: block; padding: 12px; border: 1px solid #d0d0d0; border-radius: 8px; font-family: system-ui, sans-serif; max-width: 420px; }\n.webskill-form__title { margin: 0 0 8px; font-size: 15px; font-weight: 600; }\n.webskill-form__message { margin: 0 0 10px; font-size: 14px; }\n.webskill-form__control { margin-bottom: 10px; display: flex; flex-direction: column; gap: 4px; }\n.webskill-form__control--invalid .webskill-form__input { border-color: #d33; }\n.webskill-form__label { font-size: 13px; font-weight: 500; }\n.webskill-form__label-required::after { content: ' *'; color: #d33; }\n.webskill-form__description { font-size: 12px; color: #666; }\n.webskill-form__error { font-size: 12px; color: #d33; display: none; }\n.webskill-form__control--invalid .webskill-form__error { display: block; }\n.webskill-form__input { padding: 6px 8px; border: 1px solid #bbb; border-radius: 4px; font-size: 14px; font-family: inherit; }\n.webskill-form__actions { display: flex; gap: 8px; margin-top: 12px; }\n.webskill-form__button { padding: 6px 14px; border-radius: 4px; border: 1px solid #bbb; background: #fff; cursor: pointer; font-size: 14px; }\n.webskill-form__button--primary { background: #2563eb; border-color: #2563eb; color: #fff; }\n.webskill-form__button--ghost { background: transparent; }\n.webskill-result { font-family: system-ui, sans-serif; font-size: 14px; }\n.webskill-result__summary { font-size: 12px; color: #666; margin-bottom: 6px; }\n.webskill-result__json { background: #f5f5f5; padding: 8px; border-radius: 4px; overflow-x: auto; }\n.webskill-result__file { padding: 4px 0; font-size: 13px; }\n.webskill-md pre { background: #f5f5f5; padding: 8px; border-radius: 4px; overflow-x: auto; }\n.webskill-md h1, .webskill-md h2, .webskill-md h3 { margin: 8px 0 4px; }\n.webskill-md p { margin: 4px 0; }\n.webskill-md ul { margin: 4px 0; padding-left: 20px; }\n";
81
+ /** 每个 document 只注入一次 */
82
+ declare function ensureStyles(doc: Document): void;
83
+ //#endregion
84
+ //#region src/adapters/vercel/vercelPayload.d.ts
85
+ /** Vercel AI SDK v7 ToolCallPart 兼容结构 */
86
+ interface VercelToolInvocation {
87
+ type: 'tool-call';
88
+ toolCallId: string;
89
+ toolName: string;
90
+ input: unknown;
91
+ }
92
+ declare const VERCEL_INTERACTION_TOOL_NAME = "webskill_interaction";
93
+ /** InteractionRequest → SDK tool UI 结构(应用聊天 UI 直接消费) */
94
+ declare function toVercelToolInvocation(request: InteractionRequest): VercelToolInvocation;
95
+ /** SDK 回传(tool result / output)→ InteractionResponse */
96
+ declare function fromVercelToolResult(part: unknown): InteractionResponse;
97
+ //#endregion
98
+ //#region src/adapters/vercel/vercelUiBridge.d.ts
99
+ /**
100
+ * 薄桥接类:request → SDK tool UI 结构 → 应用的聊天 UI(sendInteraction 回调实现)
101
+ * → SDK 回传 → InteractionResponse。
102
+ */
103
+ declare class VercelUiBridge implements UiBridge {
104
+ #private;
105
+ constructor(deps: {
106
+ sendInteraction: (invocation: VercelToolInvocation) => Promise<unknown>;
107
+ });
108
+ request(input: InteractionRequest): Promise<InteractionResponse>;
109
+ }
110
+ //#endregion
111
+ //#region src/adapters/openui/openuiLang.d.ts
112
+ /**
113
+ * InteractionRequest ↔ openui-lang 双向转换。
114
+ * openui-lang 语法(@openuidev/react-lang 实测):
115
+ * - 每行一条语句 `identifier = Expression`,`root = Component(...)` 为入口
116
+ * - 组件调用参数为位置参数;字符串双引号反斜杠转义
117
+ * - 组件词汇(与应用 Library 约定):Form(title, children)、
118
+ * TextField(name, label, required?, defaultValue?)、NumberField、BooleanField(name, label, default?)、
119
+ * SelectField(name, label, options)、SubmitButton(label, actionType, requestId)、
120
+ * CancelButton(label, actionType, requestId)
121
+ */
122
+ declare const OPENUI_SUBMIT_ACTION = "webskill:submit";
123
+ declare const OPENUI_CANCEL_ACTION = "webskill:cancel";
124
+ declare function toOpenUiLang(request: InteractionRequest): string;
125
+ /** OpenUI ActionEvent → InteractionResponse(formState 优先,取消单独分支) */
126
+ declare function fromOpenUiAction(action: unknown): InteractionResponse;
127
+ //#endregion
128
+ //#region src/adapters/a2ui/a2uiMessages.d.ts
129
+ /**
130
+ * InteractionRequest → A2UI 协议消息(v0.9.1,Basic Catalog)。
131
+ * 依据 https://a2ui.org/specification/v0.9-a2ui/:
132
+ * - 信封 {version, createSurface|updateComponents|updateDataModel|deleteSurface}
133
+ * - 组件为扁平邻接表(id 引用),root 必需
134
+ * - 输入组件与数据模型经 JSON Pointer 双向绑定;action.context 回传
135
+ * - createSurface.sendDataModel: true → 客户端动作时携带完整数据模型
136
+ *
137
+ * action 约定:submit → {name: 'webskill:submit', context: {requestId}};
138
+ * cancel → {name: 'webskill:cancel', context: {requestId}}。
139
+ */
140
+ declare const A2UI_VERSION = "v0.9.1";
141
+ declare const A2UI_BASIC_CATALOG_ID = "https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json";
142
+ declare const A2UI_SUBMIT_ACTION = "webskill:submit";
143
+ declare const A2UI_CANCEL_ACTION = "webskill:cancel";
144
+ interface A2uiMessage {
145
+ version: string;
146
+ [key: string]: unknown;
147
+ }
148
+ declare function toA2uiMessages(request: InteractionRequest): A2uiMessage[];
149
+ /** A2UI client→server action 事件 → InteractionResponse */
150
+ declare function fromA2uiAction(event: unknown): InteractionResponse;
151
+ //#endregion
152
+ //#region src/a2uiRuntime/litRendererBridge.d.ts
153
+ /**
154
+ * A2UI 运行时桥(Lit 渲染器路径):
155
+ * InteractionRequest →(7A 转换器)→ A2UI v0.9.1 消息序列 →
156
+ * @a2ui/web_core MessageProcessor 处理 → @a2ui/lit 渲染到容器 →
157
+ * action 事件(合并双向绑定的表单数据模型)→ fromA2uiAction → InteractionResponse。
158
+ *
159
+ * 版本对齐:渲染器 @a2ui/lit@0.10.x 经 v0_9 入口同时接受 v0.9 / v0.9.1 消息
160
+ * (schema 枚举 ['v0.9','v0.9.1']),与 7A v0.9.1 转换产物直接兼容。
161
+ */
162
+ declare class LitRendererBridge implements UiBridge {
163
+ #private;
164
+ constructor(deps: {
165
+ mount: HTMLElement;
166
+ document?: Document;
167
+ });
168
+ request(input: InteractionRequest): Promise<InteractionResponse>;
169
+ }
170
+ //#endregion
171
+ export { A2UI_BASIC_CATALOG_ID, A2UI_CANCEL_ACTION, A2UI_SUBMIT_ACTION, A2UI_VERSION, type A2uiMessage, type CollectedValues, type ControlModel, type FormModel, LitRendererBridge, OPENUI_CANCEL_ACTION, OPENUI_SUBMIT_ACTION, VERCEL_INTERACTION_TOOL_NAME, type VercelToolInvocation, VercelUiBridge, WEBSKILL_STYLES_CSS, WebFormBridge, buildRenderResult, collectValues, ensureStyles, fromA2uiAction, fromOpenUiAction, fromVercelToolResult, interactionToFormModel, renderBlocks, renderMiniMarkdown, renderRenderResult, shapeInteractionValue, toA2uiMessages, toOpenUiLang, toVercelToolInvocation };
package/dist/ui.js ADDED
@@ -0,0 +1,4 @@
1
+ import { S as buildRenderResult } from "./dist-B_ldNWwT.js";
2
+ import { C as toOpenUiLang, S as toA2uiMessages, _ as interactionToFormModel, a as LitRendererBridge, b as renderRenderResult, c as VERCEL_INTERACTION_TOOL_NAME, d as WebFormBridge, f as collectValues, g as fromVercelToolResult, h as fromOpenUiAction, i as A2UI_VERSION, l as VercelUiBridge, m as fromA2uiAction, n as A2UI_CANCEL_ACTION, o as OPENUI_CANCEL_ACTION, p as ensureStyles, r as A2UI_SUBMIT_ACTION, s as OPENUI_SUBMIT_ACTION, t as A2UI_BASIC_CATALOG_ID, u as WEBSKILL_STYLES_CSS, v as renderBlocks, w as toVercelToolInvocation, x as shapeInteractionValue, y as renderMiniMarkdown } from "./dist-RcqvzAGF.js";
3
+
4
+ export { A2UI_BASIC_CATALOG_ID, A2UI_CANCEL_ACTION, A2UI_SUBMIT_ACTION, A2UI_VERSION, LitRendererBridge, OPENUI_CANCEL_ACTION, OPENUI_SUBMIT_ACTION, VERCEL_INTERACTION_TOOL_NAME, VercelUiBridge, WEBSKILL_STYLES_CSS, WebFormBridge, buildRenderResult, collectValues, ensureStyles, fromA2uiAction, fromOpenUiAction, fromVercelToolResult, interactionToFormModel, renderBlocks, renderMiniMarkdown, renderRenderResult, shapeInteractionValue, toA2uiMessages, toOpenUiLang, toVercelToolInvocation };