ysr666/dsh-vision-router
ysr666/dsh-vision-router为纯文本 Agent 提供视觉能力:内置免 Key 视觉链 + 像素级视觉工具(看图问答、定位、裁剪、像素对比、取色、OCR、矢量化、抠图、截图);粘贴图片即可用。
纯文本路由的透明图片护栏:贴图不再 400 卡死会话,附带 vision_analyze 工具(OCR/PDF/docx/pptx/视频)。
English | 中文
Let text-only models "see" images — and never let an image deadlock your session. Transparent image guard + vision analysis tool for DeepSeek Harness (dsh).
Most models on DeepSeek Harness (deepseek-v4-pro etc.) are text-only, which causes two problems:
400 unknown variant \image_url`` → the conversation is stuck forever.This plugin fixes both with two gates, and turns images into text the main model can actually consume.
paste image → [Gate 1] agent/pre-step: the image is converted to text by the vision
model BEFORE it is ever written into the session log
→ the log only contains text, no image block exists
→ [Gate 2] llm/stream backstop: if an image block still appears in
replayed history (e.g. a session poisoned before install), it is
rewritten to OCR text at request time before reaching the model
deepseek-v4-pro keeps reasoning; image content arrives as text.vision_analyze tool (model-invoked, engine chosen by the model per task): reads workspace files — image OCR, PDF text layer + embedded images, docx/pptx text + embedded images, video frame OCR (≤12 frames), plain text files; loud rejection for xlsx/doc.Compared with dsh-vision-router, ModLens, dsh-vision-toolkit, see_image/view_image and similar:
vision_analyze's engine argument (local free character OCR / vision model) is decided by the model after analysing the task: cheap and smart.npm test).# 已发布 npm 后:
dsh plugin --profile web add dsh-vision-guard
# 或直接从 GitHub 安装:
dsh plugin --profile web add github:good-boy4069/dsh-vision-guard
If pnpm refuses with
ERR_PNPM_ADDING_TO_ROOT(older launchers), add the workspace-root flag:dsh plugin --profile web add -w dsh-vision-guard.
Restart dsh web. Or add the two rows from the repo's cordis.patch.yml to your profile patch layer manually.
All fields optional (defaults shown). The vision route must point to a model that accepts image input:
| Field | Default | Meaning |
|---|---|---|
visionProvider / visionModel | opencode-go / minimax-m3 | The vision route. Point it at an image-capable model on your subscription |
ocrTimeoutMs | 45000 | Per-image OCR timeout |
budgetPerDay | 200 | Daily OCR cap (runaway-cost guard), state stored under $DSH_HOME |
cacheMaxEntries | 500 | OCR result cache size cap (LRU eviction) |
maxOcrTokens | 2048 | Vision call output cap |
stateFile | ~/vision-guard-state.json | Budget state file (~ = dsh home) |
ocrPrompt | verbatim transcription | Custom instruction |
passthrough | [] | Raw-image whitelist: [{provider, model}] — only add routes you have tested to accept images |
vision_analyze side: the OCR engine is a required per-call argument (engine), chosen by the model per task — local = local tesseract (free, characters only), vision = the configured vision model. There is no localOcr config key.
minimax-m3 on opencode-go). Text-only models like deepseek-v4-pro cannot serve as the vision model — their upstream gateway 400s on images and deadlocks the session.passthrough. This is the core anti-deadlock design; do not bypass it.vision_analyze's document/video paths; plain image OCR needs none):
pdftotext/pdfimages (poppler-utils);ffmpeg/ffprobe;python3 (stdlib only);tesseract (free local OCR; needs chi_sim+eng).budgetPerDay as a backstop.42 + 7 = 49 as 4247249 in our tests); for charts/photos/complex UI pick the vision engine (the model chooses per task when calling vision_analyze).input: [text, image] on a text-only model in your model settings (required for GUI image pasting), you must keep this guard installed — removing the guard while keeping that declaration will deadlock sessions again.ctx.get('visionGuard')?.status(), or the [vision-guard] active line in the dsh log.dsh plugin remove), restart; already-recognized text stays in history, no side effects.MIT