a2ui-render-in-dsh 0.1.1 → 0.1.2
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 +80 -34
- package/README.zh.md +79 -33
- package/lib/client.js +698 -529
- package/lib/index.js +141 -58
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/README.zh.md)
|
|
4
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,
|
|
5
|
+
**A2UI interactive cards for the dsh web UI**: the agent adaptively renders **interactive, visual UI cards** right inside the conversation — quizzes, forms, multi-step wizards, dropdowns, date pickers, product cards, sortable/filterable tables, ECharts charts, China map choropleths, math function plots, Mermaid flowcharts/mind maps, KaTeX formulas, Markdown long-form, image uploads, signature pads, and step-by-step algorithm animations. User interactions flow back to the agent as plain-language messages (images included), cards **stream in progressively** and can be **updated in place**, and everything visible is one click away from the clipboard.
|
|
6
6
|
|
|
7
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
8
|
|
|
9
|
-
📸 **[Feature showcase with GIFs → DEMO.md](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/DEMO.md)**
|
|
9
|
+
📸 **[Feature showcase with GIFs → DEMO.md](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/DEMO.md)** · 🗺️ **[Scenario × component map](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/docs/SCENARIOS.md)**
|
|
10
10
|
|
|
11
|
-

|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -18,21 +18,25 @@ The UI protocol is [A2UI v0.9](https://github.com/google/A2UI) (a declarative Ag
|
|
|
18
18
|
|
|
19
19
|
```
|
|
20
20
|
a2ui-render-in-dsh (one npm package, a dsh bundle)
|
|
21
|
-
├─ Host half lib/index.js cordis plugin registering
|
|
22
|
-
│ ├─ a2ui_render renders a card (slim ~
|
|
21
|
+
├─ Host half lib/index.js cordis plugin registering three agent tools
|
|
22
|
+
│ ├─ a2ui_render renders a card (slim ~220-token description, always visible)
|
|
23
|
+
│ ├─ a2ui_update updates an already-rendered card in place (progress,
|
|
24
|
+
│ │ long tasks, live dashboards) via its surfaceId
|
|
23
25
|
│ └─ a2ui_catalog returns the full component catalog & authoring
|
|
24
|
-
│ rules (
|
|
25
|
-
└─ Client half lib/client.js browser bundle registering the
|
|
26
|
+
│ rules (loaded on demand, once per conversation)
|
|
27
|
+
└─ Client half lib/client.js browser bundle registering the toolviews
|
|
26
28
|
├─ x-card engine (A2UI command stream, data binding, action resolution)
|
|
27
|
-
├─ component catalog implementations (
|
|
28
|
-
|
|
29
|
+
├─ component catalog implementations (44 components, themed via --dsw-* tokens)
|
|
30
|
+
├─ streaming renderer (truncated-JSON repair → cards appear while the model types)
|
|
31
|
+
└─ ECharts 6 / Mermaid 11 / KaTeX (fonts inlined) / China geoJSON all bundled
|
|
32
|
+
— zero external requests
|
|
29
33
|
```
|
|
30
34
|
|
|
31
35
|
### Key design decisions
|
|
32
36
|
|
|
33
|
-
**1.
|
|
37
|
+
**1. Proactive rendering, decided by the model — anchored on UI's purposes.** The tool contract frames the judgment as: would a card serve any of UI's four purposes better than prose? **Act** (the user must answer/choose/fill/adjust — render a form), **browse** (the user wants to see or scan data — statistics, rankings, distributions, trends get a chart/table/map, and uncertain data never cancels the card: chart the best known, label the period, caveat in prose), **understand** (structure or notation aids comprehension — math, code, flows, stepwise processes), or **feedback** (long multi-step work gets a progress card advanced via `a2ui_update`). None of the four → prose. Cards always **pair with prose**: the takeaway lives in 1–3 sentences of normal text, the structured content in the card, with no duplication. Grounded in HCI research (Norman's gulfs, the keyhole effect, external cognition) and verified with keyword-free prompts across all purposes plus prose negatives.
|
|
34
38
|
|
|
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
|
|
39
|
+
**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 stays at ~220 tokens even as the catalog grew to 44 components. 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
40
|
|
|
37
41
|
**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
42
|
|
|
@@ -46,16 +50,25 @@ Tracks: Backend, Data Analysis
|
|
|
46
50
|
|
|
47
51
|
**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
52
|
|
|
49
|
-
**6. Fully self-contained display stack.** ECharts, Mermaid,
|
|
53
|
+
**6. Fully self-contained display stack.** ECharts, Mermaid, KaTeX (woff2 fonts as data URIs), and the China province geoJSON are all bundled (~5.5MB, served locally, loaded once) — no CDN, works offline; light/dark theme follows the page automatically.
|
|
54
|
+
|
|
55
|
+
**7. Live cards: streaming in, updating in place.** Cards render progressively while the model is still emitting JSON (a tolerant parser repairs the truncated stream and mounts complete components early), so a big dashboard appears piece by piece instead of after a long pause. And a rendered card is not frozen: `a2ui_update` addresses it by `surfaceId` to patch components or data in place — progress bars that actually move, task cards that fill in results, dashboards that refresh. Updates persist and replay after a page reload.
|
|
56
|
+
|
|
57
|
+
**8. Answers beyond text.** `Upload` (photos) and `Signature` (hand-drawn canvas) send images back through dsh's native prompt channel as real image parts — the model sees the picture, not a placeholder. `Suggestions` renders tappable follow-up chips that send themselves as the next user message. Voice recording is deliberately excluded: dsh's prompt channel carries text + images only.
|
|
50
58
|
|
|
51
59
|
## Highlights
|
|
52
60
|
|
|
53
61
|
- 🎯 **Adaptive**: the model chooses text vs. card; verified reliable in both directions
|
|
54
|
-
- 🪶 **Context-friendly**: skill-style catalog design, ~
|
|
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
|
-
-
|
|
58
|
-
-
|
|
62
|
+
- 🪶 **Context-friendly**: skill-style catalog design, ~220 tokens always-visible for 44 components
|
|
63
|
+
- 💬 **Elegant answers**: plain-language submissions, not raw JSON strings; photos & signatures return as real images
|
|
64
|
+
- 🔒 **Submit-once locking**: forms can't double-submit, records persist, a "refill" button reopens them; query buttons unaffected
|
|
65
|
+
- ⚡ **Streaming render**: cards appear progressively while the model is still writing the JSON
|
|
66
|
+
- 🔄 **In-place updates**: `a2ui_update` patches a live card by surfaceId — moving progress bars, task cards that finish themselves, refreshing dashboards; survives page reloads
|
|
67
|
+
- 📊 **Full visualization family**: ECharts charts/dashboards, function plots, China map choropleth, all Mermaid diagram types, KaTeX formulas (matrices are forced into formula rendering), image compare slider, video
|
|
68
|
+
- 🎬 **Algorithm animations**: array/bars, grid/matrix, and graph/tree forms, auto-detected; auto-plays once per card (component remounts never replay), ↻ manual replay, stepping, progress bar, legend
|
|
69
|
+
- 🧾 **Interactive tables**: click-to-sort (numeric-aware), filter box, pagination, copy as TSV, CSV export, editable-table input
|
|
70
|
+
- 🧭 **Rich answer kit**: multi-step Wizard, Calendar date picking, drag-free RankList ordering, Suggestions follow-up chips, Upload, Signature
|
|
71
|
+
- 📋 **Quick copy everywhere**: Stat tiles click-copy, tables copy/export, CodeBlock copy, formulas copy their LaTeX, charts download as PNG, Markdown copies its source
|
|
59
72
|
- ⛶ **Fullscreen zoom**: mind maps/flowcharts/charts/images go fullscreen with fit-to-viewport, wheel zoom + drag pan
|
|
60
73
|
- 🧱 **Multi-column layout**: Grid for product comparisons and chart dashboards
|
|
61
74
|
- 🎛️ **Complete input states**: dropdown single/multi select, preselection (dataModel seeds), component- and option-level disabling
|
|
@@ -85,18 +98,45 @@ Tracks: Backend, Data Analysis
|
|
|
85
98
|
| `List` | `children, direction?` | List container |
|
|
86
99
|
| `Divider` | — | Separator |
|
|
87
100
|
| `Text` | `text, variant?: h1\|h2\|h3\|body\|caption\|strong` | Text |
|
|
101
|
+
| `Markdown` | `text` | **Rich long-form**: headings, bold/italic, links, lists, quotes, fenced code, `$...$` math; copy-source button |
|
|
88
102
|
| `Image` | `url, alt?, width?, height?` | Images (incl. GIF), built-in fullscreen zoom |
|
|
89
103
|
| `Tag` | `text, color?: blue\|green\|red\|orange\|gray` | Tag/badge |
|
|
90
104
|
| `Math` | `tex, block?` | **KaTeX** formulas (fonts inlined, zero external requests); matrices/vectors must use this |
|
|
91
105
|
| `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)
|
|
106
|
+
| `Chart` | `option, height?, functions?, params?, xMin?, xMax?, samples?, yClip?` | **ECharts 6**: data mode (option verbatim) + function-plot mode (expressions sampled automatically, asymptote breaks) + `params` live-bound constants (Slider→curve); fullscreen + PNG download |
|
|
107
|
+
| `Map` | `data, title?, unit?, height?` | **China choropleth**: province-level distribution (sales/users by region), geoJSON bundled |
|
|
93
108
|
| `Video` | `url, poster?, loop?, muted?, autoplay?` | HTML5 video (mp4/webm) |
|
|
94
|
-
| `
|
|
109
|
+
| `ImageCompare` | `before, after` | Drag-divider before/after image comparison |
|
|
110
|
+
| `Anim` | `frames, interval?, height?, autoplay?, labels?` | **Algorithm animation**: bars, grid/matrix, and graph/tree (BFS/DFS, auto circle layout) forms auto-detected; auto-plays once per card per tab, ↻ replay / pause / step / reset / progress / legend |
|
|
95
111
|
| `Button` | `label, variant?, submit?, action: {event: {name, context?}}` | Sends the submission; `submit` explicitly controls card locking |
|
|
96
112
|
| `MultipleChoice` | `options, bind, maxAllowedSelections?, disabled?` | Flat multi/single select (`maxAllowedSelections: 1` = single), per-option disable |
|
|
97
113
|
| `Select` | `options, bind, label?, placeholder?, multiple?, maxAllowedSelections?, disabled?` | **Dropdown**: single stores a value, multi stores an array; option descriptions/disabling |
|
|
98
114
|
| `CheckBox` | `label, bind, disabled?` | Boolean toggle |
|
|
115
|
+
| `Slider` | `bind, label?, min?, max?, step?, unit?` | Numeric slider; pairs with Chart `params` for live parameter exploration |
|
|
116
|
+
| `Rate` | `bind, label?, max?` | Star rating |
|
|
117
|
+
| `Calc` | `expr, inputs, out, digits?` | Invisible derived value: live-recomputed expression written back to the data model (calculator engine) |
|
|
118
|
+
| `When` | `value, equals?/includes?/notEmpty?, children` | Conditional container: reveal follow-up fields on selection |
|
|
119
|
+
| `Tabs` | `tabs, children, bind?` | Tab switcher: dataset switching / content grouping |
|
|
120
|
+
| `Table` | `columns, rows, caption?, sortable?, filter?, pageSize?` | **Interactive tables**: click-to-sort (numeric-aware), filter box, pagination, copy TSV / CSV export; dictionary binding switches datasets |
|
|
121
|
+
| `Stat` | `label, value, unit?, trend?, hint?` | KPI tile, click to copy the value; combine in a Grid for metric overviews |
|
|
122
|
+
| `Steps` | `items` | Step list (done/current/pending) |
|
|
123
|
+
| `Progress` | `value, max?, label?` | Progress bar |
|
|
124
|
+
| `Timeline` | `items` | Timeline (history / event review) |
|
|
125
|
+
| `CodeBlock` | `code, language?, title?` | Code with line numbers, light highlighting, copy button |
|
|
126
|
+
| `Icon` | `name, size?, color?` | 32 built-in stroke icons |
|
|
127
|
+
| `Audio` | `url, title?` | Audio player |
|
|
128
|
+
| `Flashcard` | `front, back` | Tap-to-flip card (vocabulary / recall) |
|
|
129
|
+
| `Countdown` | `to?/seconds?, label?` | Live countdown |
|
|
99
130
|
| `TextField` | `label?, placeholder?, multiline?, bind, disabled?` | Text input |
|
|
131
|
+
| `Wizard` | `steps, children, submitLabel?` | **Multi-step form**: one pane per step, prev/next + progress built in, final submit sends all collected fields |
|
|
132
|
+
| `Calendar` | `bind, label?, min?, max?` | Month-view date picker with range limits |
|
|
133
|
+
| `RankList` | `items, bind, label?` | Reorder options by priority; submits the ordered list |
|
|
134
|
+
| `EditableTable` | `columns, rows, bind, label?` | User edits cells inline; the whole grid submits |
|
|
135
|
+
| `Upload` | `bind?, label?, max?` | Image picker — chosen photos are sent back to the model as **real images** |
|
|
136
|
+
| `Signature` | `label?` | Handwritten signature pad; the drawing returns as an image |
|
|
137
|
+
| `Suggestions` | `items` | Tappable follow-up chips below an answer; tapping sends that question as the next user message |
|
|
138
|
+
|
|
139
|
+
**Inline math**: every text position (Text, option labels, table cells, steps, flashcards, animation captions) may embed KaTeX with `$...$` — math-quiz OPTIONS can be formulas. **Reactive bindings**: inputs write the data model and every `{"path"}` binding updates live — slider→curve (Chart `params`), choice→follow-up (When), input→computed result (Calc→Stat), switcher→dataset (Tabs / Table dictionary binding).
|
|
100
140
|
|
|
101
141
|
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
142
|
|
|
@@ -109,7 +149,20 @@ Common to inputs: **preselect** by seeding `dataModel` at the bind path; **disab
|
|
|
109
149
|
| dsh | `@deepseek-ai/dsh` ≥ 0.1.1-rc.1 with an initialized web profile (run `dsh web` once before installing) |
|
|
110
150
|
| Node.js | ≥ 20 (with npm) |
|
|
111
151
|
|
|
112
|
-
### Option A · From
|
|
152
|
+
### Option A · From npm (recommended)
|
|
153
|
+
|
|
154
|
+
```sh
|
|
155
|
+
dsh plugin --profile web add a2ui-render-in-dsh
|
|
156
|
+
dsh web
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Zero runtime dependencies — two commands and you're done. If your npm mirror hasn't synced the latest version yet, point at the official registry explicitly:
|
|
160
|
+
|
|
161
|
+
```sh
|
|
162
|
+
dsh plugin --profile web add a2ui-render-in-dsh --registry https://registry.npmjs.org
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Option B · From source (for developers / hacking on the plugin)
|
|
113
166
|
|
|
114
167
|
```sh
|
|
115
168
|
# 1. Clone and build
|
|
@@ -117,27 +170,17 @@ git clone https://github.com/baihui-ai/a2ui-render-in-dsh.git
|
|
|
117
170
|
cd a2ui-render-in-dsh
|
|
118
171
|
npm install
|
|
119
172
|
npm run build
|
|
120
|
-
# Build emits
|
|
173
|
+
# Build emits lib/index.js (host plugin) + lib/client.js (browser bundle).
|
|
121
174
|
# lib/ is not committed — you MUST build after cloning or dsh won't find the entry.
|
|
122
175
|
|
|
123
|
-
# 2. Install into dsh's web profile
|
|
176
|
+
# 2. Install into dsh's web profile in link mode
|
|
124
177
|
dsh plugin --profile web add link:$(pwd)
|
|
125
|
-
#
|
|
126
|
-
# a2ui-render-in-dsh to the profile's dsh.profile.bundles automatically.
|
|
178
|
+
# After code changes: just npm run build + restart dsh web, no reinstall.
|
|
127
179
|
|
|
128
180
|
# 3. Start / restart dsh web
|
|
129
181
|
dsh web
|
|
130
182
|
```
|
|
131
183
|
|
|
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
184
|
### Verify in three steps
|
|
142
185
|
|
|
143
186
|
```sh
|
|
@@ -156,7 +199,10 @@ curl -s http://127.0.0.1:<port>/ | grep -o "a2ui-render-in-dsh/client.js[^\"]*"
|
|
|
156
199
|
### Upgrade & uninstall
|
|
157
200
|
|
|
158
201
|
```sh
|
|
159
|
-
# upgrade (
|
|
202
|
+
# upgrade (npm install)
|
|
203
|
+
dsh plugin --profile web update a2ui-render-in-dsh
|
|
204
|
+
|
|
205
|
+
# upgrade (source link install): rebuild after pulling, then restart dsh web
|
|
160
206
|
git pull && npm run build
|
|
161
207
|
|
|
162
208
|
# uninstall: removes the dependency and the bundles entry, then restart dsh web
|
package/README.zh.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
[English](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/README.md) | 中文
|
|
4
4
|
|
|
5
|
-
**dsh web 的 A2UI 交互卡片插件**:让 Agent 在对话流里自适应地渲染**可交互、可视化的 UI
|
|
5
|
+
**dsh web 的 A2UI 交互卡片插件**:让 Agent 在对话流里自适应地渲染**可交互、可视化的 UI 卡片**——选择题、表单、分步向导、下拉、日历选日期、商品卡、可排序/筛选的表格、ECharts 图表、中国地图分布、数学函数绘图、Mermaid 流程图/思维导图、KaTeX 公式、Markdown 长文、图片上传、手写签名、算法过程动画——用户的点击/勾选/输入以自然语言消息回传给 Agent(图片也能回传),卡片**边生成边渲染**、还能**原地更新**,所见内容一键复制。
|
|
6
6
|
|
|
7
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
8
|
|
|
9
|
-
📸 **[功能示例(含动图)→ DEMO.md](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/DEMO.zh.md)**
|
|
9
|
+
📸 **[功能示例(含动图)→ DEMO.md](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/DEMO.zh.md)** · 🗺️ **[场景 × 组件映射](https://github.com/baihui-ai/a2ui-render-in-dsh/blob/main/docs/SCENARIOS.zh.md)**
|
|
10
10
|
|
|
11
|
-

|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -18,20 +18,24 @@ UI 协议基于 [A2UI v0.9](https://github.com/google/A2UI)(Agent-to-UI 声明
|
|
|
18
18
|
|
|
19
19
|
```
|
|
20
20
|
a2ui-render-in-dsh (一个 npm 包,dsh bundle)
|
|
21
|
-
├─ 宿主端 lib/index.js cordis
|
|
22
|
-
│ ├─ a2ui_render 渲染卡片(描述仅 ~
|
|
23
|
-
│
|
|
24
|
-
|
|
21
|
+
├─ 宿主端 lib/index.js cordis 插件,注册三个 Agent 工具
|
|
22
|
+
│ ├─ a2ui_render 渲染卡片(描述仅 ~220 token,常驻)
|
|
23
|
+
│ ├─ a2ui_update 按 surfaceId 原地更新已渲染的卡片
|
|
24
|
+
│ │ (进度推进、长任务回填、看板刷新)
|
|
25
|
+
│ └─ a2ui_catalog 返回完整组件目录与写卡规则(按需加载,每会话一次)
|
|
26
|
+
└─ 客户端 lib/client.js 浏览器 bundle,注册各工具的专属 toolview
|
|
25
27
|
├─ x-card 引擎(A2UI 命令流、数据绑定、action 解析)
|
|
26
|
-
├─ 组件目录实现(
|
|
27
|
-
|
|
28
|
+
├─ 组件目录实现(44 个组件,跟随 --dsw-* 主题令牌)
|
|
29
|
+
├─ 流式渲染器(截断 JSON 修复 → 模型边写卡片边出现)
|
|
30
|
+
└─ ECharts 6 / Mermaid 11 / KaTeX(字体内联)/ 中国省份 geoJSON
|
|
31
|
+
全部打入 bundle,零外部请求
|
|
28
32
|
```
|
|
29
33
|
|
|
30
34
|
### 关键设计决策
|
|
31
35
|
|
|
32
|
-
**1.
|
|
36
|
+
**1. 主动式渲染,由模型判断——锚定 UI 的目的。** 工具契约把判断框定为:卡片能否在 UI 的四个目的之一上胜过纯文本?**方便操作**(用户要回答/选择/填写/调节——渲染表单)、**方便浏览**(用户想看/扫数据——统计、排名、分布、趋势出图表/表格/地图,数据不确定也不取消卡片:画已知最好的数据、标注时间口径、正文说明局限)、**增强理解**(结构或记号帮助理解——数学、代码、流程、分步过程)、**状态反馈**(长/多步任务先出进度卡,`a2ui_update` 原地推进)。四者都不沾 → 纯文本。卡片始终**与文案搭配**:结论/看点用 1–3 句正文说,结构化内容进卡片,两边不重复。判断框架有 HCI 理论依据(Norman 双鸿沟、钥匙孔效应、外部认知),并用无关键词的自然语言提示词对各目的 + 纯文本反例实测。
|
|
33
37
|
|
|
34
|
-
**2. skill 式上下文设计(目录按需加载)。** 完整组件目录不内联在工具描述里,而是放进 `a2ui_catalog`
|
|
38
|
+
**2. skill 式上下文设计(目录按需加载)。** 完整组件目录不内联在工具描述里,而是放进 `a2ui_catalog` 工具:组件扩到 44 个,常驻上下文仍稳定在 ~220 token;模型首次画卡前调用一次目录,同会话后续卡片直接复用;不画卡的会话零目录开销。服务端校验未知组件名并报错引导查目录,防止模型跳过目录瞎猜。
|
|
35
39
|
|
|
36
40
|
**3. 非阻塞回传,复用原生消息通路。** 卡片提交不需要自定义 server 通道:客户端通过 dsh 自身的 `session.prompt` RPC 把提交内容作为普通用户消息发回会话。消息是**自然语言**(按钮文案 + 所选内容,多字段换行列出),对人可读、对模型可解析,不污染对话观感:
|
|
37
41
|
|
|
@@ -45,16 +49,25 @@ a2ui-render-in-dsh (一个 npm 包,dsh bundle)
|
|
|
45
49
|
|
|
46
50
|
**5. 模型只做擅长的事。** 数学函数绘图:模型只写表达式(`tan(x)`),采样、渐近线断线由内置**安全表达式求值器**完成(白名单 shunting-yard 解析,非 eval,注入即拒绝)——让模型手工枚举几百个数据点必然画错。算法动画:模型模拟算法输出逐帧状态(这是 LLM 强项),播放、过渡、控件由组件完成。
|
|
47
51
|
|
|
48
|
-
**6. 展示组件全部自包含。** ECharts、Mermaid、KaTeX(含 woff2 字体 data-URI
|
|
52
|
+
**6. 展示组件全部自包含。** ECharts、Mermaid、KaTeX(含 woff2 字体 data-URI)、中国省份 geoJSON 全部打进 bundle(~5.5MB,本地服务一次加载),无 CDN 依赖、可离线;明暗主题按页面背景亮度自动跟随。
|
|
53
|
+
|
|
54
|
+
**7. 活的卡片:流式渲染 + 原地更新。** 模型还在输出 JSON 时卡片就开始渲染(容错解析器修复截断的流,完整的组件提前挂载),大卡片逐块出现而不是长时间空白后一次性弹出。渲染完的卡片也不是死的:`a2ui_update` 按 `surfaceId` 原地替换组件或数据——进度条真的会动、任务卡自己填上结果、看板随时刷新;更新持久化,刷新页面后自动重放。
|
|
55
|
+
|
|
56
|
+
**8. 回答不止于文字。** `Upload`(拍照/截图)和 `Signature`(手写画板)走 dsh 原生消息通路把**真实图片**发回给模型——模型看到的是图,不是占位符。`Suggestions` 渲染可点的追问 chips,点一下即作为下一条用户消息发出。录音回传刻意不做:dsh 的 prompt 通道只支持文本 + 图片。
|
|
49
57
|
|
|
50
58
|
## 亮点
|
|
51
59
|
|
|
52
60
|
- 🎯 **自适应**:模型自行判断"文本还是卡片",双向实测可靠
|
|
53
|
-
- 🪶 **上下文友好**:skill
|
|
54
|
-
- 💬 **优雅回传**:自然语言提交消息,非 JSON
|
|
55
|
-
- 🔒
|
|
56
|
-
-
|
|
57
|
-
-
|
|
61
|
+
- 🪶 **上下文友好**:skill 式目录设计,44 个组件常驻开销仅 ~220 token
|
|
62
|
+
- 💬 **优雅回传**:自然语言提交消息,非 JSON 裸串;照片、签名以真实图片回传
|
|
63
|
+
- 🔒 **提交即锁定**:表单防重复提交,记录持久化,"重新填写"可解锁;查询按钮不受影响
|
|
64
|
+
- ⚡ **流式渲染**:模型边写 JSON,卡片边逐块出现
|
|
65
|
+
- 🔄 **原地更新**:`a2ui_update` 按 surfaceId 更新已渲染的卡片——进度条会动、任务卡自己填结果、看板可刷新;刷新页面后重放
|
|
66
|
+
- 📊 **可视化全家桶**:ECharts 图表/仪表盘、函数绘图、中国地图分布、Mermaid 全图型、KaTeX 公式(矩阵强制公式化渲染)、图片对比滑块、视频
|
|
67
|
+
- 🎬 **算法动画**:数组/柱状、网格/矩阵、图/树三形态自动识别;每卡只自动播一遍(组件重挂载不重播),↻ 手动重播、单步、进度条、图例
|
|
68
|
+
- 🧾 **交互表格**:点表头排序(识别数字)、筛选框、分页、复制 TSV、导出 CSV、可编辑表格输入
|
|
69
|
+
- 🧭 **丰富作答组件**:分步向导 Wizard、日历选日期、RankList 排优先级、Suggestions 追问 chips、图片上传、手写签名
|
|
70
|
+
- 📋 **一键复制**:指标块点击复制、表格复制/导出、代码块复制、公式复制 LaTeX 源码、图表下载 PNG、Markdown 复制原文
|
|
58
71
|
- ⛶ **全屏放大**:思维导图/流程图/图表/图片一键全屏,自动适配视口,滚轮缩放 + 拖拽平移
|
|
59
72
|
- 🧱 **一行多列**:Grid 布局做商品对比、图表仪表盘
|
|
60
73
|
- 🎛️ **完整输入态**:下拉单选/多选、预选中(dataModel 初值)、组件级/选项级禁用
|
|
@@ -84,18 +97,45 @@ a2ui-render-in-dsh (一个 npm 包,dsh bundle)
|
|
|
84
97
|
| `List` | `children, direction?` | 列表容器 |
|
|
85
98
|
| `Divider` | — | 分隔线 |
|
|
86
99
|
| `Text` | `text, variant?: h1\|h2\|h3\|body\|caption\|strong` | 文本 |
|
|
100
|
+
| `Markdown` | `text` | **富文本长文**:标题、加粗/斜体、链接、列表、引用、代码块、`$...$` 公式;带复制原文按钮 |
|
|
87
101
|
| `Image` | `url, alt?, width?, height?` | 图片(含 GIF),自带全屏放大 |
|
|
88
102
|
| `Tag` | `text, color?: blue\|green\|red\|orange\|gray` | 标签 |
|
|
89
103
|
| `Math` | `tex, block?` | **KaTeX** 公式(字体内联零外部请求);矩阵/向量必须走此组件 |
|
|
90
104
|
| `Mermaid` | `code, caption?` | **Mermaid 11**:流程图/思维导图/时序图/甘特图等,自带全屏放大 |
|
|
91
|
-
| `Chart` | `option, height?, functions?, xMin?, xMax?, samples?, yClip?` | **ECharts 6**:数据模式(option 透传)+
|
|
105
|
+
| `Chart` | `option, height?, functions?, params?, xMin?, xMax?, samples?, yClip?` | **ECharts 6**:数据模式(option 透传)+ 函数绘图模式(表达式自动采样、渐近线断线)+ `params` 绑定常量(滑杆→曲线联动);全屏 + 下载 PNG |
|
|
106
|
+
| `Map` | `data, title?, unit?, height?` | **中国地图分布**:省级数据热力着色(分区销售/用户分布),geoJSON 内置 |
|
|
92
107
|
| `Video` | `url, poster?, loop?, muted?, autoplay?` | HTML5 视频(mp4/webm) |
|
|
93
|
-
| `
|
|
108
|
+
| `ImageCompare` | `before, after` | 拖动分割线的图片前后对比(before/after、A/B) |
|
|
109
|
+
| `Anim` | `frames, interval?, height?, autoplay?, labels?` | **算法动画**:数组/柱状、网格/矩阵、图/树(BFS/DFS,自动圆形布局)三形态自动识别;每卡每页签只自动播一遍,↻ 重播/暂停/单步/重置/进度条/图例 |
|
|
94
110
|
| `Button` | `label, variant?, submit?, action: {event: {name, context?}}` | 触发回传;`submit` 显式控制是否锁卡 |
|
|
95
111
|
| `MultipleChoice` | `options, bind, maxAllowedSelections?, disabled?` | 平铺多选/单选(`maxAllowedSelections: 1` 单选),选项级禁用 |
|
|
96
112
|
| `Select` | `options, bind, label?, placeholder?, multiple?, maxAllowedSelections?, disabled?` | **下拉选择**:单选存值、多选存数组,选项描述/禁用 |
|
|
97
113
|
| `CheckBox` | `label, bind, disabled?` | 布尔勾选 |
|
|
114
|
+
| `Slider` | `bind, label?, min?, max?, step?, unit?` | 数值滑杆;配合 Chart `params` 做参数探索联动 |
|
|
115
|
+
| `Rate` | `bind, label?, max?` | 星级评分 |
|
|
116
|
+
| `Calc` | `expr, inputs, out, digits?` | 隐形派生值:表达式实时重算写回数据模型(计算器引擎) |
|
|
117
|
+
| `When` | `value, equals?/includes?/notEmpty?, children` | 条件容器:选中特定项才显示后续字段 |
|
|
118
|
+
| `Tabs` | `tabs, children, bind?` | 页签:数据集切换 / 内容分组 |
|
|
119
|
+
| `Table` | `columns, rows, caption?, sortable?, filter?, pageSize?` | **交互表格**:点表头排序(识别数字)、筛选框、分页、复制 TSV / 导出 CSV;字典绑定切换数据集 |
|
|
120
|
+
| `Stat` | `label, value, unit?, trend?, hint?` | KPI 指标块,点击复制数值;Grid 组合成速览行 |
|
|
121
|
+
| `Steps` | `items` | 步骤条(done/current/pending) |
|
|
122
|
+
| `Progress` | `value, max?, label?` | 进度条 |
|
|
123
|
+
| `Timeline` | `items` | 时间轴(历程/事件回顾) |
|
|
124
|
+
| `CodeBlock` | `code, language?, title?` | 代码块:行号 + 轻量高亮 + 复制按钮 |
|
|
125
|
+
| `Icon` | `name, size?, color?` | 内置 32 个常用线条图标 |
|
|
126
|
+
| `Audio` | `url, title?` | 音频播放器 |
|
|
127
|
+
| `Flashcard` | `front, back` | 点击翻面闪卡(背单词/问答记忆) |
|
|
128
|
+
| `Countdown` | `to?/seconds?, label?` | 实时倒计时 |
|
|
98
129
|
| `TextField` | `label?, placeholder?, multiline?, bind, disabled?` | 文本输入 |
|
|
130
|
+
| `Wizard` | `steps, children, submitLabel?` | **分步表单**:每步一个面板,内置上一步/下一步 + 进度,最后一步提交全部字段 |
|
|
131
|
+
| `Calendar` | `bind, label?, min?, max?` | 月视图日期选择,支持范围限制 |
|
|
132
|
+
| `RankList` | `items, bind, label?` | 用户按优先级排序选项,提交排好的列表 |
|
|
133
|
+
| `EditableTable` | `columns, rows, bind, label?` | 用户直接改单元格,整表提交 |
|
|
134
|
+
| `Upload` | `bind?, label?, max?` | 图片选择器——所选照片以**真实图片**回传给模型 |
|
|
135
|
+
| `Signature` | `label?` | 手写签名画板,笔迹以图片回传 |
|
|
136
|
+
| `Suggestions` | `items` | 回答下方的可点追问 chips,点一下即作为下一条用户消息发出 |
|
|
137
|
+
|
|
138
|
+
**内联公式**:所有文本位置(Text、选项、表格单元格、步骤、闪卡、动画解说)支持 `$...$` 内嵌 KaTeX——数学选择题的选项可以直接是公式。**响应式联动**:输入组件写数据模型,所有 `{"path"}` 绑定即时更新——滑杆→曲线(Chart `params`)、选择→追问(When)、输入→计算结果(Calc→Stat)、切换→换表(Tabs/Table 字典绑定)。
|
|
99
139
|
|
|
100
140
|
输入组件通用:**预选中**在 `dataModel` 给 bind 路径设初值;**禁用**用组件级 `disabled: true` 或选项级 `disabled`。数据绑定:`bind` 为不带前导斜杠的写入路径;展示属性用 `{"path": "/x"}`(带斜杠)读实时值。
|
|
101
141
|
|
|
@@ -108,7 +148,20 @@ a2ui-render-in-dsh (一个 npm 包,dsh bundle)
|
|
|
108
148
|
| dsh | `@deepseek-ai/dsh` ≥ 0.1.1-rc.1,且 web profile 已初始化(装插件前先运行过一次 `dsh web`) |
|
|
109
149
|
| Node.js | ≥ 20(含 npm) |
|
|
110
150
|
|
|
111
|
-
### 方式 A ·
|
|
151
|
+
### 方式 A · npm 安装(推荐)
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
dsh plugin --profile web add a2ui-render-in-dsh
|
|
155
|
+
dsh web
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
零运行时依赖,两条命令装完即用。若你的 npm 镜像尚未同步最新版本,显式指定官方源:
|
|
159
|
+
|
|
160
|
+
```sh
|
|
161
|
+
dsh plugin --profile web add a2ui-render-in-dsh --registry https://registry.npmjs.org
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 方式 B · 源码安装(开发者 / 需要改代码时)
|
|
112
165
|
|
|
113
166
|
```sh
|
|
114
167
|
# 1. 克隆并构建
|
|
@@ -116,27 +169,17 @@ git clone https://github.com/baihui-ai/a2ui-render-in-dsh.git
|
|
|
116
169
|
cd a2ui-render-in-dsh
|
|
117
170
|
npm install
|
|
118
171
|
npm run build
|
|
119
|
-
#
|
|
172
|
+
# 构建产出:lib/index.js(宿主端)+ lib/client.js(浏览器 bundle)
|
|
120
173
|
# lib/ 不在 git 里,克隆后必须先构建,否则 dsh 启动时找不到入口
|
|
121
174
|
|
|
122
175
|
# 2. 以 link 方式装进 dsh 的 web profile
|
|
123
176
|
dsh plugin --profile web add link:$(pwd)
|
|
124
|
-
#
|
|
125
|
-
# a2ui-render-in-dsh 追加到 profile 的 dsh.profile.bundles
|
|
177
|
+
# 改码后只需 npm run build + 重启 dsh web,无需重装
|
|
126
178
|
|
|
127
179
|
# 3. 启动 / 重启 dsh web
|
|
128
180
|
dsh web
|
|
129
181
|
```
|
|
130
182
|
|
|
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
183
|
### 三步验证
|
|
141
184
|
|
|
142
185
|
```sh
|
|
@@ -155,7 +198,10 @@ curl -s http://127.0.0.1:<port>/ | grep -o "a2ui-render-in-dsh/client.js[^\"]*"
|
|
|
155
198
|
### 升级与卸载
|
|
156
199
|
|
|
157
200
|
```sh
|
|
158
|
-
# 升级(
|
|
201
|
+
# 升级(npm 安装)
|
|
202
|
+
dsh plugin --profile web update a2ui-render-in-dsh
|
|
203
|
+
|
|
204
|
+
# 升级(源码 link 安装):拉新代码重新构建,重启 dsh web 即生效
|
|
159
205
|
git pull && npm run build
|
|
160
206
|
|
|
161
207
|
# 卸载:从 profile 移除(依赖与 bundles 条目会一并清掉),重启 dsh web
|