前言¶
在 DSH 里和 agent 对话时,常见做法是模型只输出 Markdown 或纯文本:计数器、小表单、简单计算器这类东西,要么靠用户自己复制 HTML 到浏览器里试,要么再写一层前端才能点按。DeepSeek Harness 的插件体系允许在客户端扩展对话 UI;dsh-generative-ui(维护者 ttmouse,GitHub 仓库 ttmouse/dsh-generative-ui)做的是:让 agent 在单轮回复里用约定好的围栏写出自包含 HTML,客户端从消息里抽出这些「工件」,在消息下方用沙箱 iframe 渲染成可交互卡片。实现是纯客户端,无后端、无额外存储,工件就活在会话消息文本里。
下面介绍它是什么、怎么装、agent 该怎么写围栏,以及布局与安全上的约束。
这是什么¶
dsh-generative-ui 是 DSH 的客户端插件(npm 包名 @ttmouse/dsh-generative-ui,当前版本 0.2.2,许可证 MIT)。它解决的是:在对话流中直接展示可交互的 Generative UI,而不是只展示静态说明。
运行环境要求(来自 package.json):DSH >=0.1.5-rc.2。
架构上分两半(README Design 节):
- Host 半:通过
systemPrompt.section把「用generative-ui围栏写工件」的约定广播给各 agent。 - 浏览器半:用
uiConversation.events累加器从assistant/message事件里提取工件(与 dsh-taskboard 同类的 turn-accumulator),挂到该轮消息位置,经conversation.chat.turnTail插槽渲染卡片。
状态不另存:工件在 session 消息里,会话在就在;没有第二份状态要同步。
核心功能¶
围栏约定与渲染¶
Agent 在回复里写围栏代码块,语言标记为 generative-ui,内容为自包含 HTML(可含内联 <script>)。插件从该轮回答中提取所有此类块,每条渲染为消息下方一张卡片。
文档中的最小示例(计数器):
```generative-ui
<!-- title: Example: counter -->
<button id="plus">+1</button> <span id="n">0</span>
<script>let n=0;plus.onclick=()=>{n++;n.textContent=n}</script>
```
README 截图说明同一对话里可以并排出现多张卡片(例如计数器与 BMI 计算器)。
沙箱 iframe¶
每张卡片对应一个裸 iframe 文档,使用:
<iframe sandbox="allow-scripts">
即允许脚本、无 same-origin:工件可交互,但不能访问宿主页面、cookies 或 localStorage。
自适应高度¶
每个工件内注入 bootstrap:通过 ResizeObserver 与 postMessage 向父页报告高度;卡片高度限制在 120–600px,超出部分在卡片内滚动。
运行时设计系统¶
工件是裸 iframe 文档,没有默认字体与间距重置。插件在 <head> 内联 DESIGN_SYSTEM_CSS,在运行时约束生成结果,而不是只在 prompt 里口头要求。要点包括:
- 用
--gui-surface-1/2/3等表面层级区分区域,而非依赖边框。 - 三种字号:
--gui-fs-title(18)、--gui-fs-body(14)、--gui-fs-caption(12)。 - 间距与圆角 token:
--gui-gap(12)、--gui-pad(16)、--gui-radius(12) 等;提供.gui-stack、.gui-card、.gui-chip等工具类。 - 按钮具备主样式、焦点环、约 44px 触控高度;动效优先
transform/opacity,并考虑prefers-reduced-motion。
同一套规则会以文本形式进入 GENERATIVE_UI_GUIDANCE,供模型参考。
源码审计(不阻断渲染)¶
auditArtifactSource(source) 可报告违规项(如 border、shadow、gradient、blur、body-spacing、comment、em-dash、buzzword、pure-color 等),不会因此阻止渲染。
安装与启用¶
官方 README 安装步骤如下。注意命令里是 link:<this-directory>,表示对本机插件目录做 link 安装,不是凭仓库名拼 github:owner/repo。
dsh plugin --profile desktop add link:<this-directory>
随后在 profile 的 package.json 里把 @ttmouse/dsh-generative-ui 加入 dsh.profile.bundles,并重启 Desktop 应用(host 半注册 system prompt 段;client.js 按请求从磁盘读取)。
客户端脚本改动刷新页面即可生效;host 半(system prompt 文案)改动需重启应用。
若你要改插件本身,仓库内开发流程为:
npm install && npm run build # 产出 lib/client.js + lib/index.mjs
npm test # unit + e2e(headless Chromium)
npm run screenshot # 从真实 client 重新生成 screenshot.png
典型用法¶
- 按上一节完成 link 安装、bundles 配置与 Desktop 重启。
- 在对话中让 agent 按约定输出
generative-ui围栏;可选 HTML 注释<!-- title: ... -->作为卡片标题。 - 发送后,在该条 assistant 消息尾部查看渲染出的交互卡片,在 iframe 沙箱内操作。
围栏内容应是自包含的 HTML(样式与脚本可内联);复杂 UI 应优先使用插件注入的设计系统 token 与 utility 类,以减少与 auditArtifactSource 冲突的写法。
适用场景与注意¶
适合谁
- 需要在 DSH 对话里快速验证小工具、表单、可视化原型,又不想单独开前端工程的开发者。
- 希望 agent 输出「能点能算」的 UI,且接受状态只存在于当前会话消息中的场景。
安全与信任
- 插件以当前 DSH 进程及浏览器环境的权限运行;安装前应阅读 GitHub 源码 与 MIT 许可证,确认符合你的安全策略。
- 沙箱限制的是 iframe 对宿主页面的访问;围栏内脚本仍在 iframe 内执行,勿让不可信模型输出未审查的可执行内容。
生态说明
DSH 强调「一切皆插件」;社区目录 SkillHub 上的 dsh-generative-ui 页 是独立站点,与 DeepSeek / 幻方无官方从属关系。
结尾¶
dsh-generative-ui 把 Generative UI 收成一条可复现约定:generative-ui 围栏 + 客户端提取 + 沙箱卡片渲染,纯客户端、零后端。若要查阅分类与简介,可看目录页 skillhub.cn/plugins/ttmouse/dsh-generative-ui;细节与示例以 GitHub README 为准。