deepseek-harness-intelligent-ui 0.2.1 → 0.2.3

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 CHANGED
@@ -6,6 +6,25 @@ All notable changes to this project are documented here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.3]
10
+
11
+ ### Changed
12
+
13
+ - Verified against DeepSeek Harness 0.2.1-alpha.4 (install smoke test and the 24-check browser E2E pass with no code changes). It is now in `TESTED_DSH_VERSIONS`.
14
+ - Redesigned both READMEs with animated SVG illustrations (hero, agent routing, widget streaming, security model), a highlights grid, badges, a compatibility table and collapsible sections. `npm run docs:art` regenerates the illustrations.
15
+
16
+ ## [0.2.2]
17
+
18
+ ### Fixed
19
+
20
+ - npm co-installation with the supported DSH 0.2.0-rc and 0.2.1-alpha lines now uses explicit prerelease peer ranges.
21
+ - README installation examples use the 0.2.2 release version, explain the optional `next` tag, and link to versioned documentation and media outside the tarball.
22
+
23
+ ### Changed
24
+
25
+ - Release reruns verify registry integrity, exact package contents and provenance before reusing a version. GitHub Release assets come from that registry tarball and conflicting assets are refused.
26
+ - Release preflight requires the tagged commit to belong to main. Actions use immutable commit SHAs, and publishing can opt into npm Trusted Publishing after account-side setup.
27
+
9
28
  ## [0.2.1]
10
29
 
11
30
  ### Changed
@@ -18,7 +37,7 @@ All notable changes to this project are documented here. The format follows
18
37
  - Real-model evaluation now reads `DEEPSEEK_API_KEY` from the environment, validates requested rendered components and multi-turn data, acknowledges all tool calls, and exits nonzero on failures. Partial runs no longer combine historical results under a new timestamp. API errors and missing messages fail clearly; requests have a timeout.
19
38
  - Marked the legacy evaluation report's missing-Chart false positive and clarified the limits of API-only evaluation in both READMEs.
20
39
 
21
- ## [0.2.0]
40
+ ## 0.2.0 (development milestone)
22
41
 
23
42
  ### Changed
24
43
 
@@ -37,7 +56,7 @@ All notable changes to this project are documented here. The format follows
37
56
  - A nightly compatibility matrix across DSH versions (install smoke test plus browser E2E).
38
57
  - A tag-driven release that publishes to npm with provenance and creates the GitHub Release.
39
58
 
40
- ## [0.1.0]
59
+ ## 0.1.0 (development milestone)
41
60
 
42
61
  ### Added
43
62
 
@@ -45,6 +64,7 @@ All notable changes to this project are documented here. The format follows
45
64
  - The declarative component catalog (`ui_render`) and sandboxed streaming HTML widgets (`ui_render_widget`).
46
65
  - The `/ui` command and the guidance system-prompt section.
47
66
 
48
- [Unreleased]: https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/compare/v0.2.0...HEAD
49
- [0.2.0]: https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/compare/v0.1.0...v0.2.0
50
- [0.1.0]: https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/releases/tag/v0.1.0
67
+ [Unreleased]: https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/compare/v0.2.3...HEAD
68
+ [0.2.3]: https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/compare/v0.2.2...v0.2.3
69
+ [0.2.2]: https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/compare/v0.2.1...v0.2.2
70
+ [0.2.1]: https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/releases/tag/v0.2.1
package/README.md CHANGED
@@ -1,42 +1,155 @@
1
- # DeepSeek Harness Intelligent UI
1
+ <div align="center">
2
2
 
3
- English | [中文](README.zh-CN.md)
3
+ <img src="https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/main/docs/assets/readme/hero.svg" alt="DeepSeek Harness Intelligent UI: generative, interactive UI for DeepSeek Harness" width="100%">
4
4
 
5
- [![CI](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/actions/workflows/ci.yml) [![npm](https://img.shields.io/npm/v/deepseek-harness-intelligent-ui)](https://www.npmjs.com/package/deepseek-harness-intelligent-ui)
5
+ **English** · [中文](README.zh-CN.md)
6
+
7
+ [![CI](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/actions/workflows/ci.yml)
8
+ [![npm](https://img.shields.io/npm/v/deepseek-harness-intelligent-ui?color=4d6bfe&label=npm)](https://www.npmjs.com/package/deepseek-harness-intelligent-ui)
9
+ [![DSH](https://img.shields.io/badge/DeepSeek%20Harness-0.1.7%20%E2%80%93%200.2.x-22d3ee)](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/compatibility.md)
10
+ [![Node](https://img.shields.io/badge/node-%E2%89%A5%2022.13-34d399)](https://nodejs.org)
11
+ [![OS](https://img.shields.io/badge/OS-Windows%20%7C%20Linux%20%7C%20macOS-a78bfa)](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/compatibility.md)
12
+ [![License: MIT](https://img.shields.io/badge/license-MIT-97a1c9)](LICENSE)
13
+
14
+ [Demo](#-demo) · [Quick start](#-quick-start) · [How it decides](#-how-the-agent-decides) · [Widgets](#-sandboxed-widgets-ui_render_widget) · [Security](#-security-model) · [Configuration](#%EF%B8%8F-configuration) · [Develop](#-develop-and-verify)
15
+
16
+ </div>
6
17
 
7
18
  Generative, interactive UI for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH). Ask in plain language and the agent decides on its own whether to answer with text, with native components (dashboards, tables, charts, timelines, live function plots, KaTeX math, Mermaid diagrams, forms), or with a fully custom **sandboxed live widget** (Three.js scenes, canvas simulations, mini-apps). The UI renders progressively in the chat while the answer streams. Sliders, rotation, zoom, sorting and tabs respond instantly in the browser. Only explicit actions (a button, a form, `Bridge.sendPrompt`) go back to the agent.
8
19
 
9
20
  It ports the ideas of CopilotKit's [OpenIntelligentUI](https://github.com/CopilotKit/OpenIntelligentUI) (Open Generative UI + A2UI-style declarative components) onto DSH's own extension points. It needs no CopilotKit, LangGraph, or external router.
10
21
 
11
- ## Demo
22
+ ## ✨ Highlights
23
+
24
+ <table>
25
+ <tr>
26
+ <td width="33%" valign="top">
27
+
28
+ ### 🧠 Decides by itself
29
+ No command needed. Each turn the agent picks text, native components or a live widget, guided by a system-prompt section.
30
+
31
+ </td>
32
+ <td width="33%" valign="top">
33
+
34
+ ### ⚡ Streams progressively
35
+ Components appear while the JSON streams. Widgets morph into **one** iframe and finalize in place: no rebuild, no flash.
36
+
37
+ </td>
38
+ <td width="33%" valign="top">
39
+
40
+ ### 🖱️ Local first
41
+ Sliders, rotate, zoom, sort, tabs and hover tooltips run in the browser and never call the model.
42
+
43
+ </td>
44
+ </tr>
45
+ <tr>
46
+ <td valign="top">
47
+
48
+ ### 🧩 20-component catalog
49
+ Cards, grids, tabs, tables, charts, timelines, `Plot`, KaTeX `Math`, `Mermaid`, forms. Validated before it renders.
12
50
 
13
- ![DeepSeek Harness Intelligent UI demo](docs/assets/demo.gif)
51
+ </td>
52
+ <td valign="top">
14
53
 
15
- 🎥 **Full-quality video (H.264, ~2 min):** [docs/assets/demo.mp4](docs/assets/demo.mp4)
54
+ ### 🔒 Sandboxed by default
55
+ Opaque-origin iframe, strict CSP, token-checked messages and a rate-limited bridge, all verified in a real browser.
16
56
 
57
+ </td>
58
+ <td valign="top">
59
+
60
+ ### 💾 State that survives
61
+ Open tabs, sort order, form values, sliders and `UI.state` survive turn folding, page reloads and stopped generations.
62
+
63
+ </td>
64
+ </tr>
65
+ </table>
66
+
67
+ ## 🎬 Demo
68
+
69
+ ![DeepSeek Harness Intelligent UI demo](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/demo.gif)
70
+
71
+ 🎥 **Full-quality video (H.264, ~2 min):** [docs/assets/demo.mp4](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/v0.2.1/docs/assets/demo.mp4)
72
+
73
+ > [!NOTE]
17
74
  > The recording comes from the real DSH Web 0.2.0-rc.1 with this plugin installed, driven by `npm run e2e:all -- --record`. The model behind it is the **scripted mock** in `scripts/e2e/` (no API key was available), so the answers are canned. Everything you see (streaming, rendering, interaction, the round trips, persistence, isolation) is the real plugin running in DSH.
18
- >
19
- > To get an inline player on GitHub, drag `docs/assets/demo.mp4` into a GitHub comment or release editor and paste the resulting `https://github.com/user-attachments/assets/…` URL on its own line here. GitHub only renders inline video for uploaded attachments, not for repository files.
75
+
76
+ <details>
77
+ <summary><b>📸 Screenshot gallery</b> (dashboard, Three.js, math, forms, streaming, dark mode, phone, reload)</summary>
78
+ <br>
20
79
 
21
80
  | Dashboard streams in, then settles | Three.js widget: R slider, rotate, zoom |
22
81
  |:---:|:---:|
23
- | ![Dashboard](docs/assets/screenshots/3-dashboard.png) | ![Sphere](docs/assets/screenshots/7-widget-rotated.png) |
82
+ | ![Dashboard](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/3-dashboard.png) | ![Sphere](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/7-widget-rotated.png) |
24
83
  | *Stat, Grid, Tabs, stacked bar chart with hover tooltip, sortable table, timeline, form* | *`x²+y²+z²=2Rz` via `UI.three()`: the slider re-shapes the surface locally* |
25
84
 
26
85
  | Math, live Plot, Mermaid | Form → agent → new UI |
27
86
  |:---:|:---:|
28
- | ![Math](docs/assets/screenshots/9-math.png) | ![Form](docs/assets/screenshots/4-form-sent.png) |
87
+ | ![Math](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/9-math.png) | ![Form](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/4-form-sent.png) |
29
88
  | *KaTeX formula, `Plot` with parameter sliders (no model call), Mermaid flowchart* | *Submitted values reach the agent, which answers with a forecast chart* |
30
89
 
31
90
  | Streaming preview (same iframe becomes final) | Stopped mid-generation |
32
91
  |:---:|:---:|
33
- | ![Preview](docs/assets/screenshots/5-widget-preview.png) | ![Stopped](docs/assets/screenshots/10-stopped.png) |
92
+ | ![Preview](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/5-widget-preview.png) | ![Stopped](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/10-stopped.png) |
34
93
 
35
94
  | Dark theme | Phone width (dark) | After reload |
36
95
  |:---:|:---:|:---:|
37
- | ![Dark](docs/assets/screenshots/11b-dark-widget.png) | ![Mobile](docs/assets/screenshots/12-mobile-dark.png) | ![Reload](docs/assets/screenshots/14-reload.png) |
96
+ | ![Dark](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/11b-dark-widget.png) | ![Mobile](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/12-mobile-dark.png) | ![Reload](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/14-reload.png) |
97
+
98
+ To get an inline player on GitHub, drag `docs/assets/demo.mp4` into a GitHub comment or release editor and paste the resulting `https://github.com/user-attachments/assets/…` URL on its own line here. GitHub only renders inline video for uploaded attachments, not for repository files.
99
+
100
+ </details>
101
+
102
+ ## 🚀 Quick start
103
+
104
+ You need [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) **0.1.7 – 0.2.x** (`>=0.1.7-rc.1 <0.3.0`) and Node.js ≥ 22.13, on Windows, Linux or macOS. Nothing is compiled during install. The package ships its prebuilt browser bundle and declares no install scripts.
105
+
106
+ ```sh
107
+ dsh plugin --profile web add deepseek-harness-intelligent-ui
108
+ ```
109
+
110
+ Then restart DSH Web (`dsh web`) and ask for something visual, for example *"compare Q1–Q4 revenue by channel"* or *"let me explore x²+y²+z²=2Rz in 3D"*.
111
+
112
+ To have your environment checked first, use the guided installer instead. It verifies Node, the `dsh` version, pnpm and the profile, then runs the same `dsh plugin add`:
113
+
114
+ ```sh
115
+ npx deepseek-harness-intelligent-ui install # --profile <name>, --dsh <path>, --dry-run
116
+ npx deepseek-harness-intelligent-ui doctor # diagnose only
117
+ ```
118
+
119
+ | Task | Command |
120
+ |---|---|
121
+ | Upgrade | `dsh plugin --profile web add deepseek-harness-intelligent-ui@latest` |
122
+ | Try a prerelease (only when the `next` dist-tag exists) | `dsh plugin --profile web add deepseek-harness-intelligent-ui@next` |
123
+ | Pin a version | `dsh plugin --profile web add deepseek-harness-intelligent-ui@0.2.3` |
124
+ | Uninstall | `dsh plugin --profile web remove deepseek-harness-intelligent-ui` (or `npx deepseek-harness-intelligent-ui uninstall`) |
125
+ | From a checkout | `dsh plugin --profile web add file:/path/to/deepseek-harness-intelligent-ui` |
126
+
127
+ <details>
128
+ <summary><b>🩺 Troubleshooting</b></summary>
129
+ <br>
130
+
131
+ - *`pnpm was not found`*: DSH installs plugins with pnpm. Run `corepack enable` (it ships with Node) or `npm i -g pnpm`.
132
+ - *`… is incompatible with dsh X`*: your DSH is outside the supported range. Upgrade DSH (`npm i -g @deepseek-ai/dsh@latest`) or check [compatibility](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/compatibility.md) for a plugin release that supports it.
133
+ - *Upgrading from 0.1.x (`dsh-intelligent-ui` via `file:`)*: run `dsh plugin --profile web remove dsh-intelligent-ui` first. Both packages insert the same `intelligent-ui` row, and `doctor` reports the conflict.
134
+ - *The UI does not appear*: restart DSH Web after installing, and make sure you started the profile you installed into (`dsh web`).
135
+
136
+ </details>
137
+
138
+ ### Compatibility
139
+
140
+ | DeepSeek Harness | Install smoke test | Browser E2E (24 checks) |
141
+ |---|:---:|:---:|
142
+ | `0.1.7-rc.2` | ✅ | ✅ |
143
+ | `0.2.0-rc.1` | ✅ | ✅ |
144
+ | `0.2.0-rc.2` (`latest`) | ✅ | ✅ |
145
+ | `0.2.1-alpha.2` | ✅ | ✅ |
146
+ | `0.2.1-alpha.4` (`alpha`) | ✅ | ✅ |
147
+
148
+ CI runs the matrix on Windows, Linux and macOS, nightly too, so new DSH releases are caught early. Details: [docs/compatibility.md](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/compatibility.md).
38
149
 
39
- ## How the agent decides
150
+ ## 🧠 How the agent decides
151
+
152
+ <img src="https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/main/docs/assets/readme/routing.svg" alt="The agent routes each prompt to plain text, ui_render or ui_render_widget; local interactions never call the model, explicit actions go back to the agent" width="100%">
40
153
 
41
154
  The plugin injects a system-prompt section (`src/guidance.js`) that makes the model route each turn itself. There is no command and no external router:
42
155
 
@@ -47,33 +160,44 @@ The plugin injects a system-prompt section (`src/guidance.js`) that makes the mo
47
160
 
48
161
  `/ui <request>` still exists to force a UI answer.
49
162
 
50
- ## Tools
51
-
52
163
  | Tool | Use it for | Rendering |
53
164
  |---|---|---|
54
165
  | `ui_render` | Structured answers | Native React components from a fixed catalog, rendered progressively as the JSON streams |
55
166
  | `ui_render_widget` | Custom visuals, 3D, simulations, mini-apps | HTML/CSS/JS in an opaque-origin sandboxed iframe: CSS first, HTML morphed in live, JS last, all in **one** iframe |
56
167
 
57
- ### Component catalog (`ui_render`)
168
+ ## 🧩 Component catalog (`ui_render`)
58
169
 
59
- `Card`, `Stack`, `Grid`, `Tabs` (keyboard navigable), `Text` (markdown subset), `Code`, `Alert`, `Badge`, `Divider`, `Stat`, `Progress`, `List`, `Table` (sortable), `Chart` (bar / line / area / pie, stacked, hover tooltip, toggleable legend), `Timeline`, **`Plot`** (y = f(x) with parameter sliders that redraw instantly; expressions run in a safe compiler, never `eval`), **`Math`** (KaTeX), **`Mermaid`** (flowchart, sequence, class, state, ER, gantt, mindmap…), `Button` (sends a prompt), and `Form` (text, number, **range slider**, select, checkbox, date, textarea; submits the values as a message).
170
+ | Category | Components |
171
+ |---|---|
172
+ | Layout | `Card`, `Stack`, `Grid`, `Tabs` (keyboard navigable) |
173
+ | Text & callouts | `Text` (markdown subset), `Code`, `Alert`, `Badge`, `Divider` |
174
+ | Data | `Stat`, `Progress`, `List`, `Table` (sortable), `Timeline` |
175
+ | Charts | `Chart`: bar / line / area / pie, stacked, hover tooltip, toggleable legend |
176
+ | Math & diagrams | **`Plot`** (y = f(x) with parameter sliders that redraw instantly; expressions run in a safe compiler, never `eval`), **`Math`** (KaTeX), **`Mermaid`** (flowchart, sequence, class, state, ER, gantt, mindmap…) |
177
+ | Interaction | `Button` (sends a prompt), `Form` (text, number, **range slider**, select, checkbox, date, textarea; submits the values as a message) |
60
178
 
61
179
  A UI travels as a **flat node list with id references**, because DSH's tool-schema subset has no recursion. The Host validates it before acknowledging: unknown types or props, dangling or duplicate ids, cycles, two parents, chart length mismatches, `Plot` expressions that do not compile, slider defaults out of range, and so on. Problems come back as `ok:false` with paths, so the model can fix them and retry.
62
180
 
63
181
  `Math` and `Mermaid` render inside the same sandbox as widgets, loading KaTeX or Mermaid from the CDN allowlist. No third-party code runs in the DSH page and the host bundle stays small (~127 KB). If the CDN is unreachable, the source text is shown instead.
64
182
 
65
- ### Widgets (`ui_render_widget`)
183
+ ## 🪟 Sandboxed widgets (`ui_render_widget`)
184
+
185
+ <img src="https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/main/docs/assets/readme/widget-streaming.svg" alt="Widget fields stream in order: placeholder, then a live preview with morphed HTML, then the same iframe is finalized and the code runs" width="100%">
66
186
 
67
187
  Fields follow the OpenIntelligentUI streaming contract, **in this order**: `title`, `initialHeight`, `placeholderMessages`, `css`, `html`, `jsFunctions`, `jsExpressions`.
68
188
 
69
189
  - **Streaming:** placeholder lines show until `css` is complete. Then a preview frame opens and the cleaned partial `html` is morphed in ([idiomorph](https://github.com/bigskysoftware/idiomorph)). When the arguments are complete, the **same frame is finalized in place**: the final HTML is morphed and the code runs. There is no rebuild, blank flash or height jump.
70
190
  - **Runtime helpers** (global `UI`):
71
- - `UI.three(el, { camera, target, autoRotate })` returns a renderer, scene, lights and OrbitControls (drag rotates, wheel/pinch zooms), renders on demand, and handles resize.
72
- - `UI.canvas(el, draw)` gives a HiDPI 2D canvas that is redrawn on resize and theme change.
73
- - `UI.state` / `UI.setState()` persist state. Inputs with an `id` are persisted and restored automatically.
74
- - `UI.color('accent')` returns an opaque theme color for three.js/canvas, and `UI.css()` returns a raw value.
75
- - `UI.onTheme(cb)`, `UI.scheme` and `UI.reducedMotion` are also available.
76
- - Helper classes: `.ui-row`, `.ui-control`, `.ui-card`, `.ui-stage`.
191
+
192
+ | Helper | What it does |
193
+ |---|---|
194
+ | `UI.three(el, { camera, target, autoRotate })` | Renderer, scene, lights and OrbitControls (drag rotates, wheel/pinch zooms); renders on demand and handles resize |
195
+ | `UI.canvas(el, draw)` | HiDPI 2D canvas, redrawn on resize and theme change |
196
+ | `UI.state` / `UI.setState()` | Persisted state; inputs with an `id` are persisted and restored automatically |
197
+ | `UI.color('accent')` / `UI.css()` | Opaque theme color for three.js/canvas / raw CSS value |
198
+ | `UI.onTheme(cb)`, `UI.scheme`, `UI.reducedMotion` | React to theme and motion preferences |
199
+ | `.ui-row`, `.ui-control`, `.ui-card`, `.ui-stage` | Helper classes |
200
+
77
201
  - **Bridge:** `Bridge.sendPrompt({ text })` disables the clicked control until the host answers, so double clicks cannot queue duplicates. `Bridge.openLink({ url })` opens links, and `Websandbox.connection.remote.*` is kept for OpenIntelligentUI compatibility.
78
202
  - **Libraries:** an importmap maps `three`, `three/addons/…`, `d3`, `chart.js/auto`, `gsap` and `canvas-confetti` to esm.sh.
79
203
  - **Recovery:** script errors show a count with **Reload** and **Ask to fix** (the latter sends the errors to the agent).
@@ -87,56 +211,20 @@ Fields follow the OpenIntelligentUI streaming contract, **in this order**: `titl
87
211
  - If the call already reached DSH, the view keeps the finished part (a static widget preview or the completed components) with a notice and a **Regenerate** button.
88
212
  - If the user stops while the arguments are still streaming, DSH drops the call entirely. The plugin stashes what was streamed and shows it beneath the stopped turn the same way.
89
213
 
90
- ## Security model
214
+ ## 🔒 Security model
215
+
216
+ <img src="https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/main/docs/assets/readme/security.svg" alt="Widgets run in an opaque-origin sandboxed iframe under a strict CSP; access to the host page is blocked and only token-checked postMessage calls reach the rate-limited bridge" width="100%">
91
217
 
92
218
  - **Widget isolation:** widgets run in `<iframe sandbox="allow-scripts allow-forms">` with `srcdoc` and **no** `allow-same-origin`. They cannot reach the DSH page, its cookies or storage, or its API. The E2E checks this in the browser: `parent.document`, `localStorage` and `document.cookie` all throw `SecurityError`, `fetch` is blocked, and `window.origin === "null"`.
93
- - **CSP:**
94
- - `default-src 'none'`.
95
- - Scripts, styles, fonts and images load only from `cdnAllowlist`.
96
- - `connect-src 'none'` unless `allowNetwork` is on.
97
- - `form-action 'none'` and `base-uri 'none'`.
219
+ - **CSP:** `default-src 'none'`; scripts, styles, fonts and images load only from `cdnAllowlist`; `connect-src 'none'` unless `allowNetwork` is on; `form-action 'none'` and `base-uri 'none'`.
98
220
  - **Messages from the frame:** they are accepted only from that frame's `contentWindow`, must carry a per-frame random token, and are shape-checked. Persisted widget state is size-limited JSON. The E2E checks that forged messages from the page or the frame are dropped.
99
- - **`sendPrompt` limits:**
100
- - It is refused during the first second after mount.
101
- - At most one send every 2 seconds.
102
- - Text is capped at `sendPromptMaxChars`.
103
- - The message is queued as a normal user message.
221
+ - **`sendPrompt` limits:** refused during the first second after mount; at most one send every 2 seconds; text capped at `sendPromptMaxChars`; queued as a normal user message.
104
222
  - **`openLink`:** https only, optionally restricted to `openLinkAllowedOrigins`.
105
223
  - **Catalog:** text renders as React elements, never raw HTML. `Plot` expressions are compiled by a tokenizer/parser over a fixed math function table, with no `eval`, `Function`, or property access.
106
224
 
107
- ## Install
108
-
109
- You need [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) **0.1.7 – 0.2.x** (`>=0.1.7-rc.1 <0.3.0`) and Node.js ≥ 22.13, on Windows, Linux or macOS. Nothing is compiled during install. The package ships its prebuilt browser bundle and declares no install scripts.
110
-
111
- ```sh
112
- dsh plugin --profile web add deepseek-harness-intelligent-ui
113
- ```
114
-
115
- To have your environment checked first, use the guided installer instead. It verifies Node, the `dsh` version, pnpm and the profile, then runs the same `dsh plugin add`:
116
-
117
- ```sh
118
- npx deepseek-harness-intelligent-ui install # --profile <name>, --dsh <path>, --dry-run
119
- npx deepseek-harness-intelligent-ui doctor # diagnose only
120
- ```
121
-
122
- | Task | Command |
123
- |---|---|
124
- | Upgrade | `dsh plugin --profile web add deepseek-harness-intelligent-ui@latest` |
125
- | Try a prerelease | `dsh plugin --profile web add deepseek-harness-intelligent-ui@next` |
126
- | Pin a version | `dsh plugin --profile web add deepseek-harness-intelligent-ui@0.2.0` |
127
- | Uninstall | `dsh plugin --profile web remove deepseek-harness-intelligent-ui` (or `npx deepseek-harness-intelligent-ui uninstall`) |
128
- | From a checkout | `dsh plugin --profile web add file:/path/to/deepseek-harness-intelligent-ui` |
129
-
130
- Supported DSH versions and the CI matrix are in [docs/compatibility.md](docs/compatibility.md).
225
+ ## ⚙️ Configuration
131
226
 
132
- **Troubleshooting**
133
-
134
- - *`pnpm was not found`*: DSH installs plugins with pnpm. Run `corepack enable` (it ships with Node) or `npm i -g pnpm`.
135
- - *`… is incompatible with dsh X`*: your DSH is outside the supported range. Upgrade DSH (`npm i -g @deepseek-ai/dsh@latest`) or check [compatibility](docs/compatibility.md) for a plugin release that supports it.
136
- - *Upgrading from 0.1.x (`dsh-intelligent-ui` via `file:`)*: run `dsh plugin --profile web remove dsh-intelligent-ui` first. Both packages insert the same `intelligent-ui` row, and `doctor` reports the conflict.
137
- - *The UI does not appear*: restart DSH Web after installing, and make sure you started the profile you installed into (`dsh web`).
138
-
139
- Restart DSH Web afterwards. The bundle patch inserts the plugin row automatically. To change settings, add to your profile's `cordis.patch.yml`:
227
+ The bundle patch inserts the plugin row automatically. To change settings, add to your profile's `cordis.patch.yml`:
140
228
 
141
229
  ```yaml
142
230
  - id: intelligent-ui
@@ -157,7 +245,7 @@ Restart DSH Web afterwards. The bundle patch inserts the plugin row automaticall
157
245
  | `sendPromptMaxChars` | `4000` | Longest message a widget, button or form may send |
158
246
  | `openLinkAllowedOrigins` | `[]` | If non-empty, the only origins `openLink` may open |
159
247
 
160
- ## Develop and verify
248
+ ## 🛠 Develop and verify
161
249
 
162
250
  ```sh
163
251
  npm install
@@ -168,11 +256,44 @@ npm run e2e:all # build → install into a temp DSH home → mock model + re
168
256
  npm run e2e:all -- --record # also re-records docs/assets/demo.mp4 / demo.gif (needs ffmpeg)
169
257
  npm run e2e:all -- --spec ./deepseek-harness-intelligent-ui-<v>.tgz # E2E the packed tarball instead of the checkout
170
258
  npm run smoke -- --spec ./deepseek-harness-intelligent-ui-<v>.tgz # install smoke test (no browser): version gate, bundle row, DSH Web boot
259
+ npm run docs:art # regenerate the animated README illustrations in docs/assets/readme/
171
260
  ```
172
261
 
173
- The E2E runs on Windows, Linux and macOS. It finds Chrome per platform (set `CHROME_PATH` to override) and uses `DSH_BIN` to test another `dsh` binary. CI runs everything on all three OSes against every supported DSH line ([compatibility](docs/compatibility.md)).
262
+ The E2E runs on Windows, Linux and macOS. It finds Chrome per platform (set `CHROME_PATH` to override) and uses `DSH_BIN` to test another `dsh` binary. CI runs everything on all three OSes against every supported DSH line ([compatibility](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/compatibility.md)).
174
263
 
175
- **Releasing** (maintainers):
264
+ - **Layout:** `src/` is the Host half (plain ESM, no build). `client-src/` is the browser half (TSX, bundled with esbuild). `client/client.js` is committed and published so npm, `file:` and git installs need no build step. CI fails if it is stale. Never add a `prepare`/`postinstall` script, because DSH's pnpm blocks plugin build scripts.
265
+ - Requires Chrome (`CHROME_PATH`), `dsh` on PATH and, for `--record`, `ffmpeg`. Headless Chrome uses SwiftShader for WebGL.
266
+
267
+ <details>
268
+ <summary><b>✅ What the browser E2E checks</b> (<code>scripts/e2e/browser.mjs</code>)</summary>
269
+ <br>
270
+
271
+ Report: [`docs/e2e-report.json`](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/v0.2.1/docs/e2e-report.json).
272
+
273
+ - Plain Q&A stays text.
274
+ - The dashboard streams progressively.
275
+ - Chart hover, table sort and tabs are local.
276
+ - A form round-trip returns a new UI.
277
+ - The preview iframe is finalized in place.
278
+ - The Three.js scene renders, and the R slider, drag-rotate and wheel-zoom work.
279
+ - The `Bridge.sendPrompt` round trip works.
280
+ - KaTeX and Mermaid render.
281
+ - Plot sliders work.
282
+ - Earlier UIs keep their state.
283
+ - Stop → static preview → Regenerate works.
284
+ - The sandbox is isolated and forged messages are ignored.
285
+ - Dark theme reaches cards and widgets.
286
+ - Phone width has no overflow.
287
+ - A reload restores the UIs and their state.
288
+ - No plugin console errors appear.
289
+
290
+ </details>
291
+
292
+ <details>
293
+ <summary><b>📦 Releasing</b> (maintainers)</summary>
294
+ <br>
295
+
296
+ See [release security and OIDC setup](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/releasing.md).
176
297
 
177
298
  1. Add the notes under a new `## [x.y.z]` heading in [CHANGELOG.md](CHANGELOG.md).
178
299
  2. Run `npm version x.y.z` (or `npm version prerelease --preid rc`). This rebuilds `client/client.js` with the new version and tags the commit.
@@ -183,31 +304,15 @@ The E2E runs on Windows, Linux and macOS. It finds Chrome per platform (set `CHR
183
304
  - creates the GitHub Release with the changelog section and the tarball.
184
305
  4. Run `npm run release:check` to perform the same preflight locally.
185
306
 
186
- - **Layout:** `src/` is the Host half (plain ESM, no build). `client-src/` is the browser half (TSX, bundled with esbuild). `client/client.js` is committed and published so npm, `file:` and git installs need no build step. CI fails if it is stale. Never add a `prepare`/`postinstall` script, because DSH's pnpm blocks plugin build scripts.
187
- - **What the E2E checks** (`scripts/e2e/browser.mjs`, report in [`docs/e2e-report.json`](docs/e2e-report.json)):
188
- - Plain Q&A stays text.
189
- - The dashboard streams progressively.
190
- - Chart hover, table sort and tabs are local.
191
- - A form round-trip returns a new UI.
192
- - The preview iframe is finalized in place.
193
- - The Three.js scene renders, and the R slider, drag-rotate and wheel-zoom work.
194
- - The `Bridge.sendPrompt` round trip works.
195
- - KaTeX and Mermaid render.
196
- - Plot sliders work.
197
- - Earlier UIs keep their state.
198
- - Stop → static preview → Regenerate works.
199
- - The sandbox is isolated and forged messages are ignored.
200
- - Dark theme reaches cards and widgets.
201
- - Phone width has no overflow.
202
- - A reload restores the UIs and their state.
203
- - No plugin console errors appear.
204
- - Requires Chrome (`CHROME_PATH`), `dsh` on PATH and, for `--record`, `ffmpeg`. Headless Chrome uses SwiftShader for WebGL.
307
+ </details>
205
308
 
206
- ## Real-model Evaluation
309
+ <details>
310
+ <summary><b>🤖 Real-model evaluation</b></summary>
311
+ <br>
207
312
 
208
313
  The API suite checks model routing, tool-argument schemas, and selected requested components or data across 15 prompts. It does **not** execute model-generated widgets in a browser or verify factual data, visual quality, physics, or interaction behavior. The separate browser E2E uses scripted model responses.
209
314
 
210
- The checked-in [historical report](docs/real-model-eval-report.json) was produced by the earlier evaluator. Its 15/15 result is not a current pass rate: B3 was incorrectly accepted despite containing no Chart. Other cases need a new run under the stricter assertions; the original report is retained with an audit note.
315
+ The checked-in [historical report](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/v0.2.1/docs/real-model-eval-report.json) was produced by the earlier evaluator. Its 15/15 result is not a current pass rate: B3 was incorrectly accepted despite containing no Chart. Other cases need a new run under the stricter assertions; the original report is retained with an audit note.
211
316
 
212
317
  The current suite requires rendered components (not orphan nodes), a sortable table for B2, a four-quarter multi-series bar chart for B3, range/checkbox form controls for B4, and parameter sliders for a native C2 Plot. Multi-turn cases validate all tool calls, acknowledge each call, require the submitted APAC/4/Optimistic parameters, and check all three requested screen sizes while retaining existing table values. These are automated assertions, not a complete quality assessment.
213
318
 
@@ -225,6 +330,8 @@ node scripts/run-real-model-suite.mjs all
225
330
 
226
331
  Each invocation writes only that run's cases to `docs/real-model-eval-report.json`. A partial run does not merge older cases into a new timestamp. Failed assertions/API calls exit with code 1; an invalid category or missing key fails before changing the report. Keep keys out of git.
227
332
 
333
+ </details>
334
+
228
335
  ## Limitations
229
336
 
230
337
  - Widgets, Math and Mermaid need the CDN allowlist to be reachable. Offline, Math/Mermaid fall back to source text and `UI.three` reports a script error.
package/README.zh-CN.md CHANGED
@@ -1,8 +1,19 @@
1
- # DeepSeek Harness Intelligent UI(智能界面)
1
+ <div align="center">
2
2
 
3
- [English](README.md) | 中文
3
+ <img src="https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/main/docs/assets/readme/hero.zh.svg" alt="DeepSeek Harness Intelligent UI:为 DeepSeek Harness 带来生成式、可交互的界面" width="100%">
4
4
 
5
- [![CI](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/actions/workflows/ci.yml) [![npm](https://img.shields.io/npm/v/deepseek-harness-intelligent-ui)](https://www.npmjs.com/package/deepseek-harness-intelligent-ui)
5
+ [English](README.md) · **中文**
6
+
7
+ [![CI](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/actions/workflows/ci.yml)
8
+ [![npm](https://img.shields.io/npm/v/deepseek-harness-intelligent-ui?color=4d6bfe&label=npm)](https://www.npmjs.com/package/deepseek-harness-intelligent-ui)
9
+ [![DSH](https://img.shields.io/badge/DeepSeek%20Harness-0.1.7%20%E2%80%93%200.2.x-22d3ee)](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/compatibility.md)
10
+ [![Node](https://img.shields.io/badge/node-%E2%89%A5%2022.13-34d399)](https://nodejs.org)
11
+ [![OS](https://img.shields.io/badge/OS-Windows%20%7C%20Linux%20%7C%20macOS-a78bfa)](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/compatibility.md)
12
+ [![License: MIT](https://img.shields.io/badge/license-MIT-97a1c9)](LICENSE)
13
+
14
+ [演示](#-演示) · [快速开始](#-快速开始) · [如何选择](#-agent-如何选择呈现方式) · [沙箱组件](#-沙箱组件ui_render_widget) · [安全](#-安全模型) · [配置](#%EF%B8%8F-配置) · [开发](#-开发与验证)
15
+
16
+ </div>
6
17
 
7
18
  为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)提供**生成式、可交互的 UI**。用户用自然语言提问,Agent 自行决定怎样作答:
8
19
 
@@ -14,36 +25,136 @@
14
25
 
15
26
  本插件把 CopilotKit [OpenIntelligentUI](https://github.com/CopilotKit/OpenIntelligentUI) 的思路(Open Generative UI + A2UI 风格声明式组件)移植到 DSH 自带的扩展点上,不依赖 CopilotKit、LangGraph 或外部路由服务。
16
27
 
17
- ## 演示
28
+ ## ✨ 亮点
29
+
30
+ <table>
31
+ <tr>
32
+ <td width="33%" valign="top">
33
+
34
+ ### 🧠 自主决策
35
+ 无需任何命令。每一轮由 Agent 依据系统提示,自行选择文本、原生组件或实时组件。
36
+
37
+ </td>
38
+ <td width="33%" valign="top">
39
+
40
+ ### ⚡ 流式渐进
41
+ JSON 还在生成,组件就已出现。实时组件在**同一个** iframe 中 morph 并原地定稿,不重建、不闪烁。
42
+
43
+ </td>
44
+ <td width="33%" valign="top">
45
+
46
+ ### 🖱️ 本地优先
47
+ 滑块、旋转、缩放、排序、标签页、悬停提示都在浏览器内完成,不调用模型。
48
+
49
+ </td>
50
+ </tr>
51
+ <tr>
52
+ <td valign="top">
53
+
54
+ ### 🧩 20 种组件
55
+ 卡片、栅格、标签页、表格、图表、时间线、`Plot`、KaTeX `Math`、`Mermaid`、表单,渲染前先校验。
18
56
 
19
- ![DeepSeek Harness Intelligent UI 演示](docs/assets/demo.gif)
57
+ </td>
58
+ <td valign="top">
20
59
 
21
- 🎥 **高清视频(H.264,约 2 分钟):** [docs/assets/demo.mp4](docs/assets/demo.mp4)
60
+ ### 🔒 默认沙箱隔离
61
+ 不透明源 iframe、严格 CSP、带 token 的消息校验、限流的 Bridge,全部在真实浏览器中实测。
22
62
 
23
- > **录制方式:** 演示视频录自真实的 DSH Web 0.2.0-rc.1,装好本插件后由 `npm run e2e:all -- --record` 自动驱动。
24
- >
25
- > **关于模型:** 背后的模型是 `scripts/e2e/` 中的**脚本化 mock**(当时没有 API Key),回答内容是预设的。画面中的流式渲染、交互、双向通信、持久化和隔离,都是插件在 DSH 中真实运行的结果。
26
- >
27
- > **在 GitHub 内联播放:** 把 `docs/assets/demo.mp4` 拖进 GitHub 的评论或 Release 编辑框,再把生成的 `https://github.com/user-attachments/assets/…` 链接单独一行粘贴到这里。GitHub 只对上传的附件内联播放视频,不支持仓库内的文件。
63
+ </td>
64
+ <td valign="top">
65
+
66
+ ### 💾 状态不丢失
67
+ 标签页、排序、表单值、滑块和 `UI.state` 在回合折叠、页面刷新、中途停止后都能恢复。
68
+
69
+ </td>
70
+ </tr>
71
+ </table>
72
+
73
+ ## 🎬 演示
74
+
75
+ ![DeepSeek Harness Intelligent UI 演示](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/demo.gif)
76
+
77
+ 🎥 **高清视频(H.264,约 2 分钟):** [docs/assets/demo.mp4](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/v0.2.1/docs/assets/demo.mp4)
78
+
79
+ > [!NOTE]
80
+ > 演示视频录自真实的 DSH Web 0.2.0-rc.1,装好本插件后由 `npm run e2e:all -- --record` 自动驱动。背后的模型是 `scripts/e2e/` 中的**脚本化 mock**(当时没有 API Key),回答内容是预设的。画面中的流式渲染、交互、双向通信、持久化和隔离,都是插件在 DSH 中真实运行的结果。
81
+
82
+ <details>
83
+ <summary><b>📸 截图集</b>(看板、Three.js、公式、表单、流式预览、深色主题、手机、刷新)</summary>
84
+ <br>
28
85
 
29
86
  | 看板流式出现并定稿 | Three.js 组件:R 滑块、旋转、缩放 |
30
87
  |:---:|:---:|
31
- | ![看板](docs/assets/screenshots/3-dashboard.png) | ![球面](docs/assets/screenshots/7-widget-rotated.png) |
88
+ | ![看板](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/3-dashboard.png) | ![球面](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/7-widget-rotated.png) |
32
89
  | *指标卡、栅格、标签页、带悬停提示的堆叠柱状图、可排序表格、时间线、表单* | *用 `UI.three()` 绘制 `x²+y²+z²=2Rz`,拖动滑块在本地即时改变曲面* |
33
90
 
34
91
  | 公式、实时函数图像、Mermaid | 表单 → Agent → 新界面 |
35
92
  |:---:|:---:|
36
- | ![数学](docs/assets/screenshots/9-math.png) | ![表单](docs/assets/screenshots/4-form-sent.png) |
93
+ | ![数学](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/9-math.png) | ![表单](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/4-form-sent.png) |
37
94
 
38
95
  | 流式预览(同一个 iframe 直接定稿) | 生成中途停止 |
39
96
  |:---:|:---:|
40
- | ![预览](docs/assets/screenshots/5-widget-preview.png) | ![停止](docs/assets/screenshots/10-stopped.png) |
97
+ | ![预览](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/5-widget-preview.png) | ![停止](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/10-stopped.png) |
41
98
 
42
99
  | 深色主题 | 手机宽度(深色) | 刷新后恢复 |
43
100
  |:---:|:---:|:---:|
44
- | ![深色](docs/assets/screenshots/11b-dark-widget.png) | ![移动端](docs/assets/screenshots/12-mobile-dark.png) | ![刷新](docs/assets/screenshots/14-reload.png) |
101
+ | ![深色](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/11b-dark-widget.png) | ![移动端](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/12-mobile-dark.png) | ![刷新](https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/v0.2.1/docs/assets/screenshots/14-reload.png) |
102
+
103
+ **在 GitHub 内联播放:** 把 `docs/assets/demo.mp4` 拖进 GitHub 的评论或 Release 编辑框,再把生成的 `https://github.com/user-attachments/assets/…` 链接单独一行粘贴到这里。GitHub 只对上传的附件内联播放视频,不支持仓库内的文件。
104
+
105
+ </details>
106
+
107
+ ## 🚀 快速开始
108
+
109
+ 需要 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) **0.1.7 – 0.2.x**(`>=0.1.7-rc.1 <0.3.0`)和 Node.js ≥ 22.13,Windows、Linux、macOS 均可。安装过程不需要编译:npm 包自带预构建的浏览器端 bundle,也没有任何安装脚本。
110
+
111
+ ```sh
112
+ dsh plugin --profile web add deepseek-harness-intelligent-ui
113
+ ```
114
+
115
+ 然后重启 DSH Web(`dsh web`),试着提一个需要可视化的问题,例如 *“按渠道对比 Q1–Q4 营收”* 或 *“让我在 3D 里探索 x²+y²+z²=2Rz”*。
116
+
117
+ 也可以用引导式安装器。它会先检查 Node、`dsh` 版本、pnpm 和 profile,检查通过后执行同样的 `dsh plugin add`:
118
+
119
+ ```sh
120
+ npx deepseek-harness-intelligent-ui install # 可选 --profile <名称>、--dsh <路径>、--dry-run
121
+ npx deepseek-harness-intelligent-ui doctor # 只诊断,不做修改
122
+ ```
123
+
124
+ | 操作 | 命令 |
125
+ |---|---|
126
+ | 升级 | `dsh plugin --profile web add deepseek-harness-intelligent-ui@latest` |
127
+ | 试用预发布版(仅在存在 `next` 标签时) | `dsh plugin --profile web add deepseek-harness-intelligent-ui@next` |
128
+ | 固定版本 | `dsh plugin --profile web add deepseek-harness-intelligent-ui@0.2.3` |
129
+ | 卸载 | `dsh plugin --profile web remove deepseek-harness-intelligent-ui`(或 `npx deepseek-harness-intelligent-ui uninstall`) |
130
+ | 从源码目录安装 | `dsh plugin --profile web add file:/path/to/deepseek-harness-intelligent-ui` |
45
131
 
46
- ## Agent 如何选择呈现方式
132
+ <details>
133
+ <summary><b>🩺 常见问题</b></summary>
134
+ <br>
135
+
136
+ - *提示 `pnpm was not found`*:DSH 用 pnpm 安装插件。运行 `corepack enable`(Node 自带)或 `npm i -g pnpm`。
137
+ - *提示 `… is incompatible with dsh X`*:当前 DSH 版本不在支持范围内。可以升级 DSH(`npm i -g @deepseek-ai/dsh@latest`),或在[兼容性文档](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/compatibility.md)里找支持该版本的插件发行版。
138
+ - *从 0.1.x 升级(以前用 `file:` 安装的 `dsh-intelligent-ui`)*:先运行 `dsh plugin --profile web remove dsh-intelligent-ui`。新旧两个包会插入同一个 `intelligent-ui` 行,`doctor` 能检测到这种冲突。
139
+ - *界面没有出现*:安装后要重启 DSH Web,并确认启动的是安装插件时指定的 profile(`dsh web`)。
140
+
141
+ </details>
142
+
143
+ ### 兼容性
144
+
145
+ | DeepSeek Harness | 安装冒烟测试 | 浏览器 E2E(24 项) |
146
+ |---|:---:|:---:|
147
+ | `0.1.7-rc.2` | ✅ | ✅ |
148
+ | `0.2.0-rc.1` | ✅ | ✅ |
149
+ | `0.2.0-rc.2`(`latest`) | ✅ | ✅ |
150
+ | `0.2.1-alpha.2` | ✅ | ✅ |
151
+ | `0.2.1-alpha.4`(`alpha`) | ✅ | ✅ |
152
+
153
+ CI 每天定时在 Windows、Linux、macOS 上跑完整矩阵,DSH 一发新版就能发现问题。详见 [docs/compatibility.md](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/compatibility.md)。
154
+
155
+ ## 🧠 Agent 如何选择呈现方式
156
+
157
+ <img src="https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/main/docs/assets/readme/routing.zh.svg" alt="Agent 把每次提问路由到纯文本、ui_render 或 ui_render_widget;本地交互不调用模型,显式操作才回到 Agent" width="100%">
47
158
 
48
159
  插件注入一段系统提示(`src/guidance.js`),让模型每一轮自行选择,用户无需输入任何命令:
49
160
 
@@ -54,7 +165,12 @@
54
165
 
55
166
  `/ui <需求>` 命令仍然保留,用于强制以 UI 作答。
56
167
 
57
- ## 组件目录(`ui_render`)
168
+ | 工具 | 适用场景 | 渲染方式 |
169
+ |---|---|---|
170
+ | `ui_render` | 结构化回答 | 固定目录中的原生 React 组件,随 JSON 流式渐进渲染 |
171
+ | `ui_render_widget` | 自定义可视化、三维、模拟、小应用 | 不透明源沙箱 iframe 中的 HTML/CSS/JS:先 CSS,再实时 morph HTML,最后执行 JS,全程**一个** iframe |
172
+
173
+ ## 🧩 组件目录(`ui_render`)
58
174
 
59
175
  | 类别 | 组件 |
60
176
  |---|---|
@@ -69,33 +185,31 @@
69
185
  - **`Form`**:字段类型有文本、数字、**范围滑块**、下拉、勾选、日期、多行文本。
70
186
  - **`Button` 与 `Form`**:点击或提交后,内容作为下一条用户消息发给 Agent。
71
187
 
72
- **传输与校验:** DSH 的工具 schema 不支持递归,所以界面以**扁平节点列表加 id 引用**的形式传输。Host 先校验再确认,检查项包括:
73
-
74
- - 未知类型或属性;
75
- - id 悬空、重复或成环;
76
- - 一个节点有多个父节点;
77
- - 图表数据长度不一致;
78
- - `Plot` 表达式无法编译、参数默认值越界等。
79
-
80
- 发现问题时返回 `ok:false` 并附带出错路径,模型据此修正后重试。
188
+ **传输与校验:** DSH 的工具 schema 不支持递归,所以界面以**扁平节点列表加 id 引用**的形式传输。Host 先校验再确认,检查项包括未知类型或属性;id 悬空、重复或成环;一个节点有多个父节点;图表数据长度不一致;`Plot` 表达式无法编译、参数默认值越界等。发现问题时返回 `ok:false` 并附带出错路径,模型据此修正后重试。
81
189
 
82
190
  **`Math` 与 `Mermaid` 的渲染:** 两者在与组件相同的沙箱中,从 CDN 白名单加载 KaTeX 或 Mermaid。第三方代码不在 DSH 页面中运行,宿主包体积保持在约 127 KB。CDN 不可用时,显示源码文本。
83
191
 
84
- ## 沙箱组件(`ui_render_widget`)
192
+ ## 🪟 沙箱组件(`ui_render_widget`)
193
+
194
+ <img src="https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/main/docs/assets/readme/widget-streaming.zh.svg" alt="组件字段按顺序流式到达:先显示占位,再实时 morph 预览,最后在同一个 iframe 中定稿并执行代码" width="100%">
85
195
 
86
196
  字段顺序固定:`title`、`initialHeight`、`placeholderMessages`、`css`、`html`、`jsFunctions`、`jsExpressions`。
87
197
 
88
198
  - **流式过程:**
89
199
  1. `css` 完成前,显示占位文字。
90
- 2. `css` 完成后打开预览 iframe,把清洗过的部分 HTML 实时 morph 进去。
200
+ 2. `css` 完成后打开预览 iframe,把清洗过的部分 HTML 实时 morph 进去([idiomorph](https://github.com/bigskysoftware/idiomorph))。
91
201
  3. 参数完整后,在**同一个 iframe 内原地定稿**:morph 最终 HTML,然后执行代码。iframe 不重建,没有白屏闪烁,高度也不跳动。
92
202
  - **运行时辅助(全局 `UI`):**
93
- - `UI.three(el, opts)`:返回 renderer、场景、灯光和 OrbitControls(拖动旋转,滚轮或双指缩放),按需渲染并自适应尺寸。
94
- - `UI.canvas(el, draw)`:高清 2D 画布,尺寸或主题变化时自动重绘。
95
- - `UI.state` / `UI.setState()`:持久化状态;带 `id` 的输入控件会自动保存并恢复。
96
- - `UI.color('accent')`:返回不透明的主题色,可直接用于 three.js 和 Canvas。
97
- - `UI.onTheme(cb)`、`UI.scheme`、`UI.reducedMotion`:响应主题变化与减少动效偏好。
98
- - 辅助样式类:`.ui-row`、`.ui-control`、`.ui-card`、`.ui-stage`。
203
+
204
+ | 辅助方法 | 作用 |
205
+ |---|---|
206
+ | `UI.three(el, opts)` | 返回 renderer、场景、灯光和 OrbitControls(拖动旋转,滚轮或双指缩放),按需渲染并自适应尺寸 |
207
+ | `UI.canvas(el, draw)` | 高清 2D 画布,尺寸或主题变化时自动重绘 |
208
+ | `UI.state` / `UI.setState()` | 持久化状态;带 `id` 的输入控件会自动保存并恢复 |
209
+ | `UI.color('accent')` / `UI.css()` | 不透明主题色(可直接用于 three.js 和 Canvas)/ 原始 CSS 值 |
210
+ | `UI.onTheme(cb)`、`UI.scheme`、`UI.reducedMotion` | 响应主题变化与减少动效偏好 |
211
+ | `.ui-row`、`.ui-control`、`.ui-card`、`.ui-stage` | 辅助样式类 |
212
+
99
213
  - **Bridge:**
100
214
  - `Bridge.sendPrompt({ text })`:在宿主应答前,自动禁用触发它的按钮,防止重复提交。
101
215
  - `Bridge.openLink({ url })`:打开链接。
@@ -103,7 +217,7 @@
103
217
  - **依赖库:** 通过 importmap 从 esm.sh 引入 `three`、`three/addons/…`、`d3`、`chart.js/auto`、`gsap`、`canvas-confetti`。
104
218
  - **错误恢复:** 出现脚本错误时显示错误数量,并提供“重新加载”和“让模型修复”两个按钮。后者会把错误信息发给 Agent。
105
219
 
106
- ## 显示位置与状态保持
220
+ ### 显示位置与状态保持
107
221
 
108
222
  - **显示位置:**
109
223
  - 回合进行中,UI 在工具调用处内联显示。从准备、执行到结果,始终是同一个组件实例,交互状态不会丢。
@@ -113,78 +227,63 @@
113
227
  - 已进入会话日志的调用:保留已完成的部分(组件的静态预览,或已生成的组件),并显示提示和“重新生成”按钮。
114
228
  - 参数仍在流式输出时就被停止的调用:DSH 会整体丢弃它。插件会暂存已生成的内容,同样在被停止的回合下方显示。
115
229
 
116
- ## 安全模型
117
-
118
- - **隔离:**
119
- - iframe 设置 `sandbox="allow-scripts allow-forms"` 并使用 `srcdoc`,**不加** `allow-same-origin`。
120
- - E2E 在浏览器中实测:访问 `parent.document`、`localStorage`、`cookie` 均抛出 `SecurityError`,`fetch` 被拦截,`window.origin` 为 `"null"`。
121
- - **CSP:**
122
- - `default-src 'none'`;
123
- - 脚本、样式、字体、图片只能来自 `cdnAllowlist`;
124
- - 默认 `connect-src 'none'`;
125
- - `form-action 'none'`、`base-uri 'none'`。
126
- - **消息校验:**
127
- - 宿主只接受来自该 iframe 的 `contentWindow`、带随机 token、且格式合法的消息。
128
- - 持久化的组件状态是有大小上限的 JSON。
129
- - E2E 实测,从页面或 iframe 伪造的消息都会被丢弃。
130
- - **sendPrompt 限制:**
131
- - 挂载后 1 秒内拒绝发送;
132
- - 2 秒内最多发送一次;
133
- - 长度受 `sendPromptMaxChars` 限制;
134
- - 以普通的排队用户消息发送。
135
- - **openLink:** 只允许 https,可用白名单进一步限制。
136
- - **Plot 表达式:** 由分词器和解析器编译,只能调用固定的数学函数表,无法使用 `eval`、`Function` 或访问属性。
230
+ ## 🔒 安全模型
137
231
 
138
- ## 安装
232
+ <img src="https://raw.githubusercontent.com/dreamfarer-space/deepseek-harness-intelligent-ui/main/docs/assets/readme/security.zh.svg" alt="组件运行在不透明源沙箱 iframe 中并受严格 CSP 约束;访问宿主页面会被拦截,只有通过 token 校验的 postMessage 才能到达限流的 Bridge" width="100%">
139
233
 
140
- 需要 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) **0.1.7 – 0.2.x**(`>=0.1.7-rc.1 <0.3.0`)和 Node.js ≥ 22.13,Windows、Linux、macOS 均可。安装过程不需要编译:npm 包自带预构建的浏览器端 bundle,也没有任何安装脚本。
234
+ - **隔离:** iframe 设置 `sandbox="allow-scripts allow-forms"` 并使用 `srcdoc`,**不加** `allow-same-origin`。E2E 在浏览器中实测:访问 `parent.document`、`localStorage`、`cookie` 均抛出 `SecurityError`,`fetch` 被拦截,`window.origin` 为 `"null"`。
235
+ - **CSP:** `default-src 'none'`;脚本、样式、字体、图片只能来自 `cdnAllowlist`;默认 `connect-src 'none'`;`form-action 'none'`、`base-uri 'none'`。
236
+ - **消息校验:** 宿主只接受来自该 iframe 的 `contentWindow`、带随机 token、且格式合法的消息。持久化的组件状态是有大小上限的 JSON。E2E 实测,从页面或 iframe 伪造的消息都会被丢弃。
237
+ - **sendPrompt 限制:** 挂载后 1 秒内拒绝发送;2 秒内最多发送一次;长度受 `sendPromptMaxChars` 限制;以普通的排队用户消息发送。
238
+ - **openLink:** 只允许 https,可用 `openLinkAllowedOrigins` 白名单进一步限制。
239
+ - **Plot 表达式:** 由分词器和解析器编译,只能调用固定的数学函数表,无法使用 `eval`、`Function` 或访问属性。
141
240
 
142
- ```sh
143
- dsh plugin --profile web add deepseek-harness-intelligent-ui
144
- ```
241
+ ## ⚙️ 配置
145
242
 
146
- 也可以用引导式安装器。它会先检查 Node、`dsh` 版本、pnpm 和 profile,检查通过后执行同样的 `dsh plugin add`:
243
+ 安装后 bundle patch 会自动插入 `intelligent-ui` 这一行。要修改配置,在 profile 的 `cordis.patch.yml` 中添加:
147
244
 
148
- ```sh
149
- npx deepseek-harness-intelligent-ui install # 可选 --profile <名称>、--dsh <路径>、--dry-run
150
- npx deepseek-harness-intelligent-ui doctor # 只诊断,不做修改
245
+ ```yaml
246
+ - id: intelligent-ui
247
+ config:
248
+ allowNetwork: true
249
+ cdnAllowlist: [https://esm.sh, https://cdn.jsdelivr.net]
151
250
  ```
152
251
 
153
- | 操作 | 命令 |
154
- |---|---|
155
- | 升级 | `dsh plugin --profile web add deepseek-harness-intelligent-ui@latest` |
156
- | 试用预发布版 | `dsh plugin --profile web add deepseek-harness-intelligent-ui@next` |
157
- | 固定版本 | `dsh plugin --profile web add deepseek-harness-intelligent-ui@0.2.0` |
158
- | 卸载 | `dsh plugin --profile web remove deepseek-harness-intelligent-ui`(或 `npx deepseek-harness-intelligent-ui uninstall`) |
159
- | 从源码目录安装 | `dsh plugin --profile web add file:/path/to/deepseek-harness-intelligent-ui` |
160
-
161
- 安装后需要重启 DSH Web。bundle patch 会自动插入 `intelligent-ui` 这一行。要修改配置,在 profile 的 `cordis.patch.yml` 中添加 `- id: intelligent-ui` 和对应的 `config:`,配置项见英文 README 的表格。支持的 DSH 版本和 CI 测试矩阵见 [docs/compatibility.md](docs/compatibility.md)。
162
-
163
- **常见问题**
164
-
165
- - *提示 `pnpm was not found`*:DSH 用 pnpm 安装插件。运行 `corepack enable`(Node 自带)或 `npm i -g pnpm`。
166
- - *提示 `… is incompatible with dsh X`*:当前 DSH 版本不在支持范围内。可以升级 DSH(`npm i -g @deepseek-ai/dsh@latest`),或在[兼容性文档](docs/compatibility.md)里找支持该版本的插件发行版。
167
- - *从 0.1.x 升级(以前用 `file:` 安装的 `dsh-intelligent-ui`)*:先运行 `dsh plugin --profile web remove dsh-intelligent-ui`。新旧两个包会插入同一个 `intelligent-ui` 行,`doctor` 能检测到这种冲突。
168
- - *界面没有出现*:安装后要重启 DSH Web,并确认启动的是安装插件时指定的 profile(`dsh web`)。
252
+ | 配置项 | 默认值 | 含义 |
253
+ |---|---|---|
254
+ | `enableCatalog` | `true` | 注册 `ui_render` |
255
+ | `enableWidget` | `true` | 注册 `ui_render_widget` |
256
+ | `injectGuidance` | `true` | 注入“何时使用 UI”的系统提示 |
257
+ | `cdnAllowlist` | esm.sh、jsdelivr、unpkg | 组件(以及 Math/Mermaid)可加载资源的来源 |
258
+ | `allowNetwork` | `false` | 允许组件对上述来源发起 `fetch` 和 WebSocket |
259
+ | `maxWidgetHeight` | `2400` | iframe 最大高度(px) |
260
+ | `maxWidgetBytes` | `400000` | 超过此大小的组件会被拒绝 |
261
+ | `sendPromptMaxChars` | `4000` | 组件、按钮、表单单条消息的最大长度 |
262
+ | `openLinkAllowedOrigins` | `[]` | 非空时,`openLink` 只能打开这些来源 |
169
263
 
170
- ## 开发与验证
264
+ ## 🛠 开发与验证
171
265
 
172
266
  ```sh
173
267
  npm install
174
268
  npm run build
175
- npm test # 107 个单元/组件测试(含 DSH 兼容性检查与安装器 CLI)
269
+ npm test # 单元/组件测试(含 DSH 兼容性检查与安装器 CLI)
176
270
  npm run typecheck
177
271
  npm run e2e:all # 构建 → 安装到临时 DSH 目录 → mock 模型 + 真实 DSH Web → 24 项浏览器检查
178
272
  npm run e2e:all -- --record # 同时重新录制 docs/assets/demo.mp4 / demo.gif(需要 ffmpeg)
179
273
  npm run e2e:all -- --spec ./deepseek-harness-intelligent-ui-<版本>.tgz # 改为对 npm pack 打出的包做 E2E
180
274
  npm run smoke -- --spec ./deepseek-harness-intelligent-ui-<版本>.tgz # 安装冒烟测试(不需要浏览器)
275
+ npm run docs:art # 重新生成 docs/assets/readme/ 下的 README 动画插图
181
276
  ```
182
277
 
183
- E2E 可以在 Windows、Linux、macOS 上运行。它会按平台自动查找 Chrome(可用 `CHROME_PATH` 指定),`DSH_BIN` 可指定其他 `dsh` 可执行文件。检查项见 `scripts/e2e/browser.mjs`,最近一次报告在 [`docs/e2e-report.json`](docs/e2e-report.json)。GitHub Actions 会在三个系统上,针对每个受支持的 DSH 版本跑完全部测试。
278
+ E2E 可以在 Windows、Linux、macOS 上运行。它会按平台自动查找 Chrome(可用 `CHROME_PATH` 指定),`DSH_BIN` 可指定其他 `dsh` 可执行文件。检查项见 `scripts/e2e/browser.mjs`,最近一次报告在 [`docs/e2e-report.json`](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/v0.2.1/docs/e2e-report.json)。GitHub Actions 会在三个系统上,针对每个受支持的 DSH 版本跑完全部测试。
184
279
 
185
280
  `client/client.js` 已提交到仓库并随包发布,所以 npm、`file:` 和 git 安装都不需要构建。不要添加 `prepare` 或 `postinstall` 脚本,因为 DSH 使用的 pnpm 会拦截插件的构建脚本。
186
281
 
187
- **发布流程**(维护者):
282
+ <details>
283
+ <summary><b>📦 发布流程</b>(维护者)</summary>
284
+ <br>
285
+
286
+ 发布安全与 OIDC 配置见[维护者说明](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/main/docs/releasing.md)。
188
287
 
189
288
  1. 在 [CHANGELOG.md](CHANGELOG.md) 中新增 `## [x.y.z]` 小节。
190
289
  2. 运行 `npm version x.y.z`(或 `npm version prerelease --preid rc`)。这一步会用新版本号重新构建 `client/client.js` 并打 tag。
@@ -195,11 +294,15 @@ E2E 可以在 Windows、Linux、macOS 上运行。它会按平台自动查找 Ch
195
294
  - 用 CHANGELOG 的对应小节和 tarball 创建 GitHub Release。
196
295
  4. 本地可以先运行 `npm run release:check` 做同样的预检。
197
296
 
198
- ## 真实模型评测
297
+ </details>
298
+
299
+ <details>
300
+ <summary><b>🤖 真实模型评测</b></summary>
301
+ <br>
199
302
 
200
303
  API 测试套件覆盖 15 个提示词,检查模型路由、工具参数格式,以及部分指定组件和数据。它**不会在浏览器中执行模型生成的组件**,也不验证数据事实、视觉质量、物理正确性或交互行为。独立浏览器 E2E 使用脚本化模型回复。
201
304
 
202
- 仓库保留的[历史报告](docs/real-model-eval-report.json)来自旧判分器,其中 15/15 不能作为当前通过率:B3 没有 Chart,却被判为通过。报告已标注此问题;其他用例需在新规则下重新运行,不能据此继续宣称全量通过。
305
+ 仓库保留的[历史报告](https://github.com/dreamfarer-space/deepseek-harness-intelligent-ui/blob/v0.2.1/docs/real-model-eval-report.json)来自旧判分器,其中 15/15 不能作为当前通过率:B3 没有 Chart,却被判为通过。报告已标注此问题;其他用例需在新规则下重新运行,不能据此继续宣称全量通过。
203
306
 
204
307
  新版要求组件可从根节点到达,B2 必须有可排序表格,B3 必须有四季度多系列柱状图,B4 表单必须有滑块和复选框,原生 C2 Plot 必须有参数滑块。多轮测试会校验所有工具调用并逐个回复,要求后续内容包含提交的 APAC、4 个季度和乐观情景,并核对三个型号的屏幕尺寸及原表格数据。这些自动断言不代表完整质量评估。
205
308
 
@@ -217,6 +320,8 @@ node scripts/run-real-model-suite.mjs all
217
320
 
218
321
  每次仅将本次用例写入 `docs/real-model-eval-report.json`,分类运行不混入旧结果。断言或 API 请求失败时返回退出码 1;类别错误或密钥缺失会在改写报告前退出。请勿将密钥提交到 git。
219
322
 
323
+ </details>
324
+
220
325
  ## 已知限制
221
326
 
222
327
  - 沙箱组件、`Math` 和 `Mermaid` 需要能访问 CDN 白名单。离线时,`Math` 和 `Mermaid` 退回显示源码,`UI.three` 会报告脚本错误。
package/client/client.js CHANGED
@@ -1,4 +1,4 @@
1
- /* deepseek-harness-intelligent-ui 0.2.1 — generated by scripts/build-client.mjs; do not edit. */
1
+ /* deepseek-harness-intelligent-ui 0.2.3 — generated by scripts/build-client.mjs; do not edit. */
2
2
  window.__ModuleLoader__.load({ id: "deepseek-harness-intelligent-ui", factory: (require) => {
3
3
  var module = { exports: {} }; var exports = module.exports;
4
4
  "use strict";var Re=Object.defineProperty;var Dn=Object.getOwnPropertyDescriptor;var qn=Object.getOwnPropertyNames;var Hn=Object.prototype.hasOwnProperty;var Bn=(e,t,n)=>t in e?Re(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Wn=(e,t)=>{for(var n in t)Re(e,n,{get:t[n],enumerable:!0})},Vn=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of qn(t))!Hn.call(e,i)&&i!==n&&Re(e,i,{get:()=>t[i],enumerable:!(r=Dn(t,i))||r.enumerable});return e};var Jn=e=>Vn(Re({},"__esModule",{value:!0}),e);var z=(e,t,n)=>Bn(e,typeof t!="symbol"?t+"":t,n);var Zr={};Wn(Zr,{apply:()=>Yr,inject:()=>Xr,promptSession:()=>zn});module.exports=Jn(Zr);var Ie=Object.freeze({sin:[1,Math.sin],cos:[1,Math.cos],tan:[1,Math.tan],asin:[1,Math.asin],acos:[1,Math.acos],atan:[1,Math.atan],atan2:[2,Math.atan2],sinh:[1,Math.sinh],cosh:[1,Math.cosh],tanh:[1,Math.tanh],exp:[1,Math.exp],ln:[1,Math.log],log:[1,Math.log10],log10:[1,Math.log10],log2:[1,Math.log2],sqrt:[1,Math.sqrt],cbrt:[1,Math.cbrt],abs:[1,Math.abs],sign:[1,Math.sign],floor:[1,Math.floor],ceil:[1,Math.ceil],round:[1,Math.round],min:[-1,Math.min],max:[-1,Math.max],pow:[2,Math.pow],hypot:[-1,Math.hypot]}),Lt=Object.freeze({pi:Math.PI,e:Math.E,tau:2*Math.PI}),_t=(e,t)=>Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0,Ut=500;function Kn(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(r===" "||r===" "||r===`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepseek-harness-intelligent-ui",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "DeepSeek Harness Intelligent UI: generative, interactive UI in the chat (declarative component catalog + sandboxed streaming HTML widgets), inspired by CopilotKit OpenIntelligentUI.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -28,7 +28,7 @@
28
28
  "./package.json": "./package.json"
29
29
  },
30
30
  "bin": {
31
- "deepseek-harness-intelligent-ui": "./bin/cli.mjs"
31
+ "deepseek-harness-intelligent-ui": "bin/cli.mjs"
32
32
  },
33
33
  "files": [
34
34
  "bin",
@@ -68,12 +68,13 @@
68
68
  "version": "node scripts/build-client.mjs && git add client/client.js",
69
69
  "prepublishOnly": "node scripts/build-client.mjs && git diff --exit-code -- client/client.js && vitest run",
70
70
  "release:check": "node scripts/ci/release-check.mjs",
71
- "smoke": "node scripts/ci/smoke.mjs"
71
+ "smoke": "node scripts/ci/smoke.mjs",
72
+ "docs:art": "node scripts/docs/readme-art.mjs"
72
73
  },
73
74
  "peerDependencies": {
74
75
  "@deepseek-ai/cordis": "~4.0.4 || >=4.0.5-alpha.0 <4.1.0-0",
75
- "@deepseek-ai/dsh": ">=0.1.7-rc.1 <0.3.0-0",
76
- "@deepseek-ai/dsh-llm": ">=0.1.7-rc.1 <0.3.0-0"
76
+ "@deepseek-ai/dsh": ">=0.1.7-rc.1 <0.3.0-0 || >=0.2.0-0 <0.2.0 || >=0.2.1-0 <0.2.1",
77
+ "@deepseek-ai/dsh-llm": ">=0.1.7-rc.1 <0.3.0-0 || >=0.2.0-0 <0.2.0 || >=0.2.1-0 <0.2.1"
77
78
  },
78
79
  "peerDependenciesMeta": {
79
80
  "@deepseek-ai/cordis": {
@@ -102,6 +103,7 @@
102
103
  "puppeteer-core": "25.12.0",
103
104
  "react": "19.3.0",
104
105
  "react-dom": "19.3.0",
106
+ "tar": "7.5.22",
105
107
  "typescript": "7.0.2",
106
108
  "vitest": "5.0.3"
107
109
  },
package/src/compat.js CHANGED
@@ -9,10 +9,10 @@
9
9
  */
10
10
 
11
11
  /** Range of `@deepseek-ai/dsh` / `@deepseek-ai/dsh-llm` versions the plugin runs on. */
12
- export const SUPPORTED_DSH_RANGE = '>=0.1.7-rc.1 <0.3.0-0';
12
+ export const SUPPORTED_DSH_RANGE = '>=0.1.7-rc.1 <0.3.0-0 || >=0.2.0-0 <0.2.0 || >=0.2.1-0 <0.2.1';
13
13
 
14
14
  /** Versions the CI compatibility matrix installs the packed plugin into. */
15
- export const TESTED_DSH_VERSIONS = Object.freeze(['0.1.7-rc.2', '0.2.0-rc.1', '0.2.0-rc.2', '0.2.1-alpha.2']);
15
+ export const TESTED_DSH_VERSIONS = Object.freeze(['0.1.7-rc.2', '0.2.0-rc.1', '0.2.0-rc.2', '0.2.1-alpha.2', '0.2.1-alpha.4']);
16
16
 
17
17
  /** Lowest Node.js version DSH itself requires. */
18
18
  export const MIN_NODE_VERSION = '22.13.0';