DeepSeek Harness 插件

siegfly/dsh-deepseek-vision

Star 数 ★ 0 分类 模型与账号接入 收录于 2026-08-15 npm dsh-deepseek-vision

视觉语言网关:注册支持图片输入的 DeepSeek provider 路由,图片先由可配置 VL 模型(默认 Qwen-VL)描述成文字再发送。

安装

# npm 包(预构建)

dsh plugin --profile web add dsh-deepseek-vision

# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)

dsh plugin --profile web add github:siegfly/dsh-deepseek-vision

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。

README

安装: dsh plugin --profile web add dsh-deepseek-vision

dsh-deepseek-vision 是给 DeepSeek Harness 的视觉语言网关插件。 纯文本的 DeepSeek 编程模型 通过一个"网关"provider 路由获得贴图能力:图片先由可配置的视觉模型(默认 Qwen-VL) 逐字描述成文字,再交给 DeepSeek 继续写代码。官方仓库零改动、跨机器安装不锁官方版本。

English | 中文

目录

亮点

  • 贴图即用,不用换模型: 注册独立路由 deepseek-vision(显示名 DeepSeek + Vision), 真实声明 inputModalities: ['text','image']——聊天窗贴图、tool-fs read_image、浏览器 截图工具全部放行。
  • 每张图只描述一次:attachmentId 进程内 LRU 缓存,重试、上下文压缩、后续轮次 复用同一份描述,不重复计费。
  • 会话不变量保持: 原始图片仍持久化进 session log,历史 / 回放 / 重构不受影响。
  • 官方机制安装: bundle 声明 + dsh plugin add,四种 spec(npm / git / 目录 / tarball)、 web 与 headless 双 profile,与官方插件完全同一路径。
  • 换 VL 模型零改码: 端点 / 模型 / 提示词 / 密钥全在设置卡片,兼容任意 OpenAI 风格 /chat/completions 网关(DashScope、vLLM、OpenRouter、LM Studio…)。
  • 失败语义明确: 默认 fail-closed,稳定错误码(AUTH / TIMEOUT / TRANSPORT / IMAGE_TOO_LARGE…),或 placeholder 降级为文字占位继续。
  • 跨版本不锁死: 发布版不锁定官方 dsh 版本——目标机安装时用自己的 dsh 重建, 构建成功即兼容证明;装前检查分级提示,绝不静默失败。

快速开始

前置:dsh 已安装并启动过一次、PATH 里有 pnpmdsh plugin 命令经 pnpm 安装插件)。

安装(npm 发布版,推荐方式):

dsh plugin --profile web add dsh-deepseek-vision

部署使用: 重启一次 dsh web → Models 页选 DeepSeek + Vision → 设置 → 插件 → 插件配置里填 VL 密钥 → 聊天窗贴图,发消息。

卸载:

dsh plugin --profile web remove dsh-deepseek-vision

headless profile、其他 spec 形式(git / 目录 / tarball)、无 CLI 的机器——见安装

效果

聊天窗里选中 DeepSeek + Vision provider 之后:

模型选择器里的 DeepSeek + Vision provider 聊天窗贴图,图片被描述后发送给 DeepSeek
  • 粘贴 / 拖入图片 → 被配置好的视觉模型先描述成文字(逐字提取代码、报错、日志、 UI 文案,并描述布局);
  • 描述文字替代图片发给 DeepSeek → 你继续用 DeepSeek 写代码,同时获得图片理解能力;
  • 每张图片只描述一次,重试 / 压缩 / 后续轮次都复用同一份描述,不重复计费;
  • session 日志仍然持久化原始图片,历史 / 回放 / 重构不变量不受影响。

工作原理

