condaThinker
dsh-image-inline
DSH plugin: show_image tool that renders an image inline into the web chat flow (QQ/WeChat style) — path text in the message, image bytes never enter model context.
- Stars
- 1
- Language
- JavaScript
- Created
- Aug 14, 2026
- Updated
- Aug 14, 2026
Introduction
dsh-image-inline
让 DeepSeek Harness (DSH) 的 Web UI 支持模型主动把一张图片渲染进对话流(QQ/微信聊天式:图片显示在会话里、可上翻、和对话同步)。
对话流消息内容里只保留路径文本,图片本身不进入模型上下文(模型上下文保持干净,纯文本模型路由不受影响)。
工作方式
模型调用新增的 show_image 工具(传入磁盘图片路径)时:
- host(
dsh/index.js):校验路径/格式/大小 → 读取字节 → 通过附件服务saveImage存成内容寻址附件 → 返回纯文本结果(路径 + 元数据摘要)。图片的展示载荷(attachmentId/宽高/字节数)通过工具的presentationMeta放进tool/result事件的meta字段——不进模型上下文、不进会话日志的 image 块。 - client(
dsh/client.js):注册tool.call.toolview键控槽位(key =show_image),在对话流中该工具调用的位置渲染图片卡片(复用官方MessageImage组件:缩略图、点击看原图、加载失败可重试)。图片 URL 走插件自己的内容寻址 HTTP 端点。
模型 → show_image(path) → 附件服务存图 → 纯文本结果(路径+摘要)
│
├─ tool/result meta ─→ client toolview 渲染图片卡片
└─ 注册表($DSH_HOME/plugins/dsh-image-inline/registry.json)
└─ GET /plugin/show-image/<attachmentId> → 图片字节
为什么需要插件自己的 HTTP 端点?
DSH 内置的 conversation.resolveImage → session.attachment RPC 只服务"会话日志的 image 块里被引用的附件"(api-proxy 的 referencedImage 授权)。本插件的结果故意不包含 image 块(否则图片会进入模型上下文),因此附件永远不会被日志引用,必须由插件自己提供读取通道。
安全性:attachmentId 是 sha256:<hex> 内容哈希——内容寻址 capability URL,不知道图片内容就无法猜测;id 只出现在用户可读的会话日志与插件注册表中。服务默认绑定 loopback,与整个 Web UI 同一信任模型。
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:condaThinker/dsh-image-inline
sudo systemctl restart dsh # 或按你的方式重启 web profile
本插件零构建(纯 JS),GitHub 直接分发源码,安装时无需执行任何构建脚本。
卸载:
npx -p @deepseek-ai/dsh dsh plugin --profile web remove dsh-image-inline
sudo systemctl restart dsh
配置
cordis.patch.yml 中的 config(可覆盖):
| 键 | 默认 | 说明 |
|---|---|---|
maxImageBytes | 26214400 (25MiB) | 单张图片编码字节上限(实际生效值 = min(本配置, 附件服务配置)) |
maxImagePixels | 40000000 (40MP) | 宽×高上限;0 关闭该检查 |
mediaTypes | png/jpeg/webp/gif | 接受的格式白名单 |
使用
在会话中让模型显示一张图片,例如:
用 show_image 显示 /path/to/your/image.png
模型调用后,对话流里该工具调用处会出现图片卡片(缩略图,点击看原图),可上翻查看历史。若图片不存在/格式不支持/超限,卡片显示错误文案,会话不中断。
测试
cd dsh-image-inline
node --test "tests/*.spec.mjs" # 33 个用例:host 24 + client 7 + 并发/路由回归
client 渲染用例按以下顺序解析 react/react-dom:DSH_HARNESS_NODE_MODULES 环境变量指向的目录(需装有 react@18 + react-dom@18),或本仓库 npm install 后的本地 node_modules。找不到时该套件自动跳过并提示,host 用例不受影响。
已知限制
- 像素超限孤儿附件:
saveImage先落盘后检查maxImagePixels——若插件配置比部署默认(40MP)更严,超限图片会留下一个无引用的附件对象(内容寻址、无害)。 - 注册表单调增长:每张展示的图在
$DSH_HOME/plugins/dsh-image-inline/registry.json留一条记录(约 200 字节/条)。 - 无构建步骤:host/client 均为纯 JS(modlens 同款零构建协议),
link:安装下改代码即生效,但新增/修改 bundle 行需重启 profile(HMR 覆盖不了 bundle 图变化)。 - 模型上下文纯净是设计目标:
show_image的结果永远是文本,图片只通过meta+ HTTP 端点到达浏览器。
开发者笔记(事故复盘)
- client bundle 必须遵循惰性 CJS 协议:
window.__ModuleLoader__.load({id, factory: (require) => {...; return module.exports}})——require是 factory 的注入参数,写成自由变量会在浏览器抛require is not defined。 - host 注入服务只能通过注入作用域访问:
ctx.inject(['webServer'], (scope) => scope.webServer.register(...)),在外层 ctx 上属性访问会抛cannot get property "webServer" without inject。 - 注册表写入已串行化(进程内 promise 队列),并行
show_image调用不会丢条目。