dsh-vision
DSH (DeepSeek Harness) vision plugin: image recognition and generation for text-only models, with a multi-engine failover chain and full UI integration.
Built for personal use — engines ride what you already have (your logged-in Codex / ChatGPT account), with free Zhipu and optional Gemini fallbacks. Every engine parameter is editable in the harness Settings page, and all temporary data is delete-after-use (用完即焚).
Tools
| Tool | What it does | Engine chain |
|---|---|---|
describe_image | Read a local image, return a description. Default mode is structured (JSON evidence: description + OCR lines with pixel boxes + layout regions + entities); the agent integrates it into a natural-language answer. mode: text for plain description only | Codex → Gemini → Zhipu GLM |
generate_image | Generate an image from a prompt; shown inline in the conversation (produced-file card + lightbox + download + reveal in Finder). quality: auto (Nano Banana 2 Lite, cheapest) / hd (Nano Banana Pro 1K/2K) / 4k (Nano Banana Pro 4K) | Codex (GPT Image) → Gemini Nano Banana (paid key) → Zhipu CogView |
Image input (paste / drag → path)
The GUI blocks image paste for text-only models. This plugin intercepts paste and drag at the window level, uploads the image to ~/.dsh/generated-images/uploads/ (content-addressed: identical images are stored once), and inserts the file path as text into the composer — the model only ever sees text. A thumbnail rail above the input shows the images (preview, horizontal scroll, per-image delete that also removes the path from the draft). After sending, the images are injected back into the conversation beside your user message.
Storage discipline (用完即焚)
- Every Codex call runs
--ephemeral(no session files in~/.codex/sessions)
with --sandbox workspace-write.
- Generated images:
gen-<hash>-<内容>-<引擎>.<ext>+ a.meta.json
sidecar (engine label for the caption). The old plain-hash path is kept as a symlink so historical images keep working.
- Uploads: deduplicated by content hash; auto-cleaned after
uploadRetentionDays (default 7, 0 = never); orphan .meta.json sidecars are cleaned automatically.
- Existing
~/.codexdata is never touched.
Settings (Settings page → dsh-vision)
| Key | Default | Meaning |
|---|---|---|
codexPath | auto | Codex CLI path (blank = auto-detect) |
uploadRetentionDays | 7 | Upload retention (0 = keep forever) |
describeEngines | ["codex","gemini","zhipu"] | Recognition chain order |
generateEngines | ["codex","gemini","zhipu"] | Generation chain order |
engines.codex.* | gpt-5.6-luna / max / priority | Codex model, effort, speed tier, timeout |
engines.gemini.* | aliases + Nano Banana models | Gemini describe chain + generation models |
engines.zhipu.* | glm-4.6v-flash / cogview-3-flash | Zhipu models, size, timeout |
Credentials (~/.dsh/.credentials.yaml)
DEEPSEEK_API_KEY— DeepSeek (harness)GEMINI_API_KEY— Gemini recognition (free tier; Pro degrades to Flash)GEMINI_IMAGE_API_KEY— generation only, paid, separate projectZHIPU_API_KEY— Zhipu fallback (free)
Engine registry (adding/removing models)
Engines live in the ENGINES registry in lib/index.js:
const ENGINES = {
codex: { id, label, describe(bytes, cfg, prompt, signal, runtime), generate(prompt, cfg, signal, runtime) },
gemini: { ... },
zhipu: { ... },
// future: openai: { ... }, ollama: { ... }
};Add = one registry entry + one settings config object + a default. Remove = delete those. Chain order and per-engine params are editable in Settings.
Install
dsh plugin --profile web add /path/to/dsh-visionThen restart dsh web. Add keys to ~/.dsh/.credentials.yaml for the fallback engines.
Requirements
- Node.js with the DSH harness (
dsh web) - Codex CLI (npm:
@openai/codex) logged in with a ChatGPT account - Optional: Zhipu / Gemini keys for fallback engines
License
MIT