DeepSeek Harness 插件

dsh-image-vision-veryint

Seamless image understanding for DeepSeek Harness: lets pure-text models read pasted/dropped images and Feishu/Lark images via a configurable vision model, without touching the host.(英文原文)

跳到安装方式

来源信息

GitHub 仓库
VeryInt/dsh-image-vision
最近更新
2026年8月17日
分类
远程与移动
GitHub stars
0
载体类型
plugin
目录证据
上游声明已找到 dsh.bundle
证据路径
package.json#dsh.bundle
核对版本
0.1.0-rc.8
上游核对日期
2026-08-20

该证据由上游目录提供。本站没有安装、运行或安全审核这个插件。

安装

默认先复制一段 Prompt,让 Agent 读 GitHub 仓库和源码;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读 GitHub 仓库和源码。

请先不要安装或执行任何命令。阅读这个插件的 GitHub 仓库、README 和关键源码,然后用清楚、直接的方式回答以下问题,帮助我判断它是否适合我的需求:

1. 这个插件是什么,解决什么问题;
2. 适合哪些用户和典型使用场景;
3. 安装后如何使用,并给出一个最小使用示例;
4. 有哪些已知限制,以及隐私、安全、兼容性或维护风险;
5. 给出“推荐 / 有条件推荐 / 不推荐”的明确建议和理由。

请区分仓库明确说明、根据源码推断和未知信息。证据不足时请明确说明,不要猜测或照抄 README。

GitHub:https://github.com/VeryInt/dsh-image-vision
插件名:dsh-image-vision-veryint
作者:VeryInt

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器4 个文件
README.md来源说明 · 只读预览
README 语言

dsh-image-vision

Seamless image understanding for DeepSeek Harness — lets pure-text main models read pasted/dropped images and Feishu/Lark images via a configurable vision model, without modifying any host code.

A pure "everything is a plugin" implementation: it wraps a documented llm service method and listens to official agent/tool waterfalls. No packages/ files are touched, so it portably runs wherever DeepSeek Harness runs.

> 简体中文说明见 README.zh.md

---

What it does

  • Paste / drop an image in chat — even when the main model is text-only

(e.g. DeepSeek V4 Flash routed through pi-ai), the image is accepted and described to the model as text.

  • Feishu / Lark document images<image token="..."/> produced by

lark_read_doc and friends is downloaded through lark-cli and described; the result is injected back as tool output.

  • describe_image model tool — describes a local image file path.
  • Full description, not just OCR — people, scenes, tables, charts and

verbatim text are all described, driven by a prompt you can override.

Pick a vision model from ModelScope free community API (e.g. Qwen/Qwen3-VL-8B-Instruct) or SiliconFlow (e.g. Qwen/Qwen3-VL-32B-Instruct). Routes are auto-discovered from your settings.

---

Why no host code changes

The web API proxy gates image upload/model-switch by calling llm.resolveModelInfo(...).inputModalities and rejecting when the model does not declare image. Since DSH is "everything is a plugin", this plugin:

1. Wraps ctx.llm.resolveModelInfo — when the target model lacks image input and a vision route is configured, the returned capabilities gain image, so the admission gate lets the image through. 2. Listens on agent/pre-step — before the real model request, each image block is transcribed by the vision model and replaced with its text, so the text-only main model only ever receives plain text.

Both steps use documented DSH extension points. No core files are changed.

---

Requirements

  • DeepSeek Harness 0.1.0-rc.6 (source checkout or installed release

both are supported, see Installation).

  • Node.js >= 22.19
  • A configured vision model provider (see Configuration).

---

Installation

