ysr666/dsh-vision-router
ysr666/dsh-vision-router为纯文本 Agent 提供视觉能力:内置免 Key 视觉链 + 像素级视觉工具(看图问答、定位、裁剪、像素对比、取色、OCR、矢量化、抠图、截图);粘贴图片即可用。
GitHub: Scorp1o117/dsh-tool-vision · npm: dsh-tool-vision
Part of the DeepSeek Harness Enhancement Suite — Vision · Soul/Persona · Long-term Memory · Plugin Marketplace.
External vision model for DeepSeek Harness.
DeepSeek's own models are text-only, and the harness derives every model
request strictly from the session log (llm/stream requests must equal the
durable derivation — the agent-loop invariant). This plugin bridges the gap
in two ways:
inspect_image tool — sends an image (local file, or http(s) URL) to
any OpenAI-compatible /chat/completions endpoint that supports
image_url content parts, and returns the vision model's textual answer
into the agent loop.inspect_image
hints before they enter the durable log, on the agent/pre-step
waterfall (the one seam where the harness lets a plugin replace the
messages of a proposed step). Images already logged by an older version
are repaired lazily with a surface replace on the session's first
pre-step. Only models listed in multimodalModels receive image blocks
directly; a model's declared inputModalities are never consulted,
because profiles routinely declare input: [text, image] on text-only
models just to pass the harness's prompt-admission check.inspect_image.tool-vision namespace (API endpoint, write-only key, model, bridge
options) in settings.yaml; changes hot-apply without a restart. The API
key lives in settings.yaml, not the profile patch. Mount by package name
(name: 'dsh-tool-vision') so the web client bundle is discovered.Mount in a profile patch ($DSH_HOME/profiles/<name>/cordis.patch.yml):
- insert:
- id: tool-vision
name: 'dsh-tool-vision' # after: pnpm add dsh-tool-vision in the profile
config:
baseURL: 'https://api.openai.com/v1'
apiKeyEnv: 'VISION_API_KEY'
model: 'gpt-4o-mini'
Or load it from a local path without npm:
- id: tool-vision
name: './plugins/dsh-tool-vision/index.js'
| Field | Default | Meaning |
|---|---|---|
baseURL | https://api.openai.com/v1 | OpenAI-compatible API base URL. |
apiKey | '' | API key (takes precedence over env). |
apiKeyEnv | VISION_API_KEY | Env var holding the key. |
model | gpt-4o-mini | Vision model id. |
maxTokens | 1024 | Max output tokens. |
timeoutMs | 60000 | Per-request timeout. |
maxImageBytes | 10MB | Largest accepted local image. |
description | default | Tool description shown to the model. |
bridgeTextOnly | true | Bridge pasted images to text hints on models that cannot see images. |
bridgeExportDir | temp | Export dir for bridged images (os.tmpdir()/dsh-vision-bridge). |
multimodalModels | [] | Model ids that receive image blocks directly (e.g. mimo-v2.5). |
llm-pi-ai:
providers:
your-provider:
models:
- id: deepseek-v4-flash
input: [text, image]
- id: tool-vision
name: 'dsh-tool-vision'
config:
multimodalModels: ['mimo-v2.5', 'grok-4.5']
Then pasting an image while on a text-only model stores a hint like
[User sent an image, exported to: <path>. Inspect it with the inspect_image tool...]
in the transcript (the pasted image no longer renders as pixels in that
message), and the agent inspects it through the configured vision endpoint.
Why not
llm/stream? The harness freezes every request and the agent-loop invariant fails any request whose messages diverge from the session-log derivation (log-reconstruction desync), and this cordis waterfall'snext()cannot replace request arguments. Theagent/pre-stepwaterfall is the supported seam: its decision messages become the durable log, so the invariant stays satisfied.
Key resolution order: config.apiKey → process.env[apiKeyEnv] →
process.env.OPENAI_API_KEY.
inspect_image| Arg | Required | Meaning |
|---|---|---|
path | ✅ | Image path (absolute, or relative to the current workspace) or http(s) URL. |
question | – | Optional specific question about the image. |
detail | – | auto / low / high resolution hint. |
Example endpoints (baseURL):
https://api.openai.com/v1 — gpt-4o, gpt-4o-minihttps://dashscope.aliyuncs.com/compatible-mode/v1 — qwen-vl-plus, qwen-vl-maxhttps://open.bigmodel.cn/api/paas/v4 — glm-4v-flash (free tier), glm-4v-plushttps://api.moonshot.cn/v1 — moonshot-v1-8k-vision-previewhttp://localhost:11434/v1 — llama3.2-vision (no key)Note for users
- This plugin is a standard profile bundle (
dsh.bundle.patch):dsh plugin --profile web add dsh-tool-visioninstalls and mounts it in one step — no manualcordis.patch.ymledits needed.- The settings section needs the
dsh-host-apiproxynamespace allowlist; the plugin patches it automatically on first start — restartdsh webonce more and the section appears. A dsh update overwrites the patch; the next plugin start re-applies it.- Settings changes hot-apply (no restart needed).
- Tested against DSH
0.1.0-rc.6.
14 vision_* tools driven by the same configured endpoint as
inspect_image (baseURL/apiKey/model) — no provider chain, no local models,
no extra settings:
| Tool | Purpose |
|---|---|
vision_describe | Image Q&A / multi-image comparison (optional structured JSON) |
vision_ground | Locate a target and return its ORIGINAL-pixel bounding box |
vision_detect | Enumerate elements (buttons, inputs, icons…) with numbered boxes |
vision_crop | Crop a pixel region to a PNG artifact |
vision_pixel_diff | Per-pixel comparison: ratio, worst regions, heatmap, report |
vision_colors | Dominant-color quantization for palette matching |
vision_ocr | Verbatim text transcription (letters only — not scene analysis) |
vision_long_screenshot_ocr | Chunked long-screenshot transcription into Markdown |
vision_trace | Potrace vectorization into colored SVG (worker-thread, safe) |
vision_extract_foreground | Solid-background removal → transparent PNG |
vision_html_screenshot | Headless render of a local .html (network blocked) |
vision_screenshot | Desktop capture (Win: PowerShell; macOS: screencapture; Linux: import/scrot) |
vision_present | Publish a generated image to the user via the host attachment store |
vision_materialize | Copy an attachment/local image into the workspace as a real path |
Quality & safety details:
VISION_CONTENT_FILTERED
instead of a generic backend error.<workspace>/.dsh-tool-vision/.[图片: <path>] marker and
the usage rule lives in a system-prompt section (clean transcript, same
model behavior).Requires sharp / potrace / puppeteer-core (declared in dependencies;
missing ones degrade lazily with an install hint and never break other tools).
inspect_image.MIT