Render interactive cards directly in DSH model conversations, displaying charts, simulators, comparison panels, and UI mockups as HTML snippets.
$ dsh plugin --profile web add github:Nagi-ovo/dsh-visualizeRun the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial
Upgrades DSH model responses from plain text to interactive visualization cards within conversations. The model passes an HTML fragment directly as a parameter to the visualize tool, and the host Web UI renders a clickable, adjustable, draggable card in the response to display charts, simulators, comparison panels, and UI mockups.
visualize tool: The model passes an entire embedded HTML fragment (markup + styles + scripts) as the fragment parameter, and the host renders it directly as an in-conversation card without generating intermediate filesvisualize skill: Automatically loads fragment authoring specifications before the model's first call, defining fragment structure, theme variables, byte limits, and allowed CDN whitelistaction: "create" and action: "update": create renders a new card; update performs precise old_str→new_str partial replacement on already-rendered cards, more efficient for small modifications<iframe sandbox="allow-scripts"> with built-in CSP, blocking external requests, nested pages, and form submissions; external static resources can only load from whitelisted CDNs@deepseek-ai/cordis (host injection), @deepseek-ai/dsh-tools (register visualize tool), @deepseek-ai/dsh-skill (register visualization skill provider), @deepseek-ai/dsh-client-runtime and @deepseek-ai/dsh-client-ui-tool (browser-side runtime)tools, skills, fs to register visualization tool and embedded skill; browser-side half injects slots, registers card component with key visualize on tool.call.toolview, and mounts streaming preview component on conversation.input.dock. TUI/headless clients without browser-side registration fallback to plain text tool results per documentation conventionssrc/index.ts (server-side Cordis plugin entry) → src/tool.ts (visualize tool definition) → src/skill.ts (visualize skill provider) → src/client/index.tsx (browser-side slot registration) → src/client/VisualizeCard.tsx and src/client/StreamingPreview.tsx (React components)Use when you need to display an interactive chart in conversation, a simulator with sliders for parameter adjustment, side-by-side comparison of multiple versions, or a product page mockup, without leaving DSH to open external BI/drawing tools. Best suited for "user asks one question, model replies with one actionable card" scenarios; purely static relational diagrams are more efficiently done with Mermaid fences.
| Dependency | Minimum Version | Description |
|---|---|---|
| DSH (cordis / dsh-tools / dsh-skill / dsh-fs / dsh-llm / dsh-sandbox-policy / dsh-session) | ^0.1.0-rc.6 | Plugin injects three host services via Cordis: tools/skills/fs; all peerDependencies are ^0.1.0-rc.6 |
| Browser-side runtime (@deepseek-ai/dsh-client-runtime / dsh-client-ui-tool / dsh-client-ui-conversation) | ^0.1.0-rc.6 | Only required for Web UI; TUI/headless auto-fallback to tool result text when missing |
| React | ^18.2.0 | Browser-side component framework; injected by host |
| Node.js | Not declared | package.json does not declare engines field; DSH 0.1.0-rc.6 host includes required runtime |
| Platform | Cross-platform | No os/cpu restrictions; card rendering happens on browser side |
dsh plugin --profile web add github:Nagi-ovo/dsh-visualize
| Config | Type | Description | Default |
|---|---|---|---|
maxFragmentBytes | Integer (natural number) | Maximum bytes allowed per card (including markup/style/script). Tool rejects and prompts to trim inline data when exceeded. | 1000000 (~1 MB) |
Q: Model still replies with text after installation, how to make model call visualize?
A: Model needs to load the visualize skill in the session to write fragments. If it doesn't trigger in a new session, restart dsh web once to let skill registration take effect; or directly say "use visualize card to draw XX" in your question.
Q: Tool prompts "fragment contains a document-skeleton tag", how to fix?
A: Don't write outer tags like <!doctype>, <html>, <head>, <body> in fragments; the host card provides its own document skeleton, styles, and theme—fragments should only contain body structure.
Q: fetch, XHR, WebSocket in card not responding?
A: Cards run in a sandboxed iframe with opaque origin; CSP prohibits connect-src external connections, only allowing static resources from whitelisted CDNs (like Chart.js, D3). When needing to fetch data, model should write data directly into fragment.
Q: Buttons in card don't respond, how to send messages back to conversation?
A: Current version doesn't support card buttons sending follow-up messages to main conversation; when needing to redraw, model must call visualize again. For "Apply" and similar buttons, tell the model directly.
Q: Use update or recreate for partial modifications?
A: Use action: "update" for old_str→new_str replacement when modifications are within 20 lines, 5 places, and no more than 4 responses—more efficient. Structural changes or larger revisions should recreate a card. Each update reloads the card, resetting slider inputs and other control states to initial values.
Q: Why don't TUI and headless clients display?
A: Interactive cards currently only render in Web UI; TUI and headless clients only see a confirmation text "Rendered ... (X bytes; workspace copy at ...)", fragment files still exist, need to open dsh web in browser to see cards.
Q: What's the maximum size for a single card?
A: Default single fragment limit is 1,000,000 bytes (~1 MB), adjustable via maxFragmentBytes in dsh profile config. Exceeding triggers direct error with prompts to reduce lines or lower precision.
Q: How to completely uninstall?
A: dsh plugin --profile web remove github:Nagi-ovo/dsh-visualize, restart dsh web. Cards in already-rendered sessions will revert to plain tool result text.
Beginner — No configuration needed for regular users; model-side syntax is automatically learned via built-in skill; users only need to describe desired visualization content in prompts. Developers need familiarity with Cordis plugin protocol, DSH tool/skill registration flow, and React for secondary development.
README.md:44)README.md:44)src/client/VisualizeCard.tsx:27)update operation has frequency and scope limits: max 4 times per response, each modification under 20 lines / 5 places; recommend recreate when exceeded (assets/visualize-skill.md:51-53)assets/visualize-skill.md:63)src/shell.ts:20-28)<!doctype> / <html> / <head> / <body>), otherwise tool errors directly (src/fragment.ts:55-74)maxFragmentBytes config for large data scenarios (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。