让 DSH 模型在对话里直接渲染可交互卡片,把图表、模拟器、对比面板和 UI mockup 做成 HTML 片段展示。
- 语言
- TypeScript
- License
- BSD-3-Clause
- 分支
- main
安装
$ dsh plugin --profile web add github:Nagi-ovo/dsh-visualize在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
对话式安装
帮我安装 DeepSeek Harness 插件 Nagi-ovo/dsh-visualize:先查看仓库 https://github.com/Nagi-ovo/dsh-visualize.git 确认安全性,然后执行安装命令并验证插件加载成功。
把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。
一句话定位
让 DSH 模型的回复从纯文字升级为对话内可交互的可视化卡片。模型把一段 HTML 片段直接作为参数传给 visualize 工具,宿主 Web UI 就在回复里渲染出一张可点、可调、可拖的卡片,用来展示图表、模拟器、对比面板和 UI 草图。
核心能力
- 注册
visualize工具:模型把整段内嵌 HTML(标记 + 样式 + 脚本)作为fragment参数传入,宿主直接渲染成对话内的卡片,无需生成中间文件 - 配套
visualizeskill:模型第一次调用前自动加载片段撰写规范,定义片段结构、主题变量、字节上限、可加载的 CDN 白名单 - 支持
action: "create"与action: "update"两种动作:create 渲染新卡片,update 对已渲染卡片做精确的 old_str→new_str 局部替换,少量修改时比重新渲染更省 - 流式预览:模型生成过程中,对话输入区下方实时显示半成品卡片,已写完的脚本即时执行;调用结束后预览自动消失,常规对话卡片接管
- 沙箱化渲染:每张卡片跑在不透明来源的
<iframe sandbox="allow-scripts">中,自带 CSP,阻止外联请求、嵌套页面和表单提交;外部静态资源只允许从白名单 CDN 加载 - 跟随宿主主题:卡片读取 DSH 的鲸鱼蓝等设计变量并注入到 frame 内,明暗主题切换、操作系统外观变化时实时重渲染
技术实现
- 语言: TypeScript(含 .tsx 浏览器侧组件)
- 关键依赖:
@deepseek-ai/cordis(注入宿主)、@deepseek-ai/dsh-tools(注册 visualize 工具)、@deepseek-ai/dsh-skill(注册可视化 skill provider)、@deepseek-ai/dsh-client-runtime与@deepseek-ai/dsh-client-ui-tool(浏览器侧运行时) - 架构模式: 插件拆为「服务端半 + 浏览器半」两份。服务端半通过 Cordis 注入
tools/skills/fs三个宿主服务,注册可视化工具和内嵌 skill;浏览器半注入slots,在tool.call.toolview上注册 key 为visualize的卡片组件,并在conversation.input.dock上挂载流式预览组件。TUI/headless 客户端没注册浏览器半时,会按文档约定的渲染意图降级为工具结果的纯文本 - 入口文件:
src/index.ts(服务端 Cordis 插件入口)→src/tool.ts(可视化工具定义)→src/skill.ts(可视化 skill provider)→src/client/index.tsx(浏览器侧 slot 注册)→src/client/VisualizeCard.tsx与src/client/StreamingPreview.tsx(React 组件)
适用场景
在对话里需要展示一份带交互的图表、可拖滑块调参数的模拟器、几个版本并排对比的方案或一张产品页 mockup,又不想跳出 DSH 打开外部 BI/绘图工具时使用。最适合"用户问一句、模型回一张能动手的卡片"的场景;纯静态的关系图直接用 Mermaid 围栏更省事。
前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH(cordis / dsh-tools / dsh-skill / dsh-fs / dsh-llm / dsh-sandbox-policy / dsh-session) | ^0.1.0-rc.6 | 插件通过 Cordis 注入 tools/skills/fs 三个宿主服务;peerDependencies 全为 ^0.1.0-rc.6 |
| 浏览器侧运行时(@deepseek-ai/dsh-client-runtime / dsh-client-ui-tool / dsh-client-ui-conversation) | ^0.1.0-rc.6 | 仅 Web UI 需要;缺时 TUI/headless 自动降级为工具结果文本 |
| React | ^18.2.0 | 浏览器侧组件框架;由宿主注入 |
| Node.js | 未声明 | package.json 未声明 engines 字段;DSH 0.1.0-rc.6 宿主已自带所需运行时 |
| 平台 | 跨平台 | 无 os/cpu 限制;卡片渲染在浏览器侧完成 |
安装方式
dsh plugin --profile web add github:Nagi-ovo/dsh-visualize
配置项
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
maxFragmentBytes | 整数(自然数) | 单张卡片允许的最大字节数(含 markup/style/script)。超出时工具直接拒绝并提示精简内联数据。 | 1000000(约 1 MB) |
常见问题
Q: 安装后模型仍只用文字回复,怎么让模型调用 visualize?
A: 模型需要在会话内加载 visualize skill 才会写出片段。如果新会话不触发,重启一次 dsh web 让 skill 注册生效;或在提问时直接说"用 visualize 卡片画一个 XX"。
Q: 工具提示 fragment contains a document-skeleton tag,怎么修?
A: 片段里不要再写 <!doctype>、<html>、<head>、<body> 这些外层标签,宿主卡片会自己提供文档骨架、样式和主题,片段只写正文结构即可。
Q: 卡片里 fetch、XHR、WebSocket 为什么没反应?
A: 卡片跑在不透明来源的沙箱 iframe 里,CSP 禁止 connect-src 外联,只能从白名单 CDN 加载静态资源(如 Chart.js、D3)。需要联网取数据时,模型应把数据直接写进 fragment。
Q: 卡片里的按钮按下去没反应,怎么回传到对话?
A: 当前版本暂未支持卡片内按钮向主对话发送 follow-up 消息,需要让模型重画时只能让模型再调一次 visualize。要点"应用"等按钮请直接告诉模型。
Q: 局部修改用 update 还是重新 create?
A: 修改范围在 20 行内、5 处以内、每回复不超过 4 次时用 action: "update" 做 old_str→new_str 替换,效率更高。结构性改动或较大修订重新 create 一张卡片更稳。每次 update 都会重载卡片,滑块输入等控件状态会回到初始值。
Q: TUI 和无头客户端为什么显示不出来?
A: 交互卡片目前只在 Web UI 渲染;TUI 和 headless 客户端只会看到一段确认文字 "Rendered ... (X bytes; workspace copy at ...)",片段文件依然存在,需要在浏览器里打开 dsh web 才能看到卡片。
Q: 单张卡片最大能多大?
A: 默认单 fragment 上限 1,000,000 字节(约 1 MB),可在 dsh profile 配置中通过 maxFragmentBytes 调大或调小。超出时会直接报错,并提示减少行数、降低精度。
Q: 怎么完全卸载?
A: dsh plugin --profile web remove github:Nagi-ovo/dsh-visualize,重启 dsh web。已渲染过的会话中卡片会回退为普通工具结果文字。
上手难度
入门 — 普通用户无需任何配置;模型侧的语法通过内置 skill 自动学习,用户只需在 prompt 中描述想要的可视化内容即可。开发者要二次开发需熟悉 Cordis 插件协议、DSH 工具/skill 注册流程与 React。
已知问题与限制
- 仅 Web UI 渲染交互卡片:TUI 和 headless 客户端没有浏览器半,会降级为工具结果纯文本(
README.md:44) - 卡片内按钮暂不能向主对话发 follow-up 消息(
README.md:44) - 卡片高度有上限:inline 模式 800px,wide 模式 1200px,超出后内部滚动(
src/client/VisualizeCard.tsx:27) update操作有频率与范围限制:每回复最多 4 次、每次改动少于 20 行 / 5 处;超出建议重新 create(assets/visualize-skill.md:51-53)- 卡片每次更新会重新加载,滑块、输入框等控件的临时状态会回到初始值(
assets/visualize-skill.md:63) - 外部静态资源仅允许从固定白名单 CDN 加载:cdnjs.cloudflare.com、cdn.jsdelivr.net、esm.sh、unpkg.com、fonts.bunny.net、fonts.googleapis.com、fonts.gstatic.com(
src/shell.ts:20-28) - 模型写片段时不得自带文档骨架标签(
<!doctype>/<html>/<head>/<body>),否则工具直接报错(src/fragment.ts:55-74) - 片段字节数上限默认 1 MB,需在大数据场景下调高
maxFragmentBytes配置(src/index.ts:36-38)

简体中文 | English
让 DSH 不只回答一段文字。模型调用 visualize 后,Web UI 会在对话里直接出现一张可交互卡片,用来做模拟器、图表、对比面板或 UI mockup。
安装
推荐直接从 GitHub 安装到 DSH 的 web profile:
dsh plugin --profile web add github:Nagi-ovo/dsh-visualize
# 如果 dsh web 正在运行,重启后刷新页面
可以运行 dsh --profile web --dump-config 确认插件已经进入最终配置。需要修改源码时,克隆仓库并在仓库目录运行 dsh plugin --profile web add .;构建产物已经提交,不需要额外构建。使用社区 plugin-registry 的用户也可以从「设置 → 插件」安装。
怎么用
直接告诉模型你想看什么,例如「做一个能调参数的排序算法可视化」。模型会写出一份 HTML fragment,再调用 visualize(path, title?, mode?) 把它放进对话。适合并排比较的内容可以使用 mode: "wide"。
卡片会跟随 DSH 的明暗主题和鲸鱼蓝配色。会话重放时,页面从持久化的工具结果恢复,不依赖原始 fragment 文件仍然存在。
安全
卡片运行在不透明来源的 sandboxed iframe 中,不能接触宿主页面。CSP 会阻止网络请求、嵌套页面和表单提交,只允许从固定 CDN 加载静态资源。单个 fragment 默认上限为 1000000 字节,可以通过 maxFragmentBytes 调整。
限制
目前只在 Web UI 中渲染交互卡片,TUI 和 headless 客户端会显示普通工具结果。卡片内的按钮暂时不能向主对话发送 follow-up 消息。
灵感来自 Codex 桌面端的 /visualize;skill 的分层 reference 和 Chart.js 优先路线借鉴了 himself65/finance-skills。
收录徽章
[](https://deepseek-plugin.org/plugins/Nagi-ovo/dsh-visualize)把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。
