# dsh-sight Plug-in vision for text-only [DeepSeek Harness (dsh)](https://deepseek.com/harness) models — paste an image, get a text description through a built-in VLM backend, no model switching. [中文版 → README.zh-CN.md](README.zh-CN.md) ## Features - **Built-in VLM presets** — OpenCode Zen (free, keyless) and Gemini Flash (free tier), plus a custom mode for any OpenAI-compatible endpoint. Pick one in the web settings page, done. - **Multi-image batch** — the `vision` tool takes up to 10 paths/URLs and describes all of them in ONE request, labeled per image. ## How it works 1. **Prompt-admission override** — dsh refuses image pastes for text-only models. dsh-sight wraps `apiProxy.sessions.prompt`: the paste is accepted, the bytes land in `/tmp/dsh-sight/image{N}/{hash}.png`, and the image block becomes a path hint before entering history. Works with any provider — no model variant to switch. 2. **`vision` tool** — the model calls it with the hint path (or any local path / http(s) URL); the plugin reads the bytes and answers through the configured OpenAI-compatible VLM backend. 3. **System-prompt section** — teaches the model the hint → `vision` tool flow. 4. **Web settings page** (Settings → Vision) — backend source (preset or custom endpoint), an effective-config preview showing the actual request target, API-key field, and advanced knobs. Saved through the standard settings RPC and applied live, no restart (hot-reload via the `dsh-sight:` section of `$DSH_HOME/settings.yaml`). 5. **Cache cleanup** — pasted images are stored under `/tmp/dsh-sight/image{N}/` with MD5 dedup and an LRU cap (`maxImages`, default 200). A boot-time sweep deletes `image*` dirs older than 7 days (`DSH_SIGHT_MAX_AGE_DAYS`), touching only the plugin's own directories; the OS clears `/tmp` on reboot too. 6. **Security** — the API key is `role('secret')` and never rides a settings response. Local reads are capped at 25 MiB; URL fetches get a 30s timeout, a 25 MiB cap, and must claim an `image/*` content type. Remote bodies are downloaded and inlined — the vision API never receives your URLs (no SSRF surface). Only png/jpeg/webp/gif/bmp are accepted. ## How to use 1. **Install & configure** — `dsh plugin --profile web add dsh-sight`, then open Settings → Vision, pick a preset (or a custom endpoint) and hit Save. 2. **Paste an image** — it is auto-saved under a plugin store directory and the image block becomes a hint carrying the exact path, e.g. `[Image #1 auto-saved to /tmp/dsh-sight/image1/xxxx.png]`. The store root is OS-dependent (`/tmp` on Linux, `/var/folders/…` on macOS, `%TEMP%` on Windows), but the hint always shows the real full path. 3. **Or call `vision` directly** — the `paths` array takes the hint path above, or any local path / http(s) URL, optionally with a `question`: ```json { "paths": ["/tmp/dsh-sight/image1/xxxx.png"], "question": "What does this chart show?" } ``` 4. **Batch** — up to 10 images per call, described in one request. ## Demo