Vision & Multimodal

dsh-vision-bridge

xieweikang123/dsh-vision-bridge · ★ 1

xieweikang123

Converts pasted images to text so text-only DeepSeek models can understand them.

License
MIT
Added
2026-08-23
Maintenance
active
Install kind
github

No manifest check is available; listing does not imply compatibility or security review.

安装

dsh plugin --profile web add github:xieweikang123/dsh-vision-bridge

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: en · Read Chinese README

Table of contents
  1. Install
  2. Let the model "accept" images
  3. Mount the plugin
  4. Configure the vision API key
  5. Configuration
  6. Backend cheat sheet
  7. How it works
  8. Known limitations
  9. License

Give a text-only dsh model "eyes" — paste an image, it is recognized into text before the model sees it.

dsh-vision-bridge is a plugin for DeepSeek Harness (dsh). It lets a text-only model (e.g. deepseek-v4-flash) understand pasted images: before a message reaches the model, each image block is sent to an OpenAI-compatible vision endpoint (Zhipu free glm-4.6v-flash by default), recognized into text, and swapped in — so the model only ever sees text.

  • Uses dsh's official agent/pre-step extension point. Non-intrusive; nothing in dsh's compiled artifacts is modified.
  • Mounts via cordis.patch.yml, alongside plugins like dsh-vision.
  • Free out-of-the-box (Zhipu free tier), with an automatic fallback chain against rate limits.

Install

# Clone into any standalone directory
git clone https://github.com/Xieweikang123/dsh-vision-bridge D:\project\dsh-vision-bridge

Let the model "accept" images

Before an image enters the agent, dsh checks the current model's inputModalities; if it does not include image, dsh rejects the message (MODEL_DOES_NOT_SUPPORT_IMAGES). Declare image input for your model in ~/.dsh/settings.yaml:

llm-pi-ai:
  providers:
    opencode-go:
      apiKeyEnv: OPENCODE_GO_API_KEY
      modelOverrides:
        deepseek-v4-flash:
          input:
            - text
            - image

This only lets dsh admit images into the agent request; turning the image into text is the plugin's job. If the gateway itself still rejects images (e.g. opencode-go returns unknown variant image_url), the plugin recognizes and replaces them before the image ever reaches the model, so the request contains no image block by then.

Mount the plugin

Add an insert entry to ~/.dsh/cordis.patch.yml (on Windows, name must be a file:// URL):

- insert:
    - id: dsh-vision-bridge
      name: 'file:///D:/project/dsh-vision-bridge/lib/index.js'

Configure the vision API key

The default uses Zhipu's free glm-4.6v-flash; you just need a key:

  1. Create an API key at https://open.bigmodel.cn.
  2. Put it in ~/.dsh/.env: VISION_API_KEY=<your-key>

Key resolution order: config.apiKey → $VISION_API_KEY → $DSH_VISION_API_KEY → $ZHIPUAI_API_KEY → $DASHSCOPE_API_KEY. A local Ollama endpoint needs no key.

Restart dsh, then paste an image and send it — the model will understand it.


Configuration

Option Type Default Description
baseURL string https://open.bigmodel.cn/api/paas/v4 OpenAI-compatible endpoint base URL
apiKey string "" API key; empty falls back to env vars
model string glm-4.6v-flash Vision model id at the endpoint
fallbackModels string[] [] Custom failover chain; empty uses Zhipu free-tier defaults
prompt string built-in Custom recognition prompt
maxTokens number 2048 Max output tokens per call
timeoutMs number 60000 Per-call timeout

Backend cheat sheet

Scenario baseURL model
Default (Zhipu free) https://open.bigmodel.cn/api/paas/v4 glm-4.6v-flash
Zhipu paid same glm-4.6v
Alibaba DashScope https://dashscope.aliyuncs.com/compatible-mode/v1 qwen3-vl-flash
Volcengine Ark https://ark.cn-beijing.volces.com/api/v3 doubao-seed-2-1-turbo-260628
Local Ollama http://localhost:11434/v1 qwen3-vl:4b (no key)

How it works

  1. User pastes/upload an image → dsh persists it as an attachment; it appears as an { type: 'image', attachment } block in the message.
  2. The plugin listens on agent/pre-step (dsh's official extension point, right before messages reach the model).
  3. On an image block → attachments.readImage(ref) gets the bytes → a base64 data: URL.
  4. It calls the vision endpoint's /chat/completions and gets back a text description.
  5. It replaces the image block with the recognition text (keeping the user's own text), returning { kind: 'enter', messages }.
  6. The text-only model receives pure text and understands the image.

Inspired by opencode-image-vision and dsh-vision, mapped to dsh's native extension points, with no extra runtime dependencies:

  • The default Zhipu free tier glm-4.6v-flash, the fallback chain (glm-4.1v-thinking-flash → glm-4v-flash), and the API-key resolution order follow dsh-vision (MIT).
  • The "recognize a pasted image into text for a text-only model" goal follows opencode-image-vision (MIT).

Identical images are cached by attachmentId to avoid re-recognition.


Known limitations

  • The original image does not appear in the conversation: the model cannot ingest images, so the plugin substitutes text and only text lands in history.
  • Recognition quality depends on the vision model: the free tier can be verbose on dense text (e.g. repeated terminal lines). glm-4.6v / qwen3.7-plus give better results.
  • Changes to plugin code require a dsh restart to load (hot-reload primarily covers cordis.patch.yml config edits).

License

MIT