flowchart LR
    User["聊天窗贴图 / read_image / 截图"] --> Gate["deepseek-vision 路由:inputModalities = text + image"]
    Gate --> Persist["apiproxy prompt RPC → ImageBlock 持久化进 session log"]
    Persist --> 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 序列化器对 image block 抛 UNSUPPORTED_CONTENT。本插件注册新的 provider 路由,继承官方 导出的 DeepSeekAdapterstream() 里把图片块经 VL 模型改写为文本后再走原汁原味的 DeepSeek wire;reasoning efforts / context 窗口 / 默认 maxTokens / retry policy 全部从 父类继承。

配置

全部可省略(走默认值)。两个 key 都支持 credential-ref(环境变量名),凭据经 dsh 的 credentials seam 解析(Web Models 页写入的凭据即可用),无 seam 时回退到启动环境变量:

路径 默认值 说明
provider deepseek-vision 注册的路由 id(避开 deepseek-official
displayName DeepSeek + Vision 模型选择器里的名字
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.maxCacheEntries 64 进程内描述缓存容量(LRU)
vl.onFailure fail fail = 描述失败整个请求失败;placeholder = 降级为文字占位继续

llm-vl-gateway 也是一个 settings namespace,三个编辑入口:设置 → 插件 → 插件配置 的"DeepSeek + Vision(视觉语言桥接)"卡片(vl.* 全字段 + VL 密钥)、Web Models 页 (deepseek.* 子段由可配置 provider 目录接管)、settings.yaml(两个子段都可写)。

插件设置卡片

provider / displayName 是注册期事实,修改即时生效(adapter 路由 + 可配置 provider 目录原子重注册,不需重启);改成已被占用的路由 id 时两个注册表保留旧值并记日志。

patch 行内配置示例(全部可选):

- insert:
    - id: llm-vl-gateway
      name: dsh-deepseek-vision
      config:
        deepseek:
          reasoningEffort: high
        vl:
          apiKeyEnv: DASHSCOPE_API_KEY
          model: qwen3-vl-flash

使用

  1. 设置两个 key:设置 → 插件 → 插件配置 → "DeepSeek + Vision(视觉语言桥接)" 卡片里填 VL 密钥(写入凭据存储,不出现在任何响应/设置里);DeepSeek key 沿用现有凭据;
  2. Models 页选择 provider DeepSeek + Vision(会话内切换即持久化为默认);
  3. 聊天窗贴图,发消息——图片自动被描述,DeepSeek 看到的是文字。

设置卡片是本插件的客户端面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 任选:

dsh plugin --profile web add dsh-deepseek-vision                          # npm(推荐)
dsh plugin --profile web add github:siegfly/dsh-deepseek-vision#<sha>       # git,锁 commit
dsh plugin --profile web add file:<本仓库路径>                        # 本地目录(开发)
dsh plugin --profile web add ./dsh-deepseek-vision-<version>.tgz              # tarball

headless 同理:dsh plugin --profile headless add dsh-deepseek-vision(客户端卡片只在 web 生效)。验证 bundle 层已挂载:dsh --profile web --dump-config | grep llm-vl-gateway。 卸载与安装一一对应:dsh plugin --profile <name> 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]

