ysr666/dsh-vision-router
ysr666/dsh-vision-router为纯文本 Agent 提供视觉能力:内置免 Key 视觉链 + 像素级视觉工具(看图问答、定位、裁剪、像素对比、取色、OCR、矢量化、抠图、截图);粘贴图片即可用。
视觉语言网关:注册支持图片输入的 DeepSeek provider 路由,图片先由可配置 VL 模型(默认 Qwen-VL)描述成文字再发送。
安装: dsh plugin --profile web add dsh-deepseek-vision
dsh-deepseek-vision 是给 DeepSeek Harness 的视觉语言网关插件。 纯文本的 DeepSeek 编程模型 通过一个"网关"provider 路由获得贴图能力:默认 native-first,目录声明支持 image 的模型 图片直通原生视觉端点;其余模型先由可配置的视觉模型 (默认 Qwen-VL)逐字描述成文字,再交给 DeepSeek 继续写代码。官方仓库零改动、跨机器 安装不锁官方版本。同类方案里它是最薄的桥:不注入 agent 工具、不经过第三方中转、 不依赖本地模型。
English | 中文
deepseek-vision(显示名 *DeepSeek + Vision*),真实声明 inputModalities: ['text','image']——聊天窗贴图、tool-fs read_image、浏览器 截图、MCP 工具返回的图片、ACP 客户端内联图片全部放行。
复用同一份描述,不重复计费。
dsh plugin add,四种 spec(npm / git / 目录 / tarball)、web 与 headless 双 profile,与官方插件完全同一路径。
OpenAI 风格 /chat/completions 网关(DashScope、vLLM、OpenRouter、LM Studio…)。
AUTH / TIMEOUT / TRANSPORT /IMAGE_TOO_LARGE…),或 placeholder 降级为文字占位继续。
install-profile)在目标机用**自己的** dsh 重建,构建成功即兼容证明,装前分级 提示、绝不静默失败;官方 CLI 路径(dsh plugin add`)直接安装发布产物,不在 目标机重建——运行时依赖经 healed fallback 解析,但兼容性未经目标机验证 (见版本对齐)。
dsh 视觉插件生态在官方 harness 发布后的几十小时内密集涌现,机制与取舍各不相同。本插件的 立场是一句话:最薄的桥——只加一条 provider 路由,其余什么都别加。
vision_describe / analyze_image 之类的工具,agent的行为面不变,贴图走的就是"贴图"这条原路;
只经过你自己配置的 VL 端点(你的 key、你的端点、你的数据);
121 个测试 / 97% 覆盖率、双语文档。
维度 · 本插件 · 工具型(如 dsh-vision-any、dsh-vision) · 路由型(如 dsh-vision-router) · 代理型(如 dsh-vision-proxy) · 本地管线型(如 DeepSeek-Harness-Vision-Tools) 机制 · provider 网关路由 · 注入 agent 工具 · 工具 + 多供应商路由 · 透明代理路由 · Python 本地 VLM 管线 图片数据流 · 只经你自己的 VL 端点 · 你自己的 API · 含第三方匿名回退 · 自有端点 + 回退链 · 本地模型,不出网 换 VL 模型 · 设置卡片,零改码 · 配置文件 · 配置文件 · 配置 + 自动探测 Ollama · 换本地模型 答案/描述缓存 · 进程内 LRU(仅描述) · — · 内容哈希答案缓存 · SHA-256 缓存 · — 失败语义 · fail-closed + 稳定错误码 · — · — · 超时保护 · — 发布链路 · 官方 bundle 机制 + 兼容门禁 + 锚点章 · — · — · — · 非 bundle
上表只列方向性差异,各项目仍在快速迭代;选型时请以各项目最新 README 为准。
前置:dsh CLI 已可用并启动过一次、PATH 里有 pnpm(dsh plugin 命令经 pnpm 安装插件)。
第一步:新机器装 `dsh`(一次性,二选一)。 dsh 是官方 CLI(npm 包 @deepseek-ai/dsh):
npm install -g @deepseek-ai/dsh # 推荐:dsh 永久进入 PATH,之后命令直接敲
# 或(官方一行启动方式):
npx @deepseek-ai/dsh web # 不装全局:CLI 只在 npx 缓存里运行,不会进 PATH⚠️ 用npx方式时dsh不会进入 PATH——新开终端直接敲dsh会报
"command not found"。要么全局安装,要么所有命令都带 npx @deepseek-ai/dsh 前缀。第二步:安装(git 形式,锁 commit,推荐):
dsh plugin --profile web add github:siegfly/dsh-deepseek-vision#<sha>
# 没装全局、走 npx 时:
npx @deepseek-ai/dsh plugin --profile web add github:siegfly/dsh-deepseek-vision#<sha>已发布的 npm 版(0.1.7)同样可用:把 spec 换成 dsh-deepseek-vision@0.1.7 (显式锁版本——pnpm 11 默认对发布不足 24h 的新版本设年龄门槛,裸 spec 在 0.1.7 发布 24h 内会暂时解析到旧版 0.1.5)。
部署使用: 重启一次 dsh web → Models 页选 DeepSeek + Vision → 设置 → 插件 → 插件配置里填 VL 密钥 → 聊天窗贴图,发消息。
卸载:
dsh plugin --profile web remove dsh-deepseek-visionheadless profile、其他 spec 形式(git / 目录 / tarball)、无 CLI 的机器——见安装。
聊天窗里选中 DeepSeek + Vision provider 之后:
·
deepseek-v4-flash-vision-exp)图片直通原生,直接走 DeepSeek 官方视觉端点; 纯文本 / 未列目录的模型则由配置好的视觉模型先描述成文字(逐字提取代码、报错、 日志、UI 文案,并描述布局);
flowchart LR
User["聊天窗贴图 / read_image / 截图 / MCP / ACP"] --> Gate["deepseek-vision 路由:inputModalities = text + image"]
Gate --> Persist["apiproxy prompt RPC → ImageBlock 持久化进 session log"]
Persist --> Decide{"DeepSeek 目录声明该模型支持 image?"}
Decide -- "是(官方视觉模型)" --> Native["yield* super.stream():父类原生序列化图片,直通 DeepSeek 视觉端点"]
Decide -- "否(纯文本 / 未列目录)" --> Bridge["ImageBridge:改写图片块(含 tool-result 嵌套)"]
VL["可配置 VL 模型(默认 qwen3-vl-flash,OpenAI 兼容端点)"] --> Bridge
Cache["attachmentId → 描述 LRU 缓存"] --> Bridge
Bridge --> Stream["yield* super.stream():原生 DeepSeek wire 继续流式"]为什么是"网关适配器"而不是中间件:DSH 有两道硬门槛——prompt / selectModel RPC 按 inputModalities 拒绝不含 image 的模型(纯 llm/stream 中间件拦不到),llm-deepseek 序列化器对 text-only 模型的 image block 抛 UNSUPPORTED_CONTENT。本插件注册新的 provider 路由,继承官方导出的 DeepSeekAdapter:stream() 先按父类目录判断所选 模型——目录声明 image 能力的(官方 rc.2 默认发布 deepseek-v4-flash-vision-exp)原样 直通,由父类原生序列化图片;纯文本与未列目录的模型才把图片块经 VL 模型改写为文本, 再走原汁原味的 DeepSeek wire。reasoning efforts / context 窗口 / 默认 maxTokens / retry policy 全部从父类继承。
全部可省略(走默认值)。两个 key 都支持 credential-ref(环境变量名)。已挂载 dsh 的 credentials 服务时,其解析结果(即使未配置)具有权威性;只有服务缺席才直接读取启动环境。 官方 credentials-local 的优先级是:进程环境变量(最高、只读)→ GUI 管理的 `.credentials.yaml` → `.env` 回退。因此 Web Models 页写入的凭据可用,而本次进程显式 导出的 key 始终优先且不能在 GUI 内修改:
路径 · 默认值 · 说明 provider · deepseek-vision · 注册的路由 id(避开 deepseek-official) displayName · DeepSeek + Vision · 模型选择器里的名字 mode · native-first · native-first = 原生视觉优先、文本模型回退;always-describe = 始终转描述;disabled = 完全退回官方 DSH 行为 deepseek.* · — · 与官方 llm-deepseek 段完全同构(apiKeyEnv / baseURL / thinking / reasoningEffort / maxTokens / models / retryPolicy…) deepseek.apiKeyEnv · DEEPSEEK_API_KEY · DeepSeek key vl.apiKeyEnv · QWEN_VL_API_KEY · VL 模型 key vl.baseURL · https://dashscope.aliyuncs.com/compatible-mode/v1 · 任意 OpenAI 兼容 /chat/completions 网关 vl.model · qwen3-vl-flash · VL 模型 id(贴图 OCR 型描述性价比最高;复杂视觉推理可换 qwen-vl-max) vl.describePrompt · 详述 + 逐字提取的英文提示词 · 图片描述指令 vl.timeoutMs · 120000 · 单次描述请求硬超时 vl.maxTokens · 2048 · 单张图片描述的最大输出 token vl.maxPixels · 4194304 · DSH 在发送 VL 前进行确定性缩放的总像素上限 vl.maxBytes · 5000000 · DSH 在发送 VL 前进行确定性编码的目标字节数 vl.maxCacheEntries · 64 · 进程内描述缓存容量(LRU) vl.onFailure · fail · fail = 描述失败整个请求失败;placeholder = 降级为文字占位继续
llm-vl-gateway 也是一个 settings namespace,三个编辑入口:设置 → 插件 → 插件配置 的"DeepSeek + Vision(视觉语言桥接)"卡片(vl.* 全字段 + VL 密钥)、Web Models 页 (deepseek.* 子段由可配置 provider 目录接管)、settings.yaml(两个子段都可写)。 卡片与 DSH 原生插件一致默认收起;折叠不会丢失草稿,保存成功后自动收起。
provider / displayName 是注册期事实,修改即时生效(adapter 路由 + 可配置 provider 目录原子重注册,不需重启);改成已被占用的路由 id 时两个注册表保留旧值并记日志。
patch 行内配置示例(全部可选):
- insert:
- id: llm-vl-gateway
name: dsh-deepseek-vision
config:
deepseek:
reasoningEffort: high
mode: native-first
vl:
apiKeyEnv: DASHSCOPE_API_KEY
model: qwen3-vl-flash卡片里填 VL 密钥(写入凭据存储,不出现在任何响应/设置里);DeepSeek key 沿用现有凭据;
设置卡片是本插件的客户端面(dsh.client):以官方解耦插件的方式注册进 settings.plugin.item 槽位,编辑 llm-vl-gateway.vl 段,与官方内置卡片(终端 / Agent 循环 / 网页搜索)同机制、同交互(暂存草稿、覆盖状态显示、保存时整体写入)。
安装走官方 bundle 机制:本包在 package.json 声明 dsh.bundle.patch(指向包内 cordis.patch.yml),dsh plugin add 把包链接进 profile 并把包名对账进 profile manifest 的 dsh.profile.bundles 层栈,loader 启动时按层挂载——不需要手工往 `cordis.patch.yml` 加任何行(旧版本加过的受管块会在下次安装/卸载时自动迁移移除)。
四种 spec 任选(日常推荐 git 形式,锁 commit):
dsh plugin --profile web add github:siegfly/dsh-deepseek-vision#<sha> # git(推荐),锁 commit
dsh plugin --profile web add dsh-deepseek-vision@0.1.7 # npm(已发布 0.1.7,显式锁版本)
dsh plugin --profile web add file:<本仓库路径> # 本地目录(开发)
dsh plugin --profile web add ./dsh-deepseek-vision-0.1.7.tgz # tarball(npm pack 产物)headless 同理:dsh plugin --profile headless add dsh-deepseek-vision(客户端卡片只在 web 生效)。验证 bundle 层已挂载:dsh --profile web --dump-config | grep llm-vl-gateway。 卸载与安装一一对应:dsh plugin --profile remove dsh-deepseek-vision。
无 CLI 的机器用等价复刻(需 Node 22.19+ 或 24+、PATH 里有 pnpm;init 布局 → 目标机 重建 → 兼容门禁 → pnpm add → bundles 对账):
pnpm install # 只装 devDeps(typescript/vitest),不会装 @deepseek-ai/*
pnpm install-profile # 或 node scripts/install-profile.mjs [profile] [dshHome]这是唯一在目标机重建的安装路径:install-profile 先用目标机自己的 dsh 类型重新构建 插件并通过 check-compat.mjs 门禁,再装入 profile(见版本对齐)。 两条路径都做下面两件事:
dsh-deepseek-vision 链接进 profile 的 node_modules(运行时 @deepseek-ai/* 依赖经官方 healed fallback 解析到同一个 dsh 安装,共享同一个 cordis 实例,无双实例问题);
dsh-deepseek-vision 对账进 dsh.profile.bundles——loader 按层挂载包内cordis.patch.yml 的 insert 行(注册路由 + 设置段);
initProfile 语义补齐(manifest + 空用户patch 层 + pnpm-workspace.yaml),已存在的文件从不改动。
装完重启一次 `dsh web`(bundles 层栈变化 + 客户端模块扫描按包名缓存)。
本仓库是独立 git 仓库,与 deepseek-harness 官方仓库没有任何 git 关系
(无 fork / 子模块 / 远程关联);官方 checkout 零改动。