dsh-html-live-preview
Verifieddsh-html-live-preview · v1.0.0 · MIT · Web UI
Live HTML preview inside DeepSeek Harness conversations: a render_html tool plus an inline, sandboxed, auto-sized renderer.
Install
dsh plugin add dsh-html-live-preview Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
dsh-html-live-preview · HTML 实时预览插件
在 DeepSeek Harness 会话里边写边渲染 HTML: 模型调用一个工具,HTML 就随生成过程直接画在对话里——不是代码块,也不是侧边栏。

它能做什么
- 边写边画:模型还在写参数时,预览就开始长出来(容错解析半截 JSON,不必等调用结束)。
- 写完能交互:
<script>在参数写完后按文档顺序执行一次,按钮、动画、图表、canvas 都能跑。 - 不会被折叠掉:回合结束后 DSH 会把工具行收进"过程"折叠区,所以本插件在回合尾部再渲染一份 (该槽位不参与折叠)。同一时刻每个调用只有一个 iframe。
- 跟随主题:帧内继承宿主的
--dsw-*/--dsh-*变量,另加一组易读别名,亮/暗切换即时生效。 - 报错说人话:帧内脚本异常、子资源加载失败会在卡片下方显示可关闭的提示条;记录被窗口截断、 无法重建时也会明确说明,而不是给一张空白框。
环境要求
- DeepSeek Harness 的 web profile(
dsh web),已在0.1.7-rc.2上验证。 - 插件把
@deepseek-ai/dsh-tools声明为 peer:版本范围之外 DSH 会拒绝加载并说明原因, 而不是等到第一次调用才炸。
安装
用装着 Web UI 的那个 profile 安装:
dsh plugin --profile web add dsh-html-live-preview
Web UI 的 插件页面里有同样的操作。安装会自动把 bundle 选中,下一轮组合即挂载(HMR 实时生效)。
从本仓库源码安装(改完代码即生效):
dsh plugin --profile web add link:/绝对路径/dsh-html-live-preview
装完请开一个新会话:已存在的会话保持它启动时的工具目录,所以工具会出现在下一个会话里。
render_html 注册在 tools 注册表的全局层,profile 里每个 agent(含子 agent)都能调用,不需要改预设。
用法
随便怎么说,只要结果是"看得见的东西":
"画一个这周延迟的柱状图" "做个登录页的界面稿,按钮点一下要有反应" "演示快排是怎么分区的"
模型会调用 render_html({ html, title?, height? })。卡片悬停时出现四个控件:
看 HTML 源码、复制、重跑脚本、展开高度(默认上限 620px,免得一张预览吃掉整屏)。
工作机制
宿主半边(index.js)只做校验与记账:限制 256 KiB、返回几 token 的回执。
HTML 本体留在会话日志的 tool/call 参数里,所以重开会话/回放照样能渲染,既不额外占存储也不占上下文。
浏览器半边(client.js)是 DSH 客户端模块工厂形式的普通 classic script——
不需要构建,除平台内置的 react 外不 import 任何东西:
| 渲染位置 | 时机 | 原因 |
|---|---|---|
tool.call.toolview |
回合进行中 | 从半截参数流式渲染 |
conversation.chat.turnTail |
回合结束后 | 尾部不在折叠区内,预览得以常驻 |
帧本身的关键设计:
- 常量 receiver 文档:iframe 的
srcdoc永远是一份固定外壳(CSP + 主题变量 + 测量脚本), 模型写的 HTML 只通过postMessage注入,因此流式更新不会重载/闪烁。 - 两阶段注入:流式阶段剥掉
<script>与on*(innerHTML插入的<script>不会执行, 但<img onerror>会);落地后注入完整 HTML 并按序执行一次脚本(外链脚本等load再继续)。 - 沙箱:
sandbox="allow-scripts",不含allow-same-origin(opaque origin)。帧内 CSP 为default-src 'none'、connect-src 'none'(无 fetch/XHR/WebSocket)、frame-src/object-src 'none'、base-uri/form-action 'none'; 放行内联脚本、4 个 CDN(jsdelivr / unpkg / cdnjs / esm.sh)与data:/https:图片字体。 链接转发给宿主,校验协议后用外部浏览器打开。 - 自动高度:帧内
ResizeObserver回传内容高度(60ms 去抖),卡片夹在内容与上限之间、 按 callId 缓存(重挂载不会塌成 0);超出上限的部分保留自己的滚动条,可展开到 2400px。
验证情况
真实 GUI + 真实模型调用(截图见 screenshots/):工具行渲染出卡片; 回合结束后预览常驻在回复下方;高度由帧内测量回传(490px / 260px);控制台无报错、无 slot 崩溃。
组件级回归夹具 test/harness.html:用假 window.__ModuleLoader__ + 真 React
直接渲染本插件组件,不需要 DSH、不消耗模型额度,覆盖流式解析、落地执行、清洗、高度上限、
展开、源码视图、主题切换、帧内报错:
mkdir -p /tmp/hp && cd /tmp/hp
cp /path/to/dsh-html-live-preview/client.js .
cp /path/to/dsh-html-live-preview/test/harness.html .
curl -sO https://unpkg.com/[email protected]/umd/react.development.js
curl -sO https://unpkg.com/[email protected]/umd/react-dom.development.js
open harness.html
已知限制
- 不支持 ```html 围栏自动渲染:DSH 目前没有任何"自定义 fence 渲染"扩展点
(
ui-primitives里的renderCode是硬编码的),只能走工具调用。这是上游插槽缺口。 - DSH 升级:声明范围是
^0.1.7-rc.2,范围之外 DSH 会停用本插件并给出原因,不会运行时崩; 放宽范围是改一行 + 重新验证。 - 帧内不能联网(设计如此):需要数据的可视化要把数据内联,或用允许的 CDN 加载库。
- 会话窗口截断:如果记录的调用落在已加载窗口之外,卡片会说明无法重建预览。
- 改插件自身代码需要重启:DSH 只热重载 profile 清单与补丁,客户端 bundle 与宿主模块按进程缓存。