两种方式做同样的事:

  • dsh-deepseek-vision 链接进 profile 的 node_modules(运行时 @deepseek-ai/* 依赖经 官方 healed fallback 解析到同一个 dsh 安装,共享同一个 cordis 实例,无双实例问题);
  • dsh-deepseek-vision 对账进 dsh.profile.bundles——loader 按层挂载包内 cordis.patch.yml 的 insert 行(注册路由 + 设置段);
  • 首次安装时如 profile 布局缺失,按官方 initProfile 语义补齐(manifest + 空用户 patch 层 + pnpm-workspace.yaml),已存在的文件从不改动

装完重启一次 dsh web(bundles 层栈变化 + 客户端模块扫描按包名缓存)。

本仓库是独立 git 仓库,与 deepseek-harness 官方仓库没有任何 git 关系 (无 fork / 子模块 / 远程关联);官方 checkout 零改动。

版本对齐

插件的运行时 @deepseek-ai/* 依赖从目标机器自己的 dsh 安装解析(healed fallback), 且安装脚本在检查之前会先在目标机器上用目标机器自己的 dsh 类型重新构建插件。因此:

发布版不锁定任何官方版本——目标机器用比锚点更新(或更旧)的官方 dsh 都可以安装; 构建成功本身就是兼容性证明。若新官方版改了本插件用到的 API,构建会自然失败并给出明确 的 tsc 错误,那时才需要发新版适配。作者无需跟随官方每次升级重新发布。

  • dshCompat.anchorVersion 只声明提交的 lib/构建出处(出处声明,不是安装 许可);pnpm build 写入的 lib/build-anchor.json 让出处无法撒谎。
  • node scripts/check-compat.mjs [dshHome] 安装前对目标机分级:完全一致 = exit 0; 任何不一致 = exit 1 提示并放行;残缺发布 / 复刻漂移 = 拒绝(有环境变量强制开关)。

完整策略、退出码分级与发版触发条件:docs/VERSIONING.md

开发

pnpm test      # vitest
pnpm build     # tsc(宿主面 + 客户端面)+ tsdown 浏览器 bundle
  • scripts/harness-paths.mjs 是仓库唯一的解析缝:$DSH_CHECKOUT → 仓库根 harness-paths.json(gitignored)→ 本机已安装 dsh 的 healed fallback。
  • 纯 npm 机器上 2 个客户端测试套件自行跳过(npm 只发布浏览器闭包里的客户端运行时); 有官方源码 checkout 的机器跑全量。
  • 产物里的 @deepseek-ai/* 导入保持裸说明符,运行时走 profile fallback。

细节:docs/DEVELOPMENT.md。贡献指南:CONTRIBUTING.md; 安全漏洞报告:SECURITY.md

边界与注意

  • compaction:默认继承会话 provider(即网关路由),图片被改写且命中缓存;若把压缩 策略显式 pin 到 deepseek-official 且历史含图,会按原逻辑 UNSUPPORTED_CONTENT 失败。
  • 卸载后的含图会话:卸载插件后,含图历史会话无法切回文本模型(官方 selectModelinputModalities 准入拒绝,属预期行为,不是数据损坏);新会话不受影响,重装即恢复。
  • VL 失败语义:默认 fail-closed——描述失败(如 key 失效)整个请求以稳定错误码 (AUTH / TIMEOUT / TRANSPORT…)终止,不静默丢图;onFailure: placeholder 可降级。
  • 图片上限 fast-fail:描述前按部署图片准入上限(ctx.attachments.imageLimits)预检, 超限图片在 base64 编码前就以 IMAGE_TOO_LARGE 失败(placeholder 策略下降级),不把 几 MB 的 data URL 送进 VL 端点再死。插件不做图片降采样(官方 seam 没有公开的降采样 能力);部署上限内的图片仍可能超过 VL 供应商自己的大小上限,建议控制 vl.timeoutMs 并留意供应商文档。
  • 描述文本会占用 DeepSeek 的 context(每图几百 token,仅首次计费)。

FAQ

安装需要关心 Node 版本吗? 官方 CLI 路径(dsh plugin add)不需要;只有无 CLI 的 复刻脚本需要 Node 22.19+ / 24+ 和 PATH 里的 pnpm

#<sha> 是什么? git spec 形式的占位符——替换成具体 commit 哈希可锁死精确代码快照; 日常使用走 npm 形式即可。

支持 CLI(headless)吗? 支持。网关路由在两个 profile 行为一致;设置卡片是 web 专属,headless 用 settings.yaml 配置。

卸载后,含图历史会话选不了模型? 属预期行为:官方 selectModelinputModalities 拒绝文本模型接入含图会话。新会话不受影响,重装即恢复。

为什么图片不直接发给 DeepSeek? 官方 DeepSeek 接口是纯文本的(会拒绝 image_url),所以先由 VL 模型描述成文字再转发——不换模型、不丢信息。

许可

MIT

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →