OoWJZZoO/dsh-read-image
DeepSeek Harness 的一款即插即用图像读取插件。安装后,DSH 将不再拒绝将图像输入到纯文本模型的会话中;相反,图像会在会话中映射为 [Image #N]。随后,Agent 可以自行调用工具,从会话或指定路径读取图像。
项目介绍Project Overview
为纯文本 DeepSeek Harness 模型提供图像读取能力。核心功能:将粘贴的图像投影为 [Image #N] 文本占位符,并通过一等公民 read_image 工具调用可配置视觉模型进行解读,原生多模态路由透传。适用场景:希望文本模型具备图像理解能力,又不想改动预设。注意:依赖 harness 内部接口,启动时会自检,失败则安全降级不影响运行;Windows 下需用 Git Bash 运行部署脚本。
Brings image reading to text-only DeepSeek Harness models. It projects pasted images as [Image #N] placeholders and exposes a first-class read_image tool that delegates interpretation to a configurable vision model; native multimodal routes pass through untouched. Use it when a text model must reference images without altering presets or switching endpoints. Caveat: it depends on harness internals — startup self-checks fail safely if contracts drift, and Windows deployment scripts need Git Bash, WSL, or MSYS2 to run.
请帮我了解并安装插件:【dsh-read-image】【https://github.com/OoWJZZoO/dsh-read-image】
把上面这条消息直接发给当前会话里的 DSH,让它帮你了解并安装。安装命令不一定准确,发给 DSH 更稳。Send this message to DSH in your current session. CLI install commands may not be accurate across systems — DSH will figure it out for you.
或使用命令行安装(适合开发者)Or use CLI install (for developers)
命令行安装CLI Install
dsh plugin --profile web add github:OoWJZZoO/dsh-read-image
把 OoWJZZoO/dsh-read-image 加入你的 DSH 配置(web profile)即可启用。
READMEREADME
dsh-read-image
Plug-and-play image reading for text-only DeepSeek Harness models: pasted images are admitted, projected as
[Image #N], and read back through a first-classread_imagetool backed by a configurable vision model — no preset changes required.
A DeepSeek Harness plugin that lets non-multimodal models "see" images.
- Pasted images are no longer rejected — text-only routes are declared to accept image input, so the api-proxy admission gate lets them through.
[Image #N]projection — on text-only routes, image blocks in the model request are replaced in place with[Image #N]text; pixels never reach a text API. Native multimodal routes pass through untouched.- First-class
read_imagetool (registered automatically in every session, shadowing the built-in tool of the same name):image_index— read the Nth image in the conversation ([Image #N]);file_path— read an image file from a path (PNG/JPEG/WebP/GIF);prompt/reasoning_effort/timeout_ms/max_tokens/max_thinking_tokens— optional overrides; omitted parameters use the configured defaults (the current real defaults are interpolated into the tool description, so the agent never has to guess);- on text-only routes the configured vision model converts the image into a text description; on native multimodal routes the image itself is returned;
- stateless and repeatable, including re-reading the same image.
- Native multimodal routes fall back to the built-in tool: when the session's base route itself declares image input (e.g.
mimo-v2.5), the custom tool is not registered and no[Image #N]prompt section is injected — the model sees real image blocks and uses the harness's built-inread_image(file_pathonly, "return the image itself").
- Visual configuration — a "Read image" section in the settings panel (gear icon in the sidebar) edits the vision model and defaults; the browser talks to the host over a typert Remote bridge (
readImageConfig), working around the harness's settings allowlist for plugin namespaces.
Installation
Requires DeepSeek Harness (dsh) 0.1.0-rc.6 or later (the harness is in developer preview; a newer release candidate may need a compatibility pass).
Windows: the plugin runtime is pure Node.js and runs on Windows as-is — the harness natively handles Windows paths (drive letters, case-insensitive filesystems, PowerShell command execution).
dshis installed via npm asdsh.cmd(on your PATH), and~/.dshmaps to%USERPROFILE%\.dsh(e.g.C:\Users\<you>\.dsh). Every command below works unchanged; wherever a literal path is shown, substitute%USERPROFILE%\.dsh\...for~/.dsh/....
Recommended: dsh plugin add
dsh plugin --profile web add github:OoWJZZoO/dsh-read-image
Then restart dsh web. This package ships a cordis.patch.yml via its dsh.bundle manifest, so the profile bundle mechanism composes the plugin row automatically — no manual patch editing.
Manual install
Add the package to the web profile and register the plugin row yourself:
// ~/.dsh/profiles/web/package.json → dependencies
"@deepseek-ai/dsh-read-image": "github:OoWJZZoO/dsh-read-image#v0.1.0"
cd ~/.dsh/profiles/web && pnpm install
Insert one row into ~/.dsh/profiles/web/cordis.patch.yml:
- insert:
- id: read-image
name: '@deepseek-ai/dsh-read-image'
config: {} # optional: deployment defaults (user layer can override)
Then restart dsh web.
Do not combine the two paths:
dsh plugin addalready composes the plugin row, so adding the dependency manually and inserting the row would register the plugin twice.
Configuration
Configuration lives in $DSH_HOME/settings.yaml (hot-reloaded, no restart) — on Windows, %USERPROFILE%\.dsh\settings.yaml when DSH_HOME is unset — and can also be edited in Web at Settings → Read image (writes to the user layer, overriding the corresponding settings.yaml keys):
# 1) Declare image input for your vision model (pi-ai route)
llm-pi-ai:
providers:
<your-provider>:
models:
- id: <your-vision-model>
# …contextWindow / maxTokens…
input: [text, image] # ← required
# 2) This plugin's configuration
dsh-read-image:
visionProvider: <your-provider> # the route provider hosting the vision model
visionModel: <your-vision-model> # the multimodal model id (must declare input: [text, image])
| Key | Default | Description |
|---|---|---|
visionProvider |
'' |
Route provider of the vision model (dropdown fed by the Models page) |
visionModel |
'' |
The multimodal model that performs read_image tasks (dropdown under that provider) |
defaultPrompt |
English step-by-step description prompt (classify → verbatim text to Markdown / visual description) | Used when read_image is called without prompt |
defaultReasoningEffort |
low |
Default reasoning intensity. low is the lowest tier widely accepted and honored; on many adapters off is equivalent to "omit the field" and does not disable thinking on models that default it on, so thinking eats into max_tokens and small budgets come back empty |
defaultTimeoutMs |
300000 |
Default vision-call timeout (5 minutes, generous) |
defaultMaxThinkingTokens |
4096 |
Default max thinking tokens (separate budget, not counted against output); when thinking exceeds the budget and the output comes back empty, read_image reports an explicit error instead of silently returning nothing |
defaultMaxTokens |
8192 |
Default actual output token cap; the API max_tokens sent is this + defaultMaxThinkingTokens (budget is 0 with reasoning_effort=off, passed through unchanged) |
guard.enabled |
true |
Environment self-check switch; false skips the self-check and force-loads the plugin (see Safety) |
Why not the settings protocol? The harness allowlists
WEB_SETTINGS_NAMESPACES, so a pluginsettings.register()namespace only answerssettings-not-exposedto the browser. The "Read image" page therefore talks to a host-side typert Remote bridge (readImageConfig.get/set, seelib/config-remote.js) instead — settings.yaml stays the base layer, Web writes go to the user layer,scope.watchhot-syncs the runtime, and headless and Web stay consistent.
Usage
- Paste an image: the text model sees
[Image #1]; callread_image image_index=1to view it. read_image file_path=/path/to/image.pngreads an image file (on Windows, bothC:\Users\...andC:/Users/...spellings work — backslashes are handled by the harness file service).- Pass
prompt(a specific question for the vision model),reasoning_effort,timeout_ms,max_tokens,max_thinking_tokensto override the defaults. - Call it repeatedly, including re-reading the same image.
Safety
This plugin rides on harness internals that can change shape between releases. On startup it runs an environment self-check over every harness contract it touches. If any check fails, the plugin fails safe: it loads nothing and the harness boots normally — the full diagnostics are written to ~/.dsh/logs/dsh-read-image-guard.log (on Windows: %USERPROFILE%\.dsh\logs\dsh-read-image-guard.log) and one short notice is logged. To force-load anyway (at your own risk): guard.enabled: false under the dsh-read-image section of settings.yaml.
How it works
| Mechanism | Layer | What it does |
|---|---|---|
| M1 admission | host | Wraps llm.resolveModelInfo so text-only routes report image input (restored on dispose) → send/switch-model gates let images through |
| M2 projection | host | Synchronous llm/stream waterfall listener: on text-only routes, image blocks become [Image #N] text, then re-dispatches the harness-deepFreezed request |
| M3 tool | per-agent | Registers read_image into the agent's own scope at session/created (shadowing the built-in tool) plus a prompt section |
| Settings | host | Registers the dsh-read-image settings namespace (schema defaults = fallback), hot-syncs runtime config via scope.watch |
| Config bridge | host | ReadImageConfigService (typert Remote, readImageConfig.get/set) reads/writes the same namespace; auto-discovered by the gateway |
| Config page | browser | settings.section registers the "Read image" page (order 12); ctx.remote.$mount self-mounts remote.readImageConfig |
| G1 self-check | host + browser | Total fuse: probes every harness contract at apply; any failure → plugin loads nothing, harness unaffected (see Safety) |
- Capability truth table: built from the original
resolveModelInfo(never the M1-wrapped one), rebuilt onllm/adapters-updatedwith startup retries; - Vision calls reuse
ctx.llm(same credentials / retries / logging as the harness), withAbortSignal.any([exec.signal, timeout])for timeouts; - Session logs are the single source of truth: image references persist as usual, and only the model-visible boundary performs the
[Image #N]replacement.
Development
Contributor guide and the full list of harness-workaround hacks (and the reasons they exist) live in AGENTS.md and docs/known-hacks.md. Tests: node --test test/ (run from the dev-profile copy — see the test file headers).
The plugin code itself is cross-platform (pure Node.js, no OS-specific APIs). The dev/deploy scripts (scripts/*.sh) are POSIX bash — on Windows run them under Git Bash / WSL / MSYS2, or mirror the copy steps by hand (they only copy package.json, lib/ and cordis.patch.yml into the profile's node_modules/@deepseek-ai/dsh-read-image).
License
MIT
nexu-io/open-design
freestylefly/awesome-gpt-image-2
anywhere-labs/dsh-desktop
walkinglabs/learn-harness-engineering
awesome-dsh-plugin/awesome-dsh-plugin
MemTensor/MemOS