a2ui-render-in-dsh 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # a2ui-render-in-dsh
2
+
3
+ English | [中文](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/README.zh.md)
4
+
5
+ **A2UI interactive cards for the dsh web UI**: the agent adaptively renders **interactive, visual UI cards** right inside the conversation — quizzes, forms, dropdowns, product cards, ECharts charts, math function plots, Mermaid flowcharts/mind maps, KaTeX formulas, and step-by-step algorithm animations. User interactions flow back to the agent as plain-language messages, closing the loop.
6
+
7
+ The UI protocol is [A2UI v0.9](https://github.com/google/A2UI) (a declarative Agent-to-UI protocol); rendering is powered by Ant Design X's official implementation, [`@ant-design/x-card`](https://www.npmjs.com/package/@ant-design/x-card).
8
+
9
+ 📸 **[Feature showcase with GIFs → DEMO.md](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/DEMO.md)**
10
+
11
+ ![Quiz interaction](https://raw.githubusercontent.com/baihui-ai/a2ui-render-in-dsh/main/docs/demo-quiz.gif)
12
+
13
+ ---
14
+
15
+ ## Design
16
+
17
+ ### Architecture: one package, two halves
18
+
19
+ ```
20
+ a2ui-render-in-dsh (one npm package, a dsh bundle)
21
+ ├─ Host half lib/index.js cordis plugin registering two agent tools
22
+ │ ├─ a2ui_render renders a card (slim ~140-token description, always visible)
23
+ │ └─ a2ui_catalog returns the full component catalog & authoring
24
+ │ rules (~975 tokens, loaded on demand, once)
25
+ └─ Client half lib/client.js browser bundle registering the a2ui_render toolview
26
+ ├─ x-card engine (A2UI command stream, data binding, action resolution)
27
+ ├─ component catalog implementations (18 components, themed via --dsw-* tokens)
28
+ └─ ECharts 6 / Mermaid 11 / KaTeX (fonts inlined) all bundled — zero external requests
29
+ ```
30
+
31
+ ### Key design decisions
32
+
33
+ **1. Adaptive rendering, decided by the model.** Whether to use UI is entirely the model's call: the tool contract says "only when a card clearly beats prose". Verified both ways — "quiz me" triggers a card, "explain X" stays plain text.
34
+
35
+ **2. Skill-style context design (catalog on demand).** The full component catalog is NOT inlined in the tool description; it lives in a second tool, `a2ui_catalog`. Always-visible cost drops from ~1,200 to ~211 tokens (−82%). The model calls the catalog once before its first card in a conversation and reuses it for later cards; conversations that never draw a card pay nothing. The host validates component names and errors with a "call a2ui_catalog" hint, so the model can't silently guess wrong.
36
+
37
+ **3. Non-blocking answers over the native message path.** Submissions need no custom server channel: the client sends the submission through dsh's own `session.prompt` RPC as an ordinary user message. Messages are **plain language** (button label + chosen values, multi-line for forms) — readable for humans, parseable for the model, no raw JSON in the conversation:
38
+
39
+ ```
40
+ Submit signup
41
+ City: Shanghai
42
+ Tracks: Backend, Data Analysis
43
+ ```
44
+
45
+ **4. Semantic submit locking.** Cards with input components (forms/quizzes) lock after their first submission — inputs disable, the chosen values stay highlighted, and the submission is recorded (persisted to localStorage; a page reload restores the locked state, values, and timestamp). Buttons on cards WITHOUT inputs (product cards) are treated as query buttons and stay clickable. A per-button `submit: true|false` overrides the heuristic.
46
+
47
+ **5. Let the model do only what it's good at.** Function plotting: the model writes an expression (`tan(x)`); sampling and asymptote breaking are done by a built-in **safe expression evaluator** (whitelist shunting-yard parser, no eval, injection is rejected) — hand-enumerating data points would inevitably fail. Algorithm animations: the model simulates the algorithm into per-step frames (an LLM strength); playback, transitions, and controls belong to the component.
48
+
49
+ **6. Fully self-contained display stack.** ECharts, Mermaid, and KaTeX (woff2 fonts as data URIs) are all bundled (~5MB, served locally, loaded once) — no CDN, works offline; light/dark theme follows the page automatically.
50
+
51
+ ## Highlights
52
+
53
+ - 🎯 **Adaptive**: the model chooses text vs. card; verified reliable in both directions
54
+ - 🪶 **Context-friendly**: skill-style catalog design, ~211 tokens always-visible
55
+ - 💬 **Elegant answers**: plain-language submissions, not raw JSON strings
56
+ - 🔒 **Submit-once locking**: forms can't double-submit, records persist; query buttons unaffected
57
+ - 📊 **Full visualization family**: ECharts charts/dashboards, function plots, all Mermaid diagram types, KaTeX formulas (matrices are forced into formula rendering), video
58
+ - 🎬 **Algorithm animations**: array/bars and grid/matrix forms, auto-detected; auto-plays once per card (component remounts never replay), ↻ manual replay, stepping, progress bar, legend
59
+ - ⛶ **Fullscreen zoom**: mind maps/flowcharts/charts/images go fullscreen with fit-to-viewport, wheel zoom + drag pan
60
+ - 🧱 **Multi-column layout**: Grid for product comparisons and chart dashboards
61
+ - 🎛️ **Complete input states**: dropdown single/multi select, preselection (dataModel seeds), component- and option-level disabling
62
+ - 🌓 **Light/dark themes** across every component
63
+ - ✅ **Verified**: jsdom interaction tests plus real-chromium screenshot/recording verification of the full pipeline
64
+
65
+ ## Built with
66
+
67
+ | Layer | Technology | Role |
68
+ |---|---|---|
69
+ | UI protocol | [A2UI v0.9](https://github.com/google/A2UI) | Open protocol for agents to describe UIs as declarative JSON |
70
+ | Protocol runtime | [`@ant-design/x-card`](https://www.npmjs.com/package/@ant-design/x-card) 2.9 (Ant Design X) | A2UI command-stream processing, data binding, action resolution |
71
+ | Charts | [Apache ECharts](https://echarts.apache.org) 6.1 | Data charts, dashboards, function plots, bar animations |
72
+ | Diagrams | [Mermaid](https://mermaid.js.org) 11.17 | Flowcharts, mind maps, sequence diagrams, gantt, and more |
73
+ | Formulas | [KaTeX](https://katex.org) 0.18 | LaTeX rendering (woff2 fonts inlined as data URIs) |
74
+ | View layer | [React](https://react.dev) 18 | Provided by dsh web's module table (externalized, not bundled) |
75
+ | Plugin framework | [cordis](https://github.com/cordiverse/cordis) + `@deepseek-ai/dsh-tools` | dsh's plugin system; agent tool registration (`defineTool`) |
76
+ | Build | [esbuild](https://esbuild.github.io) | Dual-half bundling, KaTeX font inlining, module-loader wrapper |
77
+
78
+ ## Component catalog
79
+
80
+ | Component | Props | Notes |
81
+ |---|---|---|
82
+ | `Column` / `Row` | `children, gap?` | Vertical / horizontal layout |
83
+ | `Grid` | `children, columns?, gap?, minWidth?` | **Multi-column**: fixed column count (2–4 recommended) or auto-fit by `minWidth` |
84
+ | `Card` | `children, title?` | Bordered group |
85
+ | `List` | `children, direction?` | List container |
86
+ | `Divider` | — | Separator |
87
+ | `Text` | `text, variant?: h1\|h2\|h3\|body\|caption\|strong` | Text |
88
+ | `Image` | `url, alt?, width?, height?` | Images (incl. GIF), built-in fullscreen zoom |
89
+ | `Tag` | `text, color?: blue\|green\|red\|orange\|gray` | Tag/badge |
90
+ | `Math` | `tex, block?` | **KaTeX** formulas (fonts inlined, zero external requests); matrices/vectors must use this |
91
+ | `Mermaid` | `code, caption?` | **Mermaid 11**: flowchart/mindmap/sequence/gantt etc., built-in fullscreen zoom |
92
+ | `Chart` | `option, height?, functions?, xMin?, xMax?, samples?, yClip?` | **ECharts 6**: data mode (option verbatim) + function-plot mode (expressions sampled automatically, asymptote breaks), built-in fullscreen |
93
+ | `Video` | `url, poster?, loop?, muted?, autoplay?` | HTML5 video (mp4/webm) |
94
+ | `Anim` | `frames, interval?, height?, autoplay?, labels?` | **Algorithm animation**: bars and grid/matrix forms auto-detected; auto-plays once per card per tab, ↻ replay / pause / step / reset / progress / legend |
95
+ | `Button` | `label, variant?, submit?, action: {event: {name, context?}}` | Sends the submission; `submit` explicitly controls card locking |
96
+ | `MultipleChoice` | `options, bind, maxAllowedSelections?, disabled?` | Flat multi/single select (`maxAllowedSelections: 1` = single), per-option disable |
97
+ | `Select` | `options, bind, label?, placeholder?, multiple?, maxAllowedSelections?, disabled?` | **Dropdown**: single stores a value, multi stores an array; option descriptions/disabling |
98
+ | `CheckBox` | `label, bind, disabled?` | Boolean toggle |
99
+ | `TextField` | `label?, placeholder?, multiline?, bind, disabled?` | Text input |
100
+
101
+ Common to inputs: **preselect** by seeding `dataModel` at the bind path; **disable** via component-level `disabled: true` or per-option `disabled`. Data binding: `bind` is a write path WITHOUT a leading slash; display props read live values with `{"path": "/x"}` (WITH a slash).
102
+
103
+ ## Installation
104
+
105
+ ### Prerequisites
106
+
107
+ | Requirement | Notes |
108
+ |---|---|
109
+ | dsh | `@deepseek-ai/dsh` ≥ 0.1.1-rc.1 with an initialized web profile (run `dsh web` once before installing) |
110
+ | Node.js | ≥ 20 (with npm) |
111
+
112
+ ### Option A · From source (recommended for now)
113
+
114
+ ```sh
115
+ # 1. Clone and build
116
+ git clone https://github.com/baihui-ai/a2ui-render-in-dsh.git
117
+ cd a2ui-render-in-dsh
118
+ npm install
119
+ npm run build
120
+ # Build emits two files: lib/index.js (host plugin) + lib/client.js (browser bundle).
121
+ # lib/ is not committed — you MUST build after cloning or dsh won't find the entry.
122
+
123
+ # 2. Install into dsh's web profile (link mode)
124
+ dsh plugin --profile web add link:$(pwd)
125
+ # Equivalent to pnpm add link:<path> inside the profile; it also appends
126
+ # a2ui-render-in-dsh to the profile's dsh.profile.bundles automatically.
127
+
128
+ # 3. Start / restart dsh web
129
+ dsh web
130
+ ```
131
+
132
+ Why link mode: upgrading is just `git pull && npm run build` plus a dsh web restart — no reinstall.
133
+
134
+ ### Option B · From npm (once the package is published)
135
+
136
+ ```sh
137
+ dsh plugin --profile web add a2ui-render-in-dsh
138
+ dsh web
139
+ ```
140
+
141
+ ### Verify in three steps
142
+
143
+ ```sh
144
+ # 1) the composed tree contains the plugin entry
145
+ dsh --profile web --dump-config | grep -B1 -A1 a2ui-render-in-dsh
146
+ # expected: - id: a2ui
147
+ # name: a2ui-render-in-dsh
148
+
149
+ # 2) the frontend bundle is served (substitute your port from the dsh web banner)
150
+ curl -s http://127.0.0.1:<port>/ | grep -o "a2ui-render-in-dsh/client.js[^\"]*"
151
+ # expected: a2ui-render-in-dsh/client.js?rev=<hash>
152
+ ```
153
+
154
+ 3) Open dsh web and say: **"Quiz me with an interactive card"** — a clickable multiple-choice card means it works (the model calls `a2ui_catalog` once before rendering; that's by design). More prompts: [DEMO.md](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/DEMO.md#one-stop-prompt-list).
155
+
156
+ ### Upgrade & uninstall
157
+
158
+ ```sh
159
+ # upgrade (link install): rebuild after pulling, then restart dsh web
160
+ git pull && npm run build
161
+
162
+ # uninstall: removes the dependency and the bundles entry, then restart dsh web
163
+ dsh plugin --profile web remove a2ui-render-in-dsh
164
+ ```
165
+
166
+ ### Troubleshooting
167
+
168
+ | Symptom | Cause | Fix |
169
+ |---|---|---|
170
+ | dsh web fails to boot / plugin missing | not built after cloning, `lib/` absent | `npm run build`, restart |
171
+ | Code changed but UI unchanged | bundles are content-hashed at dsh boot | rebuild, then **restart dsh web** |
172
+ | Cards render as generic tool rows | client bundle not loaded | run verify step 2; check `/plugins/a2ui-render-in-dsh/` requests in the browser console |
173
+ | Tool errors with `unknown component` | the model guessed without reading the catalog | self-correcting by design: the error tells the model to call `a2ui_catalog` and retry |
174
+ | Model answers in text, no card | the adaptive contract judged prose better | say "with an interactive card" in the prompt to trigger reliably |
175
+
176
+ ### Notes
177
+
178
+ - The client bundle is ~5MB (ECharts + Mermaid + KaTeX built in, zero external requests), served locally and cached by the browser after first load
179
+ - Submission records live in browser `localStorage`, the animation played-once latch in `sessionStorage` — both local-only; the submission message itself is in the conversation, so the model side is unaffected across devices
180
+
181
+ ## How it works
182
+
183
+ 1. The model decides a card helps → calls `a2ui_catalog` once (first card in the conversation) → calls `a2ui_render` with an A2UI v0.9 component adjacency list
184
+ 2. The client toolview renders the arguments into a live interactive card via the x-card engine
185
+ 3. The user clicks a Button → the plugin composes a plain-language summary → sends it through `session.prompt` as a user message → the model continues (grading / next step)
186
+ 4. Form cards lock and record after submission; query buttons stay clickable
187
+
188
+ ## Development
189
+
190
+ ```sh
191
+ npm run watch # incremental dual-half builds (restart dsh web to apply)
192
+ ```
193
+
194
+ | File | Responsibility |
195
+ |---|---|
196
+ | `src/host/index.js` | Both tool definitions: `a2ui_render` (schema + component-name validation), `a2ui_catalog` (the full authoring guide) |
197
+ | `src/client/index.jsx` | Client plugin entry (locale + toolview registration) |
198
+ | `src/client/toolview.jsx` | Card rendering, submission composing, locking & localStorage records |
199
+ | `src/client/components.jsx` | Interactive catalog (layout/text/button/choice/dropdown/input) |
200
+ | `src/client/components-viz.jsx` | Chart / Mermaid / Math / Video / Anim |
201
+ | `src/client/zoomable.jsx` | Fullscreen zoom shell (Fullscreen API + zoom/pan) |
202
+ | `src/client/expr.js` | Safe expression evaluator for function plots (whitelist, no eval) |
203
+ | `scripts/build.mjs` | esbuild dual-half build (KaTeX font data-URI inlining, `window.__ModuleLoader__` wrapper) |
204
+
205
+ The client bundle externalizes only `react` / `react/jsx-runtime` (provided by dsh's module table); everything else is inlined.
206
+
207
+ ## Known limits
208
+
209
+ - Streaming card render: a placeholder row shows until the args JSON parses completely (no partial rendering)
210
+ - No dedicated animation form for graph/tree algorithms yet (BFS, tree rotations); the array and matrix forms cover sorting, searching, DP, etc.
211
+ - Side-by-side cards across separate tool calls are not possible (one call per row in the dsh conversation); `Grid` covers multi-column within one call
212
+
213
+ ## License
214
+
215
+ MIT
package/README.zh.md ADDED
@@ -0,0 +1,214 @@
1
+ # a2ui-render-in-dsh
2
+
3
+ [English](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/README.md) | 中文
4
+
5
+ **dsh web 的 A2UI 交互卡片插件**:让 Agent 在对话流里自适应地渲染**可交互、可视化的 UI 卡片**——选择题、表单、下拉、商品卡、ECharts 图表、数学函数绘图、Mermaid 流程图/思维导图、KaTeX 公式、算法过程动画——用户的点击/勾选/输入以自然语言消息回传给 Agent,形成完整的交互闭环。
6
+
7
+ UI 协议基于 [A2UI v0.9](https://github.com/google/A2UI)(Agent-to-UI 声明式界面协议),渲染引擎使用 Ant Design X 官方实现 [`@ant-design/x-card`](https://www.npmjs.com/package/@ant-design/x-card)。
8
+
9
+ 📸 **[功能示例(含动图)→ DEMO.md](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/DEMO.zh.md)**
10
+
11
+ ![做题交互](https://raw.githubusercontent.com/baihui-ai/a2ui-render-in-dsh/main/docs/demo-quiz.gif)
12
+
13
+ ---
14
+
15
+ ## 设计
16
+
17
+ ### 架构:一包两端
18
+
19
+ ```
20
+ a2ui-render-in-dsh (一个 npm 包,dsh bundle)
21
+ ├─ 宿主端 lib/index.js cordis 插件,注册两个 Agent 工具
22
+ │ ├─ a2ui_render 渲染卡片(描述仅 ~140 token,常驻)
23
+ │ └─ a2ui_catalog 返回完整组件目录与写卡规则(~975 token,按需一次)
24
+ └─ 客户端 lib/client.js 浏览器 bundle,注册 a2ui_render 的专属 toolview
25
+ ├─ x-card 引擎(A2UI 命令流、数据绑定、action 解析)
26
+ ├─ 组件目录实现(18 个组件,跟随 --dsw-* 主题令牌)
27
+ └─ ECharts 6 / Mermaid 11 / KaTeX(字体内联)全部打入 bundle,零外部请求
28
+ ```
29
+
30
+ ### 关键设计决策
31
+
32
+ **1. 自适应渲染,由模型判断。** 是否用 UI 完全交给模型:工具契约写明"仅当卡片明显优于纯文本时调用"。实测:「出题考我」触发卡片,「解释一下 X」保持纯文本。
33
+
34
+ **2. skill 式上下文设计(目录按需加载)。** 完整组件目录不内联在工具描述里,而是放进 `a2ui_catalog` 工具:常驻上下文从 ~1200 token 降到 ~211 token(-82%);模型首次画卡前调用一次目录,同会话后续卡片直接复用;不画卡的会话零目录开销。服务端校验未知组件名并报错引导查目录,防止模型跳过目录瞎猜。
35
+
36
+ **3. 非阻塞回传,复用原生消息通路。** 卡片提交不需要自定义 server 通道:客户端通过 dsh 自身的 `session.prompt` RPC 把提交内容作为普通用户消息发回会话。消息是**自然语言**(按钮文案 + 所选内容,多字段换行列出),对人可读、对模型可解析,不污染对话观感:
37
+
38
+ ```
39
+ 提交报名
40
+ 城市:上海
41
+ 方向:后端开发、数据分析
42
+ ```
43
+
44
+ **4. 语义化的提交锁定。** 含输入组件的卡片(表单/做题)提交后整卡锁定并记录(localStorage 持久化,刷新后恢复锁定态、已选值和提交时间);无输入组件的卡片(商品卡)上的按钮自动识别为**查询按钮**,可反复点击。按钮级 `submit: true|false` 可显式覆盖。
45
+
46
+ **5. 模型只做擅长的事。** 数学函数绘图:模型只写表达式(`tan(x)`),采样、渐近线断线由内置**安全表达式求值器**完成(白名单 shunting-yard 解析,非 eval,注入即拒绝)——让模型手工枚举几百个数据点必然画错。算法动画:模型模拟算法输出逐帧状态(这是 LLM 强项),播放、过渡、控件由组件完成。
47
+
48
+ **6. 展示组件全部自包含。** ECharts、Mermaid、KaTeX(含 woff2 字体 data-URI)全部打进 bundle(~5MB,本地服务一次加载),无 CDN 依赖、可离线;明暗主题按页面背景亮度自动跟随。
49
+
50
+ ## 亮点
51
+
52
+ - 🎯 **自适应**:模型自行判断"文本还是卡片",双向实测可靠
53
+ - 🪶 **上下文友好**:skill 式目录设计,常驻开销 ~211 token
54
+ - 💬 **优雅回传**:自然语言提交消息,非 JSON 裸串
55
+ - 🔒 **提交即锁定**:表单防重复提交,记录持久化,查询按钮不受影响
56
+ - 📊 **可视化全家桶**:ECharts 图表/仪表盘、函数绘图、Mermaid 全图型、KaTeX 公式(矩阵强制公式化渲染)、视频
57
+ - 🎬 **算法动画**:数组/柱状 + 网格/矩阵双形态,自动识别;每卡只自动播一遍(组件重挂载不重播),↻ 手动重播、单步、进度条、图例
58
+ - ⛶ **全屏放大**:思维导图/流程图/图表/图片一键全屏,自动适配视口,滚轮缩放 + 拖拽平移
59
+ - 🧱 **一行多列**:Grid 布局做商品对比、图表仪表盘
60
+ - 🎛️ **完整输入态**:下拉单选/多选、预选中(dataModel 初值)、组件级/选项级禁用
61
+ - 🌓 **明暗主题**:全组件跟随 dsh 主题令牌
62
+ - ✅ **可验证**:jsdom 交互测试 + chromium 真实渲染截图/录屏验证全链路
63
+
64
+ ## 技术栈
65
+
66
+ | 层 | 技术 | 用途 |
67
+ |---|---|---|
68
+ | UI 协议 | [A2UI v0.9](https://github.com/google/A2UI) | Agent 用声明式 JSON 描述界面的开放协议 |
69
+ | 协议运行时 | [`@ant-design/x-card`](https://www.npmjs.com/package/@ant-design/x-card) 2.9(Ant Design X) | A2UI 命令流处理、数据绑定、action 解析 |
70
+ | 图表 | [Apache ECharts](https://echarts.apache.org) 6.1 | 数据图表、仪表盘、函数绘图、柱状动画 |
71
+ | 图示 | [Mermaid](https://mermaid.js.org) 11.17 | 流程图、思维导图、时序图、甘特图等全图型 |
72
+ | 公式 | [KaTeX](https://katex.org) 0.18 | LaTeX 公式渲染(woff2 字体以 data-URI 内联) |
73
+ | 视图层 | [React](https://react.dev) 18 | 由 dsh web 模块表提供(外置,不打入 bundle) |
74
+ | 插件框架 | [cordis](https://github.com/cordiverse/cordis) + `@deepseek-ai/dsh-tools` | dsh 插件体系;Agent 工具注册(`defineTool`) |
75
+ | 构建 | [esbuild](https://esbuild.github.io) | 宿主/客户端双端打包、KaTeX 字体内联、模块加载器封装 |
76
+
77
+ ## 组件目录
78
+
79
+ | 组件 | 属性 | 说明 |
80
+ |---|---|---|
81
+ | `Column` / `Row` | `children, gap?` | 纵/横布局 |
82
+ | `Grid` | `children, columns?, gap?, minWidth?` | **一行多列**:固定列数(推荐 2–4)或按 `minWidth` 自适应换行 |
83
+ | `Card` | `children, title?` | 带边框分组 |
84
+ | `List` | `children, direction?` | 列表容器 |
85
+ | `Divider` | — | 分隔线 |
86
+ | `Text` | `text, variant?: h1\|h2\|h3\|body\|caption\|strong` | 文本 |
87
+ | `Image` | `url, alt?, width?, height?` | 图片(含 GIF),自带全屏放大 |
88
+ | `Tag` | `text, color?: blue\|green\|red\|orange\|gray` | 标签 |
89
+ | `Math` | `tex, block?` | **KaTeX** 公式(字体内联零外部请求);矩阵/向量必须走此组件 |
90
+ | `Mermaid` | `code, caption?` | **Mermaid 11**:流程图/思维导图/时序图/甘特图等,自带全屏放大 |
91
+ | `Chart` | `option, height?, functions?, xMin?, xMax?, samples?, yClip?` | **ECharts 6**:数据模式(option 透传)+ 函数绘图模式(表达式自动采样、渐近线断线),自带全屏 |
92
+ | `Video` | `url, poster?, loop?, muted?, autoplay?` | HTML5 视频(mp4/webm) |
93
+ | `Anim` | `frames, interval?, height?, autoplay?, labels?` | **算法动画**:数组/柱状与网格/矩阵双形态自动识别;每卡每页签只自动播一遍,↻ 重播/暂停/单步/重置/进度条/图例 |
94
+ | `Button` | `label, variant?, submit?, action: {event: {name, context?}}` | 触发回传;`submit` 显式控制是否锁卡 |
95
+ | `MultipleChoice` | `options, bind, maxAllowedSelections?, disabled?` | 平铺多选/单选(`maxAllowedSelections: 1` 单选),选项级禁用 |
96
+ | `Select` | `options, bind, label?, placeholder?, multiple?, maxAllowedSelections?, disabled?` | **下拉选择**:单选存值、多选存数组,选项描述/禁用 |
97
+ | `CheckBox` | `label, bind, disabled?` | 布尔勾选 |
98
+ | `TextField` | `label?, placeholder?, multiline?, bind, disabled?` | 文本输入 |
99
+
100
+ 输入组件通用:**预选中**在 `dataModel` 给 bind 路径设初值;**禁用**用组件级 `disabled: true` 或选项级 `disabled`。数据绑定:`bind` 为不带前导斜杠的写入路径;展示属性用 `{"path": "/x"}`(带斜杠)读实时值。
101
+
102
+ ## 安装
103
+
104
+ ### 前置要求
105
+
106
+ | 要求 | 说明 |
107
+ |---|---|
108
+ | dsh | `@deepseek-ai/dsh` ≥ 0.1.1-rc.1,且 web profile 已初始化(装插件前先运行过一次 `dsh web`) |
109
+ | Node.js | ≥ 20(含 npm) |
110
+
111
+ ### 方式 A · 源码安装(当前推荐)
112
+
113
+ ```sh
114
+ # 1. 克隆并构建
115
+ git clone https://github.com/baihui-ai/a2ui-render-in-dsh.git
116
+ cd a2ui-render-in-dsh
117
+ npm install
118
+ npm run build
119
+ # 构建产出两个文件:lib/index.js(宿主端插件)+ lib/client.js(浏览器 bundle)
120
+ # lib/ 不在 git 里,克隆后必须先构建,否则 dsh 启动时找不到入口
121
+
122
+ # 2. 以 link 方式装进 dsh 的 web profile
123
+ dsh plugin --profile web add link:$(pwd)
124
+ # 该命令等价于在 profile 里 pnpm add link:<路径>,并自动把
125
+ # a2ui-render-in-dsh 追加到 profile 的 dsh.profile.bundles
126
+
127
+ # 3. 启动 / 重启 dsh web
128
+ dsh web
129
+ ```
130
+
131
+ link 方式的好处:后续升级只需 `git pull && npm run build` 再重启 dsh web,无需重装。
132
+
133
+ ### 方式 B · npm 安装(包发布到 npm 后)
134
+
135
+ ```sh
136
+ dsh plugin --profile web add a2ui-render-in-dsh
137
+ dsh web
138
+ ```
139
+
140
+ ### 三步验证
141
+
142
+ ```sh
143
+ # ① 组合树里出现本插件条目
144
+ dsh --profile web --dump-config | grep -B1 -A1 a2ui-render-in-dsh
145
+ # 期望输出:- id: a2ui
146
+ # name: a2ui-render-in-dsh
147
+
148
+ # ② 前端 bundle 正常下发(<port> 换成你的端口,默认见 dsh web 启动输出)
149
+ curl -s http://127.0.0.1:<port>/ | grep -o "a2ui-render-in-dsh/client.js[^\"]*"
150
+ # 期望输出:a2ui-render-in-dsh/client.js?rev=<hash>
151
+ ```
152
+
153
+ ③ 打开 dsh web 对它说:**「用交互卡片出一道单选题考我」**——出现可点选的选择题卡片即安装成功(模型会先调一次 `a2ui_catalog` 再渲染,属正常流程)。更多试玩提示词见 [DEMO.zh.md](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/DEMO.zh.md#一站式体验提示词)。
154
+
155
+ ### 升级与卸载
156
+
157
+ ```sh
158
+ # 升级(link 安装):拉新代码重新构建,重启 dsh web 即生效
159
+ git pull && npm run build
160
+
161
+ # 卸载:从 profile 移除(依赖与 bundles 条目会一并清掉),重启 dsh web
162
+ dsh plugin --profile web remove a2ui-render-in-dsh
163
+ ```
164
+
165
+ ### 故障排查
166
+
167
+ | 现象 | 原因 | 解决 |
168
+ |---|---|---|
169
+ | dsh web 启动报找不到入口 / 插件未加载 | 克隆后没有构建,`lib/` 不存在 | `npm run build` 后重启 |
170
+ | 改了代码但界面没变化 | bundle 在 dsh 启动时按内容哈希缓存 | 重新构建后**重启 dsh web** |
171
+ | 卡片显示为普通工具行而非交互卡片 | 客户端 bundle 未加载 | 用上面第②步确认下发;浏览器控制台看 `/plugins/a2ui-render-in-dsh/` 请求是否 200 |
172
+ | 工具报 `unknown component` 错误 | 模型未查目录就猜组件名 | 属自纠错设计:错误信息会引导模型调 `a2ui_catalog` 后重试,无需人工干预 |
173
+ | 模型不渲染卡片、只回文本 | 自适应判断认为文本更合适 | 提示词里点明「用交互卡片」即可稳定触发 |
174
+
175
+ ### 其他说明
176
+
177
+ - 客户端 bundle 约 5MB(ECharts + Mermaid + KaTeX 全部内置、零外部请求),由 dsh 本地服务,浏览器首次加载后缓存
178
+ - 提交锁定记录存浏览器 `localStorage`、动画"已播过"闩锁存 `sessionStorage`,均为本地行为;提交消息本身在会话记录里,跨设备不影响模型侧
179
+
180
+ ## 工作方式
181
+
182
+ 1. 模型对话中判断需要卡片 → 首次先调 `a2ui_catalog` 加载组件目录 → 调 `a2ui_render` 传入 A2UI v0.9 组件邻接表
183
+ 2. 客户端 toolview 用 x-card 引擎把参数渲染成实时交互卡片
184
+ 3. 用户点击 Button → 插件组装自然语言摘要 → 经 `session.prompt` 作为用户消息发回 → 模型继续对话(判分/下一步)
185
+ 4. 表单卡提交后锁定并记录;查询按钮可反复点击
186
+
187
+ ## 开发
188
+
189
+ ```sh
190
+ npm run watch # 双端增量构建(改完重启 dsh web 生效)
191
+ ```
192
+
193
+ | 文件 | 职责 |
194
+ |---|---|
195
+ | `src/host/index.js` | 两个工具的定义:`a2ui_render`(含参数 schema 与组件名校验)、`a2ui_catalog`(完整写卡指南) |
196
+ | `src/client/index.jsx` | 客户端插件入口(locale + toolview 注册) |
197
+ | `src/client/toolview.jsx` | 卡片渲染、提交消息组装、锁定与 localStorage 记录 |
198
+ | `src/client/components.jsx` | 交互组件目录(布局/文本/按钮/选择/下拉/输入) |
199
+ | `src/client/components-viz.jsx` | Chart / Mermaid / Math / Video / Anim |
200
+ | `src/client/zoomable.jsx` | 全屏放大外壳(Fullscreen API + 缩放平移) |
201
+ | `src/client/expr.js` | 函数绘图的安全表达式求值器(白名单,非 eval) |
202
+ | `scripts/build.mjs` | esbuild 双端构建(KaTeX 字体 data-URI 内联、`window.__ModuleLoader__` 封装) |
203
+
204
+ 客户端 bundle 只外置 `react` / `react/jsx-runtime`(由 dsh 模块表提供),其余全部内联。
205
+
206
+ ## 已知边界
207
+
208
+ - 卡片流式渲染:参数 JSON 完整解析前显示占位行(不做部分渲染)
209
+ - 图/树类算法动画(BFS、树旋转)暂无专用形态(现有数组/矩阵两形态覆盖排序、查找、DP 等)
210
+ - 跨调用的多卡并排做不到(dsh 会话流一条工具调用一行);一次调用内 `Grid` 覆盖一行多列需求
211
+
212
+ ## License
213
+
214
+ MIT
@@ -0,0 +1,5 @@
1
+ # a2ui-render-in-dsh: agent-rendered interactive A2UI cards (quiz options, forms, product cards).
2
+ # The host half registers the a2ui_render tool; the client half owns its toolview.
3
+ - insert:
4
+ - id: a2ui
5
+ name: a2ui-render-in-dsh