Two deployment styles are supported: a source checkout (clone the deepseek-harness repo and run pnpm dsh web) and the installed release (npm i -g @deepseek-ai/dsh). Both go through the same dsh plugin manager; @deepseek-ai/* dependencies are provided by the host and resolved from the DSH installation anchor.

From GitHub (recommended)

npx @deepseek-ai/dsh plugin --profile web add github:VeryInt/dsh-image-vision

From a local path (development / validation)

git clone https://github.com/VeryInt/dsh-image-vision.git /path/to/dsh-image-vision
npx @deepseek-ai/dsh plugin --profile web add /path/to/dsh-image-vision

> Replace <profile> with whichever profile you use (web, headless, ...). > If pnpm blocks a git dependency's build/prepare script, allowlist the exact > key it prints under allowBuilds in <profile>/pnpm-workspace.yaml, then > re-run.

Restart Harness after installing. The plugin then appears under Settings → Plugins.

---

Configuration

Image recognition needs a vision model provider. Add an OpenAI-compatible vision endpoint in the DSH Models page (or ~/.dsh/settings.yaml), and — this is the part the Models page does not show — declare input: [text, image] on the model entry.

Example settings.yaml:

llm-pi-ai:
  providers:
    modelscope:
      displayName: ModelScope
      apiKeyEnv: MODELSCOPE_API_KEY
      api: openai-completions
      baseURL: https://api-inference.modelscope.cn/v1
      models:
        - id: Qwen/Qwen3-VL-8B-Instruct
          name: Qwen3-VL-8B
          input: [ text, image ]
    siliconflow:
      displayName: 硅基流动
      apiKeyEnv: SILICONFLOW_API_KEY
      api: openai-completions
      baseURL: https://api.siliconflow.cn/v1
      models:
        - id: Qwen/Qwen3-VL-32B-Instruct
          name: Qwen3-VL-32B-Instruct
          input: [ text, image ]

Then provide the API key in ~/.credentials.yaml or as an environment variable:

# ModelScope community access: generate at https://modelscope.cn
MODELSCOPE_API_KEY=ms-xxxxxx
# SiliconFlow: generate at https://cloud.siliconflow.cn
SILICONFLOW_API_KEY=sk-xxxxxx

> Use a vision model (VL suffix). Text-only models such as > Qwen/Qwen3.5-27B return empty results even when declared image-capable.

Plugin vision route

The plugin's cordis.patch.yml carries two relevant fields:

- insert:
    - id: dsh-image-vision
      name: dsh-image-vision
      config:
        provider: siliconflow      # vision provider route (empty = auto-discover)
        model: Qwen/Qwen3-VL-32B-Instruct   # vision model id (empty = auto-discover)
        # prompt: ...
        # maxImagesPerMessage: 4
        # feishuImages: true
        # maxFeishuImages: 5

Rules:

  • Both provider and model set: used as-is (highest priority).
  • Both empty: scan every configured provider and pick the first model

declaring input: [text, image] (this is the common case).

  • Changing the model = update these two fields and make sure the model

declares input: [text, image] in settings.yaml.

---

Verification

After a restart:

1. Paste an image in chat — the main model should describe its content (rendered as [图片内容] …). 2. Read a Feishu/Lark doc with images — tool output gains [飞书图片 <token>] … descriptions. 3. describe_image tool — ask the model to describe a local image path.

On a transient vision failure the reply still comes back with a [图片内容识别失败:…] / [飞书图片 … 识别失败:…] placeholder rather than failing the whole turn.

---

Options

FieldDefaultDescription
provideremptyVision provider route; empty = auto-discover
modelemptyVision model id; empty = auto-discover
prompt(full description)Instruction sent to the vision model
maxImagesPerMessage4Max images bridged per message; beyond throws
feishuImagestrueAuto-describe Feishu <image token>
maxFeishuImages5Max Feishu images per tool result

---

How this differs from oil-oil/dsh-vision

We looked at the community plugin oil-oil/dsh-vision before writing this one. Key differences:

oil-oil/dsh-visiondsh-image-vision
MechanismReplaces the official deepseek-official adapter with a VisionBridgeAdapter; installer disables the built-in llm-deepseekWraps only llm.resolveModelInfo and uses the official agent/pre-step waterfall — no adapter replacement, no built-in plugin disabled
Works withModels routed through deepseek-officialAny pure-text route (pi-ai deepseek, etc.) because it hooks the llm service, not a specific route
Vision backendsBundles several (zenmux / Bailian / see config / local OCR)Reuses your settings.yaml / Models vision providers (input: [text, image])
Settings UIShips a "Vision Recognition" cardNone — config lives in the plugin cordis.patch.yml
PackagingTypeScript + tsdown build, many peer depsPlain JS ESM, minimal peers, no build step

In short: oil-oil replaces the DeepSeek adapter (so it only affects deepseek-official and requires disabling the built-in plugin); this plugin only wraps a llm capability lookup and uses the official pre-step — it works for any text-only main model route and makes no destructive changes, which fits "everything is a plugin" more literally.

---

License

[MIT](./LICENSE)