DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

MCJF28 /

MCJF28/dsh-visual-card

Verified

Renders AI-generated HTML as interactive cards inside DeepSeek Harness conversations: playable demos, full-screen, copy and download.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@de8257c6

dsh-visual-card

中文 | English

可视化回答插件:AI 交一段 HTML,在对话里渲染成一个可交互的窗口——能点、能用键盘操作、能全屏、能导出。

效果

工具调用后,本轮回答下方出现一个窗口:

  • 顶部工具条:标题 + 全屏 / 复制 / 下载
  • 内容区是 AI 写的 HTML,脚本会真正执行(按钮、canvas、动画都能跑)
  • 颜色自动跟随当前亮/暗主题

能做什么

  • 图表、色板、布局示意
  • 可点击的演示(切换状态、翻页、展开细节)
  • 完整的小游戏(WASD 移动、canvas 逐帧动画)
  • 需要键盘操作时,点进窗口才接管键盘,窗口外按键照常进输入框

键盘规则

操作 行为
点进窗口 窗口接管键盘,标题栏提示「键盘已交给窗口」
按 Esc 释放键盘,回到输入框
点窗口外 自动释放
鼠标 始终正常(悬停、滚动、点击都不用先聚焦)

实现上用了 iframe:AI 生成的脚本通常监听 document 的键盘事件,如果和宿主共用同一个文档,窗口外按键也会触发它。iframe 有独立的事件作用域,焦点不在里面就收不到键。

工具

render_visual({
  title: '标题',
  html: '<div>...</div>',
  // height 可选:不给就按内容自动定高(推荐)
})

高度是自动的:宽度固定后,内容多高卡片就多高,不套固定框。内容超过设置的比例上限时,改为卡片内部滚动 —— 再大的卡片也不会逼你滚动整个对话才能看全貌。

写 HTML 时用主题变量,不要写死颜色:

--v-bg-base、--v-bg-layer-1/2、--v-border、--v-text、--v-text-dim、--v-brand、--v-success/warn/error

设置

设置 → 可视化:

项 作用
高度上限 卡片高度按内容自动决定;超过这个比例(40–100% 视口高)就改成卡片内部滚动,不逼你滚动整个对话才能看全貌
允许执行脚本 关掉后按钮、动画、小游戏都不运行,只显示静态内容。脚本运行在宿主页面里,这是唯一的安全风险来源
每个会话保留轮数 超出的旧轮次在写入时丢弃(10–2000)
每轮最多卡片数 一轮里超过这个数量只留最新的(1–50)
清空历史 清掉 cards.json,带二次确认

改动即时保存到 ~/.dsh/visual/settings.json。

存储

卡片按「会话 + 轮次」落盘到 ~/.dsh/visual/cards.json,重启后仍在。保留轮数与每轮上限由设置决定。

删掉这个目录只会丢失历史可视化,不影响功能。

安装

推荐:内置插件安装程序。 打开「设置 → 内置插件」,粘贴包名,点安装,再重启应用:

dsh-visual-card

安装程序会自动写进 dsh.profile.bundles,不用手改任何文件。

命令行方式(先完全退出应用):

cd ~/.dsh/profiles/desktop
pnpm add dsh-visual-card

然后把包名加进 dsh.profile.bundles,重启应用。

安全说明

AI 生成的脚本运行在宿主页面里,不是沙箱。这是「能点击、能跑小游戏」的必然代价。

插件只约束「不引用外部资源」,不做代码审查。自己用没问题;如果要在不信任 AI 输出的场景里用,请先自行加沙箱。

已知限制

  • 卡片固定渲染在本轮回答下方,不能插入正文中间——宿主的对话节点是固定 19 种,插件无法新增节点类型
  • turnTail 槽位只在本轮结束后渲染,所以流式输出期间看不到卡片

English | 中文

Visual answers for DeepSeek Harness: the model hands over a block of HTML and it renders as an interactive window inside the conversation — clickable, keyboard-operable, fullscreen-capable, exportable.

What it looks like

After the tool call, a window appears below the turn's answer:

  • Toolbar: title plus Fullscreen / Copy / Download
  • The content area is the model's HTML, and its scripts really run (buttons, canvas, animation all work)
  • Colors follow the active light/dark theme automatically

What you can build

  • Charts, color swatches, layout sketches
  • Clickable demos (state toggles, paging, expanding detail)
  • Complete small games (WASD movement, per-frame canvas animation)
  • When a demo needs the keyboard, clicking into the window takes it over; keys outside keep going to the composer

Keyboard rules

Action Behavior
Click into the window The window takes the keyboard; the title bar says so
Press Esc Release the keyboard, back to the composer
Click outside Released automatically
Mouse Always works — hover, scroll and click need no focus first

The implementation uses an iframe. Scripts generated by the model typically listen for keydown on document; if they shared the host document, keys pressed anywhere would reach them. An iframe has its own event scope, so it only receives keys while focus is inside.

Tool

render_visual({
  title: 'Title',
  html: '<div>...</div>',
  // height is optional; omit it and the card sizes itself to its content (recommended)
})

Height is automatic: once the width is fixed, the card is as tall as its content — no fixed frame. When the content exceeds the configured cap, the card scrolls internally, so even a large card never forces you to scroll the whole conversation.

Use theme variables instead of hard-coded colors:

--v-bg-base, --v-bg-layer-1/2, --v-border, --v-text, --v-text-dim, --v-brand, --v-success/warn/error

Settings

Settings → Visual:

Item Effect
Height cap Card height follows its content; above this share of the viewport (40–100%) the card scrolls internally instead of forcing a page scroll
Allow scripts When off, buttons, animation and games do not run — only static content renders. Scripts run inside the host page, which is the only source of risk here
Turns kept per conversation Older turns are dropped on write (10–2000)
Max cards per turn Beyond this many in one turn only the newest are kept (1–50)
Clear history Deletes cards.json, behind a second confirmation

Changes save immediately to ~/.dsh/visual/settings.json.

Storage

Cards are persisted per conversation and turn to ~/.dsh/visual/cards.json, so they survive a restart. Retention is governed by the settings above.

Deleting the directory only loses visual history; functionality is unaffected.

Install

The built-in plugin installer is the recommended way. Open Settings → Built-in Plugins, paste the package name, press install, then restart the app:

dsh-visual-card

The installer writes the entry into dsh.profile.bundles for you; no manual file edits.

From the command line (quit the app completely first):

cd ~/.dsh/profiles/desktop
pnpm add dsh-visual-card

Add the package name to dsh.profile.bundles and restart the app.

Security

Scripts generated by the model run inside the host page — this is not a sandbox. That is the unavoidable cost of "clickable, can run games".

The plugin only enforces "no external resources" and performs no code review. Fine for personal use; if you point it at model output you do not trust, add a sandbox first.

Known limits

  • Cards always render below the turn's answer and cannot be placed mid-text: the host supports a fixed set of 19 conversation node kinds, and a plugin cannot add one
  • The turnTail slot only renders after the turn closes, so nothing appears while the answer is still streaming
—/ 5

No ratings yet

Verified DSH bundle

Commit de8257c600c7

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout