@changfenhuang/dsh-genui 0.9.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.
- package/CHANGELOG.md +367 -0
- package/LICENSE +21 -0
- package/README.md +261 -0
- package/README.zh-CN.md +261 -0
- package/SKILL.md +115 -0
- package/cordis.patch.yml +9 -0
- package/demo-prompts.md +118 -0
- package/lib/assets/echarts.js +64 -0
- package/lib/assets/mermaid.js +3591 -0
- package/lib/assets/three.js +3844 -0
- package/lib/client.js +5 -0
- package/lib/index.js +1895 -0
- package/lib/invariant.js +19 -0
- package/lib/types/client/EChartNode.d.ts +4 -0
- package/lib/types/client/ErrorBoundary.d.ts +30 -0
- package/lib/types/client/GenuiBlock.d.ts +7 -0
- package/lib/types/client/PlotBlock.d.ts +44 -0
- package/lib/types/client/action-context.d.ts +7 -0
- package/lib/types/client/asset-echarts.d.ts +15 -0
- package/lib/types/client/asset-loader.d.ts +31 -0
- package/lib/types/client/asset-mermaid.d.ts +1 -0
- package/lib/types/client/asset-three.d.ts +1 -0
- package/lib/types/client/blocks/advanced.d.ts +104 -0
- package/lib/types/client/blocks/basic.d.ts +27 -0
- package/lib/types/client/blocks/charts.d.ts +38 -0
- package/lib/types/client/blocks/diagram/geometry.d.ts +73 -0
- package/lib/types/client/blocks/diagram/index.d.ts +5 -0
- package/lib/types/client/blocks/diagram/layout.d.ts +41 -0
- package/lib/types/client/blocks/diagram/theme.d.ts +35 -0
- package/lib/types/client/blocks/forms.d.ts +83 -0
- package/lib/types/client/blocks/render-node.d.ts +10 -0
- package/lib/types/client/blocks/state.d.ts +58 -0
- package/lib/types/client/dom-fence.d.ts +14 -0
- package/lib/types/client/echarts-lazy.d.ts +17 -0
- package/lib/types/client/fence-render.d.ts +58 -0
- package/lib/types/client/gallery.d.ts +9 -0
- package/lib/types/client/guard.d.ts +126 -0
- package/lib/types/client/index.d.ts +36 -0
- package/lib/types/client/interaction-store.d.ts +43 -0
- package/lib/types/client/mermaid-core.d.ts +8 -0
- package/lib/types/client/mermaid-lazy.d.ts +9 -0
- package/lib/types/client/mermaid-safe.d.ts +52 -0
- package/lib/types/client/panel-command.d.ts +29 -0
- package/lib/types/client/panel-store.d.ts +94 -0
- package/lib/types/client/panel.d.ts +15 -0
- package/lib/types/client/parse-partial.d.ts +37 -0
- package/lib/types/client/safe-math.d.ts +43 -0
- package/lib/types/client/scene3d-core.d.ts +21 -0
- package/lib/types/client/scene3d-lazy.d.ts +8 -0
- package/lib/types/client/spec.d.ts +610 -0
- package/lib/types/client/toolview.d.ts +7 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/plugin/index.d.ts +25 -0
- package/lib/types/plugin/invariant.d.ts +15 -0
- package/lib/types/plugin/tool.d.ts +27 -0
- package/lib/types/shared/fence-repair.d.ts +67 -0
- package/package.json +121 -0
- package/src/client/EChartNode.tsx +242 -0
- package/src/client/ErrorBoundary.tsx +66 -0
- package/src/client/GenuiBlock.module.css +1263 -0
- package/src/client/GenuiBlock.tsx +166 -0
- package/src/client/PlotBlock.module.css +155 -0
- package/src/client/PlotBlock.tsx +431 -0
- package/src/client/action-context.ts +32 -0
- package/src/client/asset-echarts.ts +25 -0
- package/src/client/asset-loader.ts +79 -0
- package/src/client/asset-mermaid.ts +13 -0
- package/src/client/asset-three.ts +12 -0
- package/src/client/blocks/advanced.tsx +435 -0
- package/src/client/blocks/basic.tsx +116 -0
- package/src/client/blocks/charts.tsx +319 -0
- package/src/client/blocks/diagram/geometry.ts +151 -0
- package/src/client/blocks/diagram/index.tsx +284 -0
- package/src/client/blocks/diagram/layout.ts +199 -0
- package/src/client/blocks/diagram/theme.ts +108 -0
- package/src/client/blocks/forms.tsx +523 -0
- package/src/client/blocks/render-node.tsx +260 -0
- package/src/client/blocks/state.ts +61 -0
- package/src/client/dom-fence.tsx +641 -0
- package/src/client/echarts-lazy.ts +35 -0
- package/src/client/fence-render.tsx +230 -0
- package/src/client/gallery.ts +128 -0
- package/src/client/guard.ts +1450 -0
- package/src/client/index.tsx +195 -0
- package/src/client/interaction-store.ts +122 -0
- package/src/client/mermaid-core.ts +121 -0
- package/src/client/mermaid-lazy.ts +31 -0
- package/src/client/mermaid-safe.ts +122 -0
- package/src/client/panel-command.ts +119 -0
- package/src/client/panel-store.ts +471 -0
- package/src/client/panel.tsx +185 -0
- package/src/client/parse-partial.ts +162 -0
- package/src/client/safe-math.ts +270 -0
- package/src/client/scene3d-core.ts +192 -0
- package/src/client/scene3d-lazy.ts +26 -0
- package/src/client/spec.ts +767 -0
- package/src/client/toolview.tsx +66 -0
- package/src/css-modules.d.ts +5 -0
- package/src/index.ts +12 -0
- package/src/plugin/index.ts +173 -0
- package/src/plugin/invariant.ts +30 -0
- package/src/plugin/node-shims.d.ts +31 -0
- package/src/plugin/tool.ts +330 -0
- package/src/shared/fence-repair.ts +244 -0
- package/tsconfig.json +35 -0
- package/tsdown.config.ts +193 -0
package/README.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# 🎨 dsh-genui
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
**English** · [简体中文](./README.zh-CN.md)
|
|
6
|
+
|
|
7
|
+
<br>
|
|
8
|
+
|
|
9
|
+
[**Open the live product site**](https://omdsh-dev.github.io/dsh-genui/) · [**Watch the real demo**](#watch-the-real-interface) · [**Install in DSH**](#quick-start)
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
> Give the model's answers a face — the text is still there, and an interactive UI is already live.
|
|
14
|
+
>
|
|
15
|
+
> 🔌 Ecosystem: the repo carries the `#dsh` · `#dsh-plugin` topics — welcome to be listed by @dsh-plugin.
|
|
16
|
+
|
|
17
|
+
`dsh-genui` turns a model reply into a **safe, interactive DSH surface**. Ask “how are this month’s orders doing?” and the answer can include a sortable data panel, a native video, a draggable plot, a local quiz, or a persistent session panel — without replacing the surrounding text.
|
|
18
|
+
|
|
19
|
+
## Start with the evidence
|
|
20
|
+
|
|
21
|
+
| If you want to… | Go straight to… | What you can verify |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| See the complete DSH flow first | [40-second real walkthrough](#40-second-walkthrough) | Components are rendered inside a real DSH conversation. |
|
|
24
|
+
| Inspect concrete UI outputs | [Three real outputs](#three-real-outputs-inside-a-dsh-reply) | Monitoring, function plots, and composable layout primitives. |
|
|
25
|
+
| Try it in your own DSH | [Quick start](#quick-start) | A public Git install, a prompt to run, and an activation check. |
|
|
26
|
+
| Learn the JSON language | [Component syntax](./SKILL.md) | The supported, guarded `dsh-ui` component specification. |
|
|
27
|
+
|
|
28
|
+
## Watch the real interface
|
|
29
|
+
|
|
30
|
+
> **No concept mockups.** The recording and images in this section are captured from `dsh-genui` rendering in the DSH interface. Use them to see the actual visual language before installing.
|
|
31
|
+
|
|
32
|
+
### 40-second walkthrough
|
|
33
|
+
|
|
34
|
+
<div align="center">
|
|
35
|
+
|
|
36
|
+
https://github.com/user-attachments/assets/f5db33ec-7471-4d4a-a85b-79c9962ab4ef
|
|
37
|
+
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<p align="center">
|
|
41
|
+
<a href="./assets/demo.mp4"><img src="./assets/demo-thumb.png" width="92%" alt="Preview of the complete dsh-genui walkthrough video"></a>
|
|
42
|
+
<br><em>Click the preview to download the original MP4 if the GitHub player is unavailable.</em>
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
The walkthrough moves from an answer-embedded panel through forms, plotting, Mermaid, and 3D-oriented components. The player does **not** auto-play. If it does not load, use the [original MP4](./assets/demo.mp4); the four-step prompt sequence is documented in [demo-prompts.md](./demo-prompts.md).
|
|
46
|
+
|
|
47
|
+
### Three real outputs inside a DSH reply
|
|
48
|
+
|
|
49
|
+
#### 1. A monitoring panel is an answer, not a separate dashboard
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<img src="./assets/showcase-panel.png" width="92%" alt="Real dsh-genui monitoring panel rendered inside a DSH conversation">
|
|
53
|
+
<br><em>Real output: refresh/reset controls, time-range selection, statistics, charts, and a service table live inside the assistant reply.</em>
|
|
54
|
+
</p>
|
|
55
|
+
|
|
56
|
+
#### 2. A function plot redraws locally as its parameters change
|
|
57
|
+
|
|
58
|
+
<p align="center">
|
|
59
|
+
<img src="./assets/showcase-plot.png" width="76%" alt="Real dsh-genui function plot with draggable parameter sliders">
|
|
60
|
+
<br><em>Real output: `plot` renders curves while sliders, reset, and animation controls update the graph locally.</em>
|
|
61
|
+
</p>
|
|
62
|
+
|
|
63
|
+
#### 3. Layout primitives compose into structured work surfaces
|
|
64
|
+
|
|
65
|
+
<p align="center">
|
|
66
|
+
<img src="./assets/showcase.png" width="76%" alt="Real dsh-genui layout and card component composition">
|
|
67
|
+
<br><em>Real output: typography, grid, card, and row/column primitives combine into a hierarchy the model can describe declaratively.</em>
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ⚠️ Read this first: dual-channel rendering (no host source patch required)
|
|
73
|
+
|
|
74
|
+
The plugin ships **two rendering channels** and picks one automatically after the host activates its browser module:
|
|
75
|
+
|
|
76
|
+
- **Registry channel**: when the host exposes the `fence-registry` extension point (newer dsh builds), fences register through the host's streaming render pipeline and behave seamlessly with the host;
|
|
77
|
+
- **DOM channel**: when the host lacks that extension point (including stock DSH and older builds), the plugin observes the session DOM and mounts its own render tree. Since 0.7.2 it **supports streaming rendering**: components appear as the model writes them — the first finished component shows up immediately, no need to wait for the whole reply. Since 0.8.3 fence discovery is **multi-surface**: it matches the stock `md-code-block` surface, the deepsuite-style `.code-block` / `.code-block-small` surfaces some host builds render instead, and — as a structural backstop — any element whose banner labels it `dsh-ui` and contains a `<pre>` body. If your dsh build renders fences with a different class name, they still render (and a one-time console warning tells you the host DOM drifted).
|
|
78
|
+
|
|
79
|
+
Whichever channel is active, components, interactions, panels, and persistence behave identically.
|
|
80
|
+
|
|
81
|
+
The repository ships both renderer channels, the host plugin, and the built browser bundle. The host still owns **client activation** and must provide the `slots` and `sessions` services. A downloaded `client.js` or a ModuleLoader cache entry proves only that bytes arrived — successful activation always prints `[genui] client active; fence-channel=registry|dom`. If that line is absent, fix package/profile identity or host activation first; DOM attributes such as `data-streaming` and `data-chat-anchor-key` are optional fallbacks, not installation prerequisites.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## ✨ Before vs. after
|
|
86
|
+
|
|
87
|
+
| Plain answer | With dsh-genui |
|
|
88
|
+
|---|---|
|
|
89
|
+
| "Revenue this month: ¥128,430, +12.4% MoM — watch the conversion rate." | One line of analysis + three stat cards (revenue / orders / conversion), a trend chart, and a progress bar rendered right beside it |
|
|
90
|
+
| Want to see more? Type another question. | The panel already has "Refresh" / "Switch view" buttons — click, and the model updates the data |
|
|
91
|
+
|
|
92
|
+
## 🚀 Quick start
|
|
93
|
+
|
|
94
|
+
Prerequisites — all required:
|
|
95
|
+
|
|
96
|
+
1. **dsh installed** (any open-source build works — the plugin picks its rendering channel at startup, see "dual-channel rendering" above)
|
|
97
|
+
2. **`pnpm` on your PATH**: the `dsh plugin` command depends on it. If missing: `corepack enable` (or `npm i -g pnpm`), then **open a new terminal** and confirm `pnpm -v` prints a version
|
|
98
|
+
|
|
99
|
+
Install (one command, all dependencies included):
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
# Public npm package (works without an npm account)
|
|
103
|
+
dsh plugin --profile web add @changfenhuang/dsh-genui
|
|
104
|
+
# Or install directly from the public GitHub source
|
|
105
|
+
dsh plugin --profile web add git+https://github.com/omdsh-dev/dsh-genui.git
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> ⚠️ **Don't use `link:` on a freshly cloned directory** — `link:` does not install the plugin's dependencies (mermaid / three / react), so the renderer will break. Use the git URL form above; reserve `link:` for local development iteration (see below).
|
|
109
|
+
|
|
110
|
+
### Verify the install in 60 seconds
|
|
111
|
+
|
|
112
|
+
After the command completes, restart dsh web and hard-refresh the browser. In a **new** session, say:
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
Use dsh-ui to draw a stats dashboard with a sortable service table.
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
You should see the reply turn into an in-place dashboard rather than a code block. For an unambiguous technical check, open the browser console: successful activation prints `[genui] client active; fence-channel=registry|dom`.
|
|
119
|
+
|
|
120
|
+
### One-click script (recommended)
|
|
121
|
+
|
|
122
|
+
After cloning, just run it — the script checks the prerequisites above, performs the install, and prompts you to restart:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
git clone https://github.com/omdsh-dev/dsh-genui.git
|
|
126
|
+
cd dsh-genui
|
|
127
|
+
./scripts/install.sh
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Developer iteration (link mode)
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
cd dsh-genui
|
|
134
|
+
pnpm install
|
|
135
|
+
dsh plugin --profile web add link:$PWD
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 🧩 Capability map
|
|
139
|
+
|
|
140
|
+
| Surface | First thing to try | Observable behavior |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| Data | Ask for an order or service dashboard | `stat`, `table`, `chart`, and `progress` appear inside the reply; supported numeric table values sort numerically. |
|
|
143
|
+
| Media | Ask for an audio or video reference | Browser-reachable media plays inline, with poster/aspect-ratio and failure states. |
|
|
144
|
+
| Exploration | Ask for `plot` with a parameter | Dragging sliders redraws the curve locally and immediately. |
|
|
145
|
+
| Feedback | Ask for a short quiz | The UI grades and explains locally; only the next model step needs an `action`. |
|
|
146
|
+
| Workspace | Ask for `/panel` or `panel: true` | A persistent, resizable session dock is updated in place. |
|
|
147
|
+
|
|
148
|
+
The following is the detailed capability reference. Every behavior is constrained by the whitelisted `dsh-ui` specification; see [SKILL.md](./SKILL.md) for the JSON syntax.
|
|
149
|
+
|
|
150
|
+
- **Answer-as-UI**: components are embedded in the reply and appear as they stream — no waiting for the whole message
|
|
151
|
+
- **30+ components**: cards, tables, charts, forms, tabs, accordions, file trees, timelines, diffs…
|
|
152
|
+
- **Native media**: audio and video play inline from browser-reachable http(s) or same-origin relative URLs, with user-controlled playback, video posters/aspect ratios, and visible failure states
|
|
153
|
+
- **ECharts integration**: the `echart` node renders full ECharts charts with theme-aware colors, tooltips, and legends. Two modes: **preset shorthand** (`preset: 'bar' | 'line' | 'area' | 'pie' | 'scatter'` + `data`/`series`) for quick upgrade from the `chart` node, or **full option** (`option` field) for custom chart types, dataZoom, visualMap, and other advanced ECharts features. The echarts engine (~1 MB) is lazy-loaded on demand — the main bundle never carries it, and conversations without `echart` nodes never download it- **Function plots**: `plot` draws curves; parameter sliders redraw in real time, with optional auto-animation
|
|
154
|
+
|
|
155
|
+
- **Quiz**: `quiz` grades on click with explanation and retry; with `action`, the answer is also sent back to the model (grading stays local and instant)
|
|
156
|
+
- **Local grading (submit)**: a multiple-choice set = one `radio` per question with `group` + `answer` (correct answer) + `explanation`, plus one `submit` button — after the user answers everything and clicks once, **the score, per-question right/wrong, and explanations appear right in the UI with zero model round-trips**; the quiz then locks, and "retake" resets locally (optional `resetAction` notifies the model). Questions without an answer fall back to an aggregated action (`fields` collects every input with an `id`)
|
|
157
|
+
- **State persistence**: answers, submission locks, and input values are saved per "session + content fingerprint" — refresh or reopen restores everything; re-rendering identical content keeps user state; new content starts fresh; LRU cap of 200 blocks
|
|
158
|
+
- **Form semantics**: `input` Enter / `textarea` Ctrl+Enter submits immediately (`submit:true`), no blur needed; fields with an `id` are collected into the submit's `fields`
|
|
159
|
+
- **Secrets ban**: GenUI must never ask for passwords, API keys, access tokens, recovery codes, or other secrets; even if a password input appears, it stays masked, is never persisted, and never enters form collection
|
|
160
|
+
- **Local-first principle**: state changes the UI can do itself (grading, quiz checking, resets, expand/collapse, selection) always happen locally and instantly; actions are reserved for things that genuinely need the model (generating new content, running tools, next-step suggestions)
|
|
161
|
+
- **Honest interactions**: interactive components must carry `action`; buttons without one render disabled (kills the "looks clickable, does nothing" fake button); buttons with `action` show instant "triggered" local feedback (proof the local event fired, not that the model received it)
|
|
162
|
+
- **Event loop**: buttons/switches/inputs/dropdowns/checkboxes/radios/textareas/quizzes carry `action`; click or blur sends back to the model, which updates the UI; same-name actions are debounced with a 300 ms trailing edge — rapid clicks merge into one (last value wins)
|
|
163
|
+
- **Tool channel**: the `render_ui` tool renders the same spec as a card in the tool row (deliverable-style UI goes through the tool, answer-style UI through the fence)
|
|
164
|
+
- **Session panel**: a persistent dock above the composer; `render_ui` / `panel: true` fences update the same surface in place; `/panel` opens it from the client (`/panel <instruction>` customizes via the model, `/panel clear` clears); the top border is draggable to resize; `append: true` merges incrementally — same-named tabs append content, new tabs get added; the whole panel caps at 200 nodes / 200 appends, after which the model should send `replace` to rebuild
|
|
165
|
+
- **Self-healing & limits**: every fence passes a spec guard — bad nodes are silently dropped, numbers clamped, strings truncated; the whole tree is capped at 200 nodes / 8 nesting levels; pathological specs never crash the UI
|
|
166
|
+
- **Chart error self-healing**: mermaid failures auto-retry with repairs (strip backticks, quote Chinese/space labels, remove `<br/>`) before degrading to source; a broken chart never hits the screen
|
|
167
|
+
- **Accessibility**: tabs/accordions/switches/progress bars carry full ARIA and keyboard navigation (arrow keys switch tabs, Home/End jump)
|
|
168
|
+
- **Zero intrusion**: without the plugin, fences are just code blocks — no errors, no session pollution
|
|
169
|
+
|
|
170
|
+
Component JSON syntax: [SKILL.md](./SKILL.md) (also copyable to `~/.dsh/skills/genui/` to boost the model).
|
|
171
|
+
|
|
172
|
+
## 📄 Example
|
|
173
|
+
|
|
174
|
+
The model outputs this fence (written for the browser — you don't need to read it):
|
|
175
|
+
|
|
176
|
+
```dsh-ui
|
|
177
|
+
{"title":"Order overview","items":[
|
|
178
|
+
{"type":"stat","label":"Total revenue","value":"¥128,430","delta":"+12.4%"},
|
|
179
|
+
{"type":"stat","label":"Orders","value":"1,024","delta":"-3.1%"}
|
|
180
|
+
]}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
What you see: two stat cards.
|
|
184
|
+
|
|
185
|
+
### ECharts example
|
|
186
|
+
|
|
187
|
+
```dsh-ui
|
|
188
|
+
{"title":"Q1 Revenue","items":[
|
|
189
|
+
{"type":"echart","title":"Monthly Revenue","preset":"bar","data":[
|
|
190
|
+
{"label":"Jan","value":98},
|
|
191
|
+
{"label":"Feb","value":112},
|
|
192
|
+
{"label":"Mar","value":128}
|
|
193
|
+
]}
|
|
194
|
+
]}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
What you see: a themed bar chart with tooltips and axis labels — rendered by ECharts, lazy-loaded on demand.
|
|
198
|
+
|
|
199
|
+
## 🔧 How it works
|
|
200
|
+
|
|
201
|
+
The model writes the interface description as JSON inside a `dsh-ui` fence; the browser-side renderer (`src/client`) claims this language through the main repo's `fence-registry` interface and renders it. Components are whitelisted — the model can't smuggle in HTML/scripts; function expressions go through a standalone parser, never `eval`.
|
|
202
|
+
|
|
203
|
+
The core render package stays light (≈110 KB min / 28 KB gzip); the mermaid, three.js, and echarts engines are bundled separately as on-demand assets (loaded through the plugin's self-registered HTTP routes the first time they're used), so startup only downloads the rendering core.
|
|
204
|
+
|
|
205
|
+
## ❓ FAQ
|
|
206
|
+
|
|
207
|
+
- **Rendering as a code block?** First check the browser console for `[genui] client active; fence-channel=registry|dom`. If absent, the client bundle was not activated even if its URL returns 200 — align the profile dependency, `package.json.name`, `cordis.patch.yml`, ModuleLoader id, and configured bundle name. If present, inspect the fence label/body; registry-less hosts automatically use the DOM channel.
|
|
208
|
+
- **Chat UI goes blank when rendering a dsh-ui fence?** Your dsh is too old — update dsh first, then reinstall the plugin.
|
|
209
|
+
- **`dsh: pnpm not found on PATH`?** Install pnpm, then **open a new terminal** and retry (`corepack enable` or `npm i -g pnpm`).
|
|
210
|
+
- **Stuck on git credentials / 404 during install?** The repo is public (`omdsh-dev/dsh-genui`) — the git URL above needs no login; a 404 for `@changfenhuang/dsh-genui` means the npm package has not been published yet.
|
|
211
|
+
- **Installed but scene3d/mermaid/echarts don't render?** The engines (mermaid / three / echarts) are no longer inlined in client.js — they load on demand the first time they're used (`/plugins/@changfenhuang/dsh-genui/assets/*.js`, hosted by the plugin's own HTTP routes). First restart dsh web + hard refresh (Cmd+Shift+R); still broken, remove and reinstall (`dsh plugin --profile web remove @changfenhuang/dsh-genui`, then add again). Hosts without the asset routes degrade to source/load-error hints — update dsh.
|
|
212
|
+
- **Model not outputting fences?** New sessions pick it up after a restart; or just say "output it with dsh-ui".
|
|
213
|
+
- **No lib/ after cloning?** Build it yourself: `pnpm install && pnpm run check`.
|
|
214
|
+
|
|
215
|
+
## 🧑💻 Development
|
|
216
|
+
|
|
217
|
+
```sh
|
|
218
|
+
pnpm install
|
|
219
|
+
pnpm run check # type check + full tests + build
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Real-device e2e
|
|
223
|
+
|
|
224
|
+
The real chain end to end: start a temporary dsh web → install the plugin → send a message in a browser so the model outputs a `dsh-ui` fence → assert the rendering → click an action button → assert the model responds (event-loop closure):
|
|
225
|
+
|
|
226
|
+
```sh
|
|
227
|
+
DEEPSEEK_API_KEY=sk-... node scripts/e2e.mjs # link-installs the current workspace
|
|
228
|
+
DEEPSEEK_API_KEY=sk-... node scripts/e2e.mjs --install git # friend path (git URL)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Prereqs: `dsh`/`pnpm` on PATH, `DEEPSEEK_API_KEY`, and the main repo's web build output (playwright resolves it from the main repo). On PASS it saves an `e2e-final.png` screenshot.
|
|
232
|
+
|
|
233
|
+
### Visual e2e (no model key)
|
|
234
|
+
|
|
235
|
+
For style/component iterations, a visual smoke that needs no API key: boots a real dsh web with the plugin link-installed, injects the component gallery fence through the DOM channel, renders it in headless Chrome, screenshots the full page, and exercises local interactions (table sort, quiz judging, tree collapse, numeric alignment) with hard assertions:
|
|
236
|
+
|
|
237
|
+
```sh
|
|
238
|
+
npx tsx scripts/e2e-visual.mts # → .e2e-artifacts/gallery.png + interactions.png
|
|
239
|
+
npx tsx scripts/e2e-visual.mts --keep # keep the scratch DSH_HOME for debugging
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Overridable: `--port 3098`, `--out <dir>`, `DSH_BIN` (defaults to the npm-mode `~/node_modules/.bin/dsh`), `PLAYWRIGHT_PATH` (defaults to the global playwright-core).
|
|
243
|
+
|
|
244
|
+
## 🗺️ Roadmap (evaluated)
|
|
245
|
+
|
|
246
|
+
| Direction | Verdict | Rationale |
|
|
247
|
+
|---|---|---|
|
|
248
|
+
| Incremental patching (model sends diffs, not full specs) | Not doing | A fence costs 200–800 tokens; resending is nearly free; a patch protocol's teaching cost and error rate aren't worth it. Revisit if sub-second auto-refreshing panels ever appear |
|
|
249
|
+
| Action debounce/dedup | ✅ Done (300 ms trailing edge, per action name) | Rapid-click spam is real friction; one choke point |
|
|
250
|
+
| Cross-session state persistence (replay restores tabs/switches) | Not doing | Replay-reset is the more correct default (the model has already updated the UI with a new fence); state survives naturally during streaming |
|
|
251
|
+
| MCP adapter / standalone gallery page / i18n | Not doing | No cross-tool demand signal; gallery material is covered by `gallery.ts` + demo-prompts + README screenshots; only 6 built-in strings |
|
|
252
|
+
|
|
253
|
+
Unit tests and builds use the locked published dsh rc.8 packages. `DSH_ROOT` is only needed by source-level or end-to-end checks.
|
|
254
|
+
|
|
255
|
+
## 🔗 Friendly links
|
|
256
|
+
|
|
257
|
+
- [Linux.do](https://linux.do)
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
📄 License: MIT
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# 🎨 dsh-genui
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
[English](./README.md) · **简体中文**
|
|
6
|
+
|
|
7
|
+
<br>
|
|
8
|
+
|
|
9
|
+
[**打开在线产品站**](https://omdsh-dev.github.io/dsh-genui/) · [**看真实演示**](#观看真实界面) · [**安装到 DSH**](#-快速开始)
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
> 让模型的回答长出界面——文字还在,可交互的 UI 已经能用。
|
|
14
|
+
>
|
|
15
|
+
> 🔌 生态:仓库已挂 `#dsh` · `#dsh-plugin` topic,欢迎 @dsh-plugin 收录。
|
|
16
|
+
|
|
17
|
+
`dsh-genui` 把模型回答变成**安全、可交互的 DSH 界面**。你问「这个月订单怎么样」,回答除了文字,还可以直接带上可排序的数据面板、原生音视频、可拖动的函数图、本地判题或常驻会话面板。
|
|
18
|
+
|
|
19
|
+
## 先看真实证据
|
|
20
|
+
|
|
21
|
+
| 你想做什么 | 直接看这里 | 可以确认什么 |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| 先看完整 DSH 流程 | [40 秒真实录屏](#40-秒完整演示) | 组件确实出现在 DSH 的真实对话里。 |
|
|
24
|
+
| 看具体界面是什么样 | [三类真实输出](#一条-dsh-回答里的三类真实输出) | 监控、函数绘图和可组合的布局组件。 |
|
|
25
|
+
| 立刻在自己的 DSH 里试 | [快速开始](#-快速开始) | 公开 Git 安装、验证提示词与激活检查。 |
|
|
26
|
+
| 学会 JSON 界面描述 | [组件语法](./SKILL.md) | 受白名单约束的 `dsh-ui` 组件规范。 |
|
|
27
|
+
|
|
28
|
+
## 观看真实界面
|
|
29
|
+
|
|
30
|
+
> **不是概念图。** 本节的录屏与截图均来自 `dsh-genui` 在 DSH 界面中的实际渲染;先看它真正长什么样,再决定是否安装。
|
|
31
|
+
|
|
32
|
+
### 40 秒完整演示
|
|
33
|
+
|
|
34
|
+
<div align="center">
|
|
35
|
+
|
|
36
|
+
https://github.com/user-attachments/assets/f5db33ec-7471-4d4a-a85b-79c9962ab4ef
|
|
37
|
+
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<p align="center">
|
|
41
|
+
<a href="./assets/demo.mp4"><img src="./assets/demo-thumb.png" width="92%" alt="dsh-genui 完整演示录屏封面"></a>
|
|
42
|
+
<br><em>若 GitHub 播放器不可用,点击封面即可下载原始 MP4。</em>
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
录屏依次经过回答内嵌面板、表单、函数绘图、Mermaid 与面向 3D 的组件。播放器不会自动播放;若没有加载,请打开[原始 MP4](./assets/demo.mp4),四幕提示词见 [demo-prompts.md](./demo-prompts.md)。
|
|
46
|
+
|
|
47
|
+
### 一条 DSH 回答里的三类真实输出
|
|
48
|
+
|
|
49
|
+
#### 1. 监控面板就是回答的一部分,不是另开一个仪表盘
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<img src="./assets/showcase-panel.png" width="92%" alt="真实 DSH 对话中渲染的 dsh-genui 监控面板">
|
|
53
|
+
<br><em>真实输出:刷新/重置、时间范围、统计卡、图表和服务表都活在助手回答里。</em>
|
|
54
|
+
</p>
|
|
55
|
+
|
|
56
|
+
#### 2. 改参数时,函数图在本地即时重绘
|
|
57
|
+
|
|
58
|
+
<p align="center">
|
|
59
|
+
<img src="./assets/showcase-plot.png" width="76%" alt="带可拖动参数滑块的真实 dsh-genui 函数图">
|
|
60
|
+
<br><em>真实输出:`plot` 绘制曲线;拖动滑块、重置和动画控制都直接更新图形。</em>
|
|
61
|
+
</p>
|
|
62
|
+
|
|
63
|
+
#### 3. 布局原语可以组成有层级的工作界面
|
|
64
|
+
|
|
65
|
+
<p align="center">
|
|
66
|
+
<img src="./assets/showcase.png" width="76%" alt="真实 dsh-genui 排版和卡片组件组合">
|
|
67
|
+
<br><em>真实输出:文字、网格、卡片、行列原语可组合成模型能够声明的界面层级。</em>
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ⚠️ 先看这里:双通道渲染(无需修改宿主源码)
|
|
73
|
+
|
|
74
|
+
本插件自带**两套渲染通道**;宿主激活浏览器模块后,插件会自动选择:
|
|
75
|
+
|
|
76
|
+
- **Registry 通道**:宿主提供 `fence-registry` 扩展点(新版 dsh 构建)时,围栏经宿主流式渲染管线注册,行为与宿主无缝;
|
|
77
|
+
- **DOM 通道**:宿主没有该扩展点(包括原版 DSH 与旧版构建)时,插件观察会话 DOM 自行挂载渲染树。自 0.7.2 起**支持流式渲染**:模型写到哪渲染到哪,首个完成的组件立即出现,不用等整段回复写完。自 0.8.3 起围栏发现**多表面兼容**:同时匹配标准 `md-code-block` 表面、部分宿主构建使用的 deepsuite 风格 `.code-block` / `.code-block-small` 表面,并以「label+`<pre>`」结构兜底——任何 banner 标注 `dsh-ui` 且含 `<pre>` 正文的元素都能被识别。即使你的 dsh 构建用了别的类名,围栏照常渲染(控制台会有一条一次性提示说明宿主 DOM 发生漂移)。
|
|
78
|
+
|
|
79
|
+
无论走哪条通道,组件、交互、面板、持久化行为完全一致。
|
|
80
|
+
|
|
81
|
+
本仓库已经包含两条渲染通道、服务端插件和浏览器构建产物;宿主仍负责**激活客户端模块**,并提供 `slots` 与 `sessions` 服务。`client.js` 返回 200 或出现在 ModuleLoader 缓存里,只能证明文件下载成功;真正激活后一定会打印 `[genui] client active; fence-channel=registry|dom`。没有这行时应先核对包名/网页配置/宿主激活链,`data-streaming`、`data-chat-anchor-key` 等页面属性只是可选信息,不是安装前提。
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## ✨ 装之前 vs 装之后
|
|
86
|
+
|
|
87
|
+
| 普通回答 | 装了 dsh-genui |
|
|
88
|
+
|---|---|
|
|
89
|
+
| "本月收入 ¥128,430,环比 +12.4%,建议关注转化率。" | 一行分析 + 旁边直接渲染:收入/订单/转化率三张统计卡、趋势图、进度条 |
|
|
90
|
+
| 想再看别的?再打一段字问一遍 | 面板上就有「刷新」「切换视图」按钮,点一下,模型更新数据 |
|
|
91
|
+
|
|
92
|
+
## 🚀 快速开始
|
|
93
|
+
|
|
94
|
+
前置条件,缺一不可:
|
|
95
|
+
|
|
96
|
+
1. **dsh 已安装**(开源版任意构建均可——插件启动时自动选择渲染通道,见上文「双通道渲染」)
|
|
97
|
+
2. **`pnpm` 在 PATH 上**:`dsh plugin` 命令依赖它。没有就 `corepack enable`(或 `npm i -g pnpm`),然后**新开一个终端**,确认 `pnpm -v` 有输出
|
|
98
|
+
|
|
99
|
+
安装(一行命令,自动带上全部依赖):
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
# npm 公开包安装(无需 npm 账号)
|
|
103
|
+
dsh plugin --profile web add @changfenhuang/dsh-genui
|
|
104
|
+
# 也可以直接从 GitHub 公开源码安装
|
|
105
|
+
dsh plugin --profile web add git+https://github.com/omdsh-dev/dsh-genui.git
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> ⚠️ **别用 `link:` 装一个刚 clone 的目录**——`link:` 不会安装插件的依赖(mermaid / three / react),装完渲染器会挂。请用上面的 git URL 方式;只有本地开发迭代才用 link:(见下文)。
|
|
109
|
+
|
|
110
|
+
### 60 秒验证安装
|
|
111
|
+
|
|
112
|
+
命令完成后,重启 dsh web 并对浏览器硬刷新。在**新**会话中输入:
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
用 dsh-ui 画一个带可排序服务表的统计看板。
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
正常情况下,回答会原地变成仪表盘,而不是显示成代码块。想做最明确的技术确认时,打开浏览器控制台:成功激活会打印 `[genui] client active; fence-channel=registry|dom`。
|
|
119
|
+
|
|
120
|
+
### 一键脚本(推荐)
|
|
121
|
+
|
|
122
|
+
clone 后直接跑,脚本会检查上述前置、执行安装、并提示重启:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
git clone https://github.com/omdsh-dev/dsh-genui.git
|
|
126
|
+
cd dsh-genui
|
|
127
|
+
./scripts/install.sh
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 开发者迭代(link 模式)
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
cd dsh-genui
|
|
134
|
+
pnpm install
|
|
135
|
+
dsh plugin --profile web add link:$PWD
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 🧩 能力地图
|
|
139
|
+
|
|
140
|
+
| 界面方向 | 第一次怎么试 | 可以直接观察到的行为 |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| 数据 | 让它做订单或服务监控看板 | `stat`、`table`、`chart`、`progress` 直接出现;已支持的数值表格按数值排序。 |
|
|
143
|
+
| 媒体 | 让它引用一段音频或视频 | 浏览器可访问的媒体直接内嵌播放,带封面/比例和失败状态。 |
|
|
144
|
+
| 探索 | 让它用 `plot` 画带参数的函数 | 拖动滑块,本地立即重绘曲线。 |
|
|
145
|
+
| 反馈 | 让它出一道小测 | 判题和解析在本地完成;需要模型参与的下一步才使用 `action`。 |
|
|
146
|
+
| 工作区 | 使用 `/panel` 或 `panel: true` | 常驻、可调高的会话 dock 在原地更新。 |
|
|
147
|
+
|
|
148
|
+
下面是完整能力说明。所有行为都受白名单 `dsh-ui` 规范约束;JSON 写法请看 [SKILL.md](./SKILL.md)。
|
|
149
|
+
|
|
150
|
+
- **回答即界面**:组件嵌在回答里,边生成边出现,不用等整段写完
|
|
151
|
+
- **30+ 组件**:卡片、表格、图表、表单、标签页、折叠面板、文件树、时间线、diff……
|
|
152
|
+
- **原生音视频**:浏览器可访问的 http(s) 或同源相对地址直接嵌入回答;用户主动控制播放,视频支持封面与画面比例,失败时原位提示
|
|
153
|
+
- **ECharts 集成**:`echart` 节点渲染完整的 ECharts 图表,自动适配主题色、提示框和图例。两种模式:**预设简写**(`preset: 'bar' | 'line' | 'area' | 'pie' | 'scatter'` + `data`/`series`)可从 `chart` 节点快速升级;**完整选项**(`option` 字段)支持自定义图表类型、dataZoom、visualMap 等高级 ECharts 功能。echarts 引擎(~1 MB)按需懒加载——主包不含引擎,没有 `echart` 节点的对话不会下载它- **函数图**:`plot` 画曲线,参数滑块拖动实时重绘,支持自动动画
|
|
154
|
+
|
|
155
|
+
- **测验**:`quiz` 点选判题 + 解析 + 重试;带 `action` 时答案同时回传模型(判题仍本地即时)
|
|
156
|
+
- **本地判卷(交卷)**:多道选择题 = 每题的 `radio` 加 `group` + `answer`(正确答案)+ `explanation`(解析),再加一个 `submit` 交卷按钮——用户全部选完点一次,**分数、每题对错、解析当场在 UI 里出现,零模型往返**;题目随即锁定,「重新作答」本地重置(可选 `resetAction` 通知模型)。题目没带答案时才退回聚合 action(`fields` 收集所有带 `id` 的输入)
|
|
157
|
+
- **状态持久化**:答案、交卷锁定、输入值按「会话 + 内容指纹」自动保存——刷新页面/重开会话原样恢复,重渲染相同内容保留用户状态,新内容自动从头开始;上限 200 块 LRU 淘汰
|
|
158
|
+
- **表单语义**:`input` 回车 / `textarea` Ctrl+Enter 即时提交(`submit:true`),不用等失焦;带 `id` 的字段值进 submit 的 `fields` 收集
|
|
159
|
+
- **秘密禁令**:GenUI 不得索取密码、API Key、访问令牌、恢复码或其他秘密;密码输入即使出现也保持打码、不持久化、不进表单收集
|
|
160
|
+
- **本地优先原则**:UI 自己能完成的状态变化(判卷、判题、重置、展开、选中)一律本地即时完成;action 只用于必须模型参与的事(生成新内容、执行工具、下一步建议)
|
|
161
|
+
- **诚实交互**:交互组件必须带 `action`;不带 `action` 的按钮渲染为禁用态(消灭"看着能点、点了没反应"的假按钮);带 `action` 的按钮点击后立即显示「已触发」本地反馈(只证明本地事件已触发,不代表模型已收到)
|
|
162
|
+
- **事件循环**:按钮/开关/输入/下拉/复选/单选/文本域/测验带 `action`,点击/失焦回传模型,模型更新界面;同名 action 300ms 尾沿防抖,连点合并为一次(最后一次的值生效)
|
|
163
|
+
- **工具通道**:`render_ui` 工具把同一份 spec 渲染成工具行卡片(交付物型 UI 走工具、回答型 UI 走围栏)
|
|
164
|
+
- **会话面板**:composer 上方常驻 dock,`render_ui` / `panel: true` 围栏原地更新同一块界面;`/panel` 命令客户端直开(`/panel <指令>` 转模型定制、`/panel clear` 清空);顶边框可拖拽调高;`append: true` 增量合并——同名标签页追加内容、新标签页新增;整面板默认最多 200 节点 / 200 条追加,达到上限后模型应发送 `replace` 重建
|
|
165
|
+
- **自愈与上限**:每个围栏过规格守卫——坏节点静默丢弃、数值钳位、字符串截断,整树 ≤200 节点 / 8 层嵌套,病态 spec 不会拖垮界面
|
|
166
|
+
- **图错误自愈**:mermaid 渲染失败自动修复重试(剥反引号、引号化中文/空格标签、去 `<br/>`),仍失败才降级源码;错误图永不直接上屏
|
|
167
|
+
- **可访问性**:tabs/折叠/开关/进度条带完整 ARIA 与键盘导航(方向键切页、Home/End 跳转)
|
|
168
|
+
- **零打扰**:不装插件时围栏只是代码块,不报错、不污染会话
|
|
169
|
+
|
|
170
|
+
组件 JSON 语法见 [SKILL.md](./SKILL.md)(也可复制到 `~/.dsh/skills/genui/` 增强模型使用)。
|
|
171
|
+
|
|
172
|
+
## 📄 示例
|
|
173
|
+
|
|
174
|
+
模型输出这段围栏(写给浏览器看的,你不用读懂):
|
|
175
|
+
|
|
176
|
+
```dsh-ui
|
|
177
|
+
{"title":"订单概览","items":[
|
|
178
|
+
{"type":"stat","label":"总收入","value":"¥128,430","delta":"+12.4%"},
|
|
179
|
+
{"type":"stat","label":"订单数","value":"1,024","delta":"-3.1%"}
|
|
180
|
+
]}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
你看到的是两张统计卡片。
|
|
184
|
+
|
|
185
|
+
### ECharts 示例
|
|
186
|
+
|
|
187
|
+
```dsh-ui
|
|
188
|
+
{"title":"Q1 收入","items":[
|
|
189
|
+
{"type":"echart","title":"月度收入","preset":"bar","data":[
|
|
190
|
+
{"label":"1月","value":98},
|
|
191
|
+
{"label":"2月","value":112},
|
|
192
|
+
{"label":"3月","value":128}
|
|
193
|
+
]}
|
|
194
|
+
]}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
你看到的是一张带提示框和坐标轴的主题色柱状图——由 ECharts 渲染,按需懒加载。
|
|
198
|
+
|
|
199
|
+
## 🔧 原理
|
|
200
|
+
|
|
201
|
+
模型把界面描述写成 JSON 放进 `dsh-ui` 围栏,浏览器端渲染器(`src/client`)通过主仓 `fence-registry` 接口认领这门语言并渲染。组件是白名单的,模型塞不进 HTML/脚本;函数表达式走独立解析器,不用 eval。
|
|
202
|
+
|
|
203
|
+
主渲染包保持轻量(≈110 KB min / 28 KB gzip),mermaid、three.js 与 echarts 引擎单独打包为按需资产(首次用到时经插件自注册的 HTTP 路由加载),启动时只下载渲染核心。
|
|
204
|
+
|
|
205
|
+
## ❓ 常见问题
|
|
206
|
+
|
|
207
|
+
- **显示成代码块?** 先在浏览器控制台找 `[genui] client active; fence-channel=registry|dom`。没有这行,即使 `client.js` 返回 200,也只是下载了文件、没有激活:请对齐网页配置依赖名、`package.json.name`、`cordis.patch.yml`、ModuleLoader id 和配置中的 bundle 名。出现这行后再查围栏标签/正文;宿主没有 registry 时会自动走 DOM 通道。
|
|
208
|
+
- **渲染 dsh-ui fence 时聊天界面白屏?** dsh 版本太旧——先更新 dsh 再重装插件。
|
|
209
|
+
- **`dsh: pnpm not found on PATH`?** 装 pnpm 后**新开终端**再试(`corepack enable` 或 `npm i -g pnpm`)。
|
|
210
|
+
- **安装时卡在 git 凭据/404?** 仓库是公开的(`omdsh-dev/dsh-genui`),上面的 git URL 无需登录;`@changfenhuang/dsh-genui` 返回 404,表示 npm 包尚未发布。
|
|
211
|
+
- **装了但 scene3d/mermaid/echarts 不渲染?** 引擎(mermaid / three / echarts)不再内联进 client.js——它们在首次用到时按需加载(`/plugins/@changfenhuang/dsh-genui/assets/*.js`,插件自带 HTTP 路由托管)。先重启 dsh web + 硬刷新(Cmd+Shift+R);仍不渲染就卸掉重装(`dsh plugin --profile web remove @changfenhuang/dsh-genui` 后再 add)。旧版宿主缺少资产路由时会降级显示源码/加载失败提示,更新 dsh 即可。
|
|
212
|
+
- **模型不主动输出?** 重启后新会话生效;或直接说"用 dsh-ui 输出"。
|
|
213
|
+
- **clone 后没有 lib/?** `pnpm install && pnpm run check` 自己构建。
|
|
214
|
+
|
|
215
|
+
## 🧑💻 开发
|
|
216
|
+
|
|
217
|
+
```sh
|
|
218
|
+
pnpm install
|
|
219
|
+
pnpm run check # 类型检查 + 全量测试 + 构建
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 真机 e2e
|
|
223
|
+
|
|
224
|
+
真实链路验证:起一个临时 dsh web → 装上插件 → 浏览器里发消息让模型输出 `dsh-ui` fence → 断言渲染 → 点击 action 按钮 → 断言模型响应(事件循环闭环):
|
|
225
|
+
|
|
226
|
+
```sh
|
|
227
|
+
DEEPSEEK_API_KEY=sk-... node scripts/e2e.mjs # link 安装当前工作区
|
|
228
|
+
DEEPSEEK_API_KEY=sk-... node scripts/e2e.mjs --install git # 朋友路径(git URL)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
前置:`dsh`/`pnpm` 在 PATH、`DEEPSEEK_API_KEY`、主仓 web 构建产物(playwright 从主仓解析)。PASS 时保存 `e2e-final.png` 截图。
|
|
232
|
+
|
|
233
|
+
### 视觉 e2e(无需模型 key)
|
|
234
|
+
|
|
235
|
+
样式/组件迭代用:起真实 dsh web + link 安装插件 → 通过 DOM 通道注入组件画廊围栏 → headless Chrome 全页截图 + 本地交互(表格排序 / 判题 / 目录折叠 / 数值对齐)硬断言,不需要任何模型额度:
|
|
236
|
+
|
|
237
|
+
```sh
|
|
238
|
+
npx tsx scripts/e2e-visual.mts # → .e2e-artifacts/gallery.png + interactions.png
|
|
239
|
+
npx tsx scripts/e2e-visual.mts --keep # 保留 scratch DSH_HOME 便于排查
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
可覆盖:`--port 3098`、`--out <dir>`、`DSH_BIN`(默认 npm 生产模式 `~/node_modules/.bin/dsh`)、`PLAYWRIGHT_PATH`(默认全局 playwright-core)。
|
|
243
|
+
|
|
244
|
+
## 🗺️ Roadmap(已评估项)
|
|
245
|
+
|
|
246
|
+
| 方向 | 结论 | 理由 |
|
|
247
|
+
|---|---|---|
|
|
248
|
+
| 增量 patch(模型只发 diff 不重发全量 spec) | 不做 | fence 一次 200–800 token,重发代价极小;patch 协议的教学成本与出错率不值得。若未来出现秒级自动刷新面板再议 |
|
|
249
|
+
| action 防抖/去重 | ✅ 已做(300ms 尾沿,按 action 名独立) | 连点刷屏是真实摩擦,收口点一处改动 |
|
|
250
|
+
| 跨会话状态持久化(回放恢复 tabs/开关) | 不做 | 回放重置是更正确的默认行为(模型已用新 fence 更新过界面);流式期间状态天然保留 |
|
|
251
|
+
| MCP 适配器 / 独立画廊页 / i18n | 不做 | 无跨工具需求信号;画廊素材已被 `gallery.ts` + demo-prompts + README 截图覆盖;内置文案仅 6 处 |
|
|
252
|
+
|
|
253
|
+
单元测试和构建直接使用锁定的 dsh rc.8 发布包;只有源码级或端到端检查才需要设置 `DSH_ROOT`。
|
|
254
|
+
|
|
255
|
+
## 🔗 友情链接
|
|
256
|
+
|
|
257
|
+
- [Linux.do](https://linux.do)
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
📄 License: MIT
|