ariesy
dsh-vision
DeepSeek Harness (DSH) dynamic Cordis plugin: global image upload button + configurable vision-model recognition with fallback
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 16, 2026
- Updated
- Aug 16, 2026
Introduction
dsh-vision
一个运行在 DeepSeek Harness (DSH) 上的动态 Cordis 插件:为所有会话提供图片上传能力,并用可配置的视觉模型自动识别图片,支持 fallback 回退链。
源码整理为独立项目,存放在 /app/dsh-vision/。
功能
| 能力 | 说明 |
|---|---|
| 📎 全局上传按钮 | 每个会话的输入框工具行出现上传按钮;选图后图片作为草稿缩略图附加到消息,同时文件保存到该会话工作区的 uploads/ 目录 |
| 自动图片识别 | 消息中的图片由视觉模型识别,识别结果以文字笔记注入模型上下文([uploaded image recognized by vision model <model>]) |
| 任意视觉模型选择 | 设置页自动列出所有声明支持 image 输入的模型,可任选其一作为主识别模型 |
| Fallback 回退 | 主模型识别失败(报错或空结果)时自动切换备用模型;可独立开启/关闭 |
| 无配置默认行为 | 未配置时按名称优先(vl/vision/image 匹配)自动选择识别模型,避免误选不支持识别的模型 |
设计要点
- Host half(
src/host.js):拦截llm/streamwaterfall。请求含图片时,先对每张图片调用视觉模型识别(不带 system 消息 —— 某些网关只认同一条用户消息内的图片),再把图片块替换为文字笔记。识别请求本身通过inFlight防重入保护。 - Client half(
src/client.js):注册两个 Slot ——conversation.input.left(上传按钮)与settings.plugins.tab("图片识别"设置页)。Client 与 Host 之间仅通过包私有 JSON RPC(host.call)通信。 - 配置存储:动态插件是进程内的,配置保存在进程内存中(主模型/fallback/开关),随插件生命周期;DSH 重启后需重新定义并运行插件。
安装
方式一:动态插件(推荐,无需重启 DSH)
src/host.js 与 src/client.js 正是动态插件定义所需的 code.host / code.client 函数体,可直接使用:
- 获取源码:
git clone https://github.com/ariesy/dsh-vision.git
# 或直接用本机路径 /app/dsh-vision
- 在 DSH 中定义动态插件(可通过 GUI 的插件运行卡片,或会话内
cordis_define):plugin前缀任取(如dsv),插件名dsh-visioncode.host←src/host.js内容code.client←src/client.js内容
- 运行该插件并在运行卡片上批准。
- 刷新浏览器页面(动态插件的 Client half 在页面加载时注入):
- 输入框工具行左侧出现 📎 上传按钮
- 设置 → 插件 → 图片识别 出现配置页
注意:动态插件是进程内的 —— DSH 重启后需重新定义并运行(步骤 2–4)。
方式二:作为标准 Cordis 插件行
需要把两文件包装为标准插件模块后放入预设的 cordis.yml:
// host-plugin.js —— 包装示例
module.exports = {
apply(ctx) {
return /* 粘贴 src/host.js 中 `return { ... }` 的内容 */;
},
};
// client-plugin.js —— 包装示例(同理,返回 src/client.js 中的 `return { ... }` 内容)
module.exports = {
apply(ctx) { ... },
};
# cordis.yml 或预设 composition
- id: dsh-vision-host
name: ./host-plugin.js
- id: dsh-vision-client
name: ./client-plugin.js
方式三:由 DSH 自主阅读并安装
在任意 DSH 会话中直接下达指令,让 agent 读取本项目源码并完成定义、运行:
阅读 /app/dsh-vision 项目(或 git clone https://github.com/ariesy/dsh-vision.git),
把 src/host.js 与 src/client.js 分别作为 code.host / code.client 定义并运行同名动态插件。
agent 会自主完成:读取源码 → cordis_define 定义插件(名称 dsh-vision)→ cordis_run 运行。之后同样需要你在运行卡片上批准,并刷新浏览器页面使 Client half 生效。
该方式与方式一本质相同,只是由 agent 代为读取和提交代码,适合不想手动复制粘贴的场景。
使用
- 在 DSH 中定义并运行此插件的 Host + Client 代码(通过动态插件运行卡片,批准后生效)。
- 刷新浏览器页面。
- 任意会话:点击输入框工具行左侧的 📎 上传图片 → 图片附加为缩略图 → 发送消息 → 自动识别并回复。
- 配置:设置 → 插件 → 图片识别:
- 主识别模型:下拉选择任意视觉模型(或"自动选择")
- Fallback 模型:下拉选择备用模型(或"不使用 fallback")
- 勾选"主模型失败时启用 fallback"
- 保存配置 / 刷新模型列表
项目结构
/app/dsh-vision/
├── package.json # 项目元数据(npm 项目壳)
├── README.md # 本文档
└── src/
├── host.js # Host half:llm/stream 拦截、识别链、配置与上传 RPC
└── client.js # Client half:上传按钮 + 设置页 UI
验证
cd /app/dsh-vision && npm run check # node --check 两个源码文件
运行时验证样例(2026-08 环境):用户上传一张《帝港海湾豪园缴费通知单》图片,模型识别并给出准确描述(期间费用区间、金额 198.64 元、制单日期等字段全部正确)。
依赖的 DSH 接口
ctx.get('llm'):listProviders()、listModels(provider)、stream(options)- 事件:
llm/stream(waterfall,ctx.on) harness.handle(method, handler):包私有 RPC- Client:
slots.inject/slots.register、host.call、React(无 JSX) ctx.get('agents')/ctx.get('subprocess')/ctx.get('fs'):上传文件落盘