dsh-generative-ui:在 DSH 对话流里渲染可交互 Generative UI

前言

在 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

典型用法

  1. 按上一节完成 link 安装、bundles 配置与 Desktop 重启。
  2. 在对话中让 agent 按约定输出 generative-ui 围栏;可选 HTML 注释 <!-- title: ... --> 作为卡片标题。
  3. 发送后,在该条 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 为准。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