chat-deepseek-vision
A native DeepSeek Harness (DSH) Cordis plugin that analyzes images through the reverse-engineered chat.deepseek.com vision mode (model_type=vision) — free, no third-party vision API key required. DeepSeek Harness(DSH)原生 Cordis 插件:通过逆向 chat.deepseek.com 识图模式(model_type=vision)分析图片,免费、无需第三方视觉 API key。
- Stars
- 1
- Language
- JavaScript
- Created
- Aug 18, 2026
- Updated
- Aug 18, 2026
Introduction
English | 中文
chat-deepseek-vision
A native DeepSeek Harness (DSH) Cordis plugin that analyzes images through the reverse-engineered chat.deepseek.com vision mode (
model_type=vision) — free, no third-party vision API key required.
- No stdio/MCP bridge (replaces the old
@deepseek-ai/dsh-mcp-client+node dist/index.jssetup) - Tools are registered directly into the current agent's tool registry, isomorphic with the official
@deepseek-ai/dsh-tool-*plugins - Pure ESM JavaScript with zero runtime assets (the official PoW wasm is embedded as base64), no build step
Tools
| Tool | Description |
|---|---|
analyze_image | Analyze an existing image (local path / http(s) URL / data URI) via chat.deepseek.com vision mode, returning a text description |
analyze_attachment | Analyze an image attached in the send box / session (by attachment_id, with a custom prompt for deep-dive analysis) |
describe_screen | Capture the screen and analyze it (full / primary / specific window; captured in the background without switching windows) |
take_screenshot | Capture the screen and save it only (no analysis) |
list_windows | List the titles of all visible windows |
dsv_status | Plugin self-check (masked token, endpoint, timeout, screenshot dir, attachment auto-describe toggle) + DeepSeek Web connectivity check |
Screenshots rely on Windows PowerShell (CopyFromScreen / GDI BitBlt / PrintWindow three-method fallback). Video/audio capabilities are outside the "analyze images via chat.deepseek.com" scope and are not included in this plugin.
Send-box Attachment Images (Direct Support)
Users can attach images directly in the send box (drag & drop / paste / file picker) — no file path needed:
-
Admission pass-through: DSH's image-attachment admission (the
promptentry) requires the current model to declareimageinput, otherwise it rejects the request outright (MODEL_DOES_NOT_SUPPORT_IMAGES, shown as "the current model does not support images"). The official DeepSeek adapter hardcodesinputModalities: ["text"]inresolveModelInfowith no config override, so this plugin installs a capability-declaration patch (lib/model.js): fordeepseek*routes only, it appends"image"to the returnedresolveModelInfomodalities, letting attachment admission pass. The patch changes only the declaration, never any real request; the original method is restored when the plugin is disposed. -
Auto-describe (
agent/pre-stephook):imageblocks in session messages are projected to text placeholders (the placeholder is rendered by the plugin as[图片附件 id=sha256:... name=... WxH]— Chinese by design, carrying the attachment id; the DeepSeek adapter never receives an image block), while the plugin automatically runs chat.deepseek.com vision and injects the description as a user message:<attachment-image id="sha256:..." name="photo.png" mediaType="image/png" width="1200" height="900"> This image is ... (full description) </attachment-image>The model can answer directly from the description; the same attachment is only analyzed once per session (durable marker + in-process cache).
-
Deep-dive analysis: the model can call the
analyze_attachmenttool with anidfor custom analysis (extract text/data, compare details, translate, etc.). -
Native image models: when using a model that genuinely accepts images (e.g. a pi-ai vision model), set
nativeImageModels: true— the plugin then skips projection/description when the model declares image input, letting the native image pipeline handle it. -
Disable auto-describe: set
autoDescribe: false(theanalyze_attachmentmanual tool remains available).
Note: after projection, the original image thumbnail position in the user message shows the attachment placeholder text (consistent with DSH's policy for MCP image results with text-only models); the attachment bytes themselves remain stored as session attachments and can be re-analyzed anytime via
analyze_attachment.
How It Works
Pure HTTP calls against chat.deepseek.com internal endpoints (no browser):
POST /api/v0/chat_session/create → chat_session_id
POST /api/v0/chat/create_pow_challenge → PoW challenge (DeepSeekHashV1)
solve PoW locally (bundled official sha3_wasm_bg.wasm, 26KB, zero imports)
POST /api/v0/file/upload_file (multipart) → file_id (x-ds-pow-response header)
GET /api/v0/file/fetch_files → poll until status == SUCCESS
POST /api/v0/chat/completion (SSE stream) → reply text (model_type="vision")
POST /api/v0/chat_session/delete → delete session after use
⚠️ Risk notice: this is a reverse-engineered, non-public interface for personal research only. DeepSeek may change the protocol or flag accounts at any time; evaluate the risk yourself. When the algorithm changes, replace
wasm/sha3_wasm_bg.wasmand runnpm run embed:wasm.
Configuration
Plugin config comes from the loader entry's config; unset fields fall back to the same-named environment variables:
| Plugin config | Env var | Default | Description |
|---|---|---|---|
token | DSW_TOKEN | - | DeepSeek Web login token (64 chars, see below) |
cookie | DSW_COOKIE | - | Session cookie (e.g. ds_session_id=..., optional) |
baseUrl | DSW_BASE_URL | https://chat.deepseek.com | DeepSeek Web endpoint |
timeoutMs | VISION_TIMEOUT_MS | 180000 | SSE idle timeout (ms): measured as "no new data" duration, so long outputs are not killed by a total-time cap |
screenshotDir | VISION_SCREENSHOT_DIR | ~/Pictures/Screenshots | Screenshot save directory |
autoDescribe | - | true | Auto-describe send-box attachments and inject the description; false keeps only the analyze_attachment manual tool |
attachmentPrompt | - | Default describe prompt | Custom prompt for auto-describing attachments |
nativeImageModels | - | false | When true, if the current model declares image input (e.g. pi-ai vision models) the plugin skips projection/description and uses the native image pipeline |
userAgent | - | Chrome 132 UA | Request UA (optional) |
Getting the token (64 chars):
- Log in to chat.deepseek.com in a browser
- F12 → Console, run:
JSON.parse(localStorage.getItem('userToken')).value - Fill the output into
token(orDSW_TOKEN)
Limits: images only (screenshots, local images, URLs, data URIs), single image ≤ 15MB.
Install into a DSH Profile
1. Install the plugin package into the profile
Run in the profile directory (dsh plugin forwards its arguments to pnpm):
dsh plugin --profile web add file:D:/mcp/chat-deepseek-vision
Equivalent to pnpm add file:D:/mcp/chat-deepseek-vision in %USERPROFILE%\.dsh\profiles\web.
2. Register the plugin in cordis.patch.yml
Edit %USERPROFILE%\.dsh\profiles\web\cordis.patch.yml and append a loader entry (token from the browser localStorage):
# chat-deepseek-vision: native DSH vision plugin (replaces the MCP deepseek-vision)
- insert:
- id: chat-deepseek-vision
name: chat-deepseek-vision
config:
token: 'your-64-char-token'
# cookie: 'ds_session_id=xxx; ...' # optional
# baseUrl: 'https://chat.deepseek.com'
# timeoutMs: 180000
You may also omit config and rely on the environment variables DSW_TOKEN/DSW_COOKIE (handier for headless/CI).
3. Restart DSH
After restart, verify: ask the agent to call dsv_status — "connected OK" means the install succeeded; analyze_image is ready to use.
Local Development
npm run smoke # smoke test: wasm/PoW, config resolution, resolveImage, plugin shape, screenshots, attachment projection/auto-describe
npm run embed:wasm # after DeepSeek updates the PoW algorithm, re-embed from wasm/sha3_wasm_bg.wasm
node scripts/smoke.mjs
Directory layout:
chat-deepseek-vision/
├── package.json # name: chat-deepseek-vision (peer: @deepseek-ai/cordis, @deepseek-ai/dsh-llm, @deepseek-ai/dsh-tools)
├── lib/
│ ├── index.js # Cordis plugin: name/inject/apply + 6 tool registrations + agent/pre-step attachment handling
│ ├── attachment.js # send-box attachments: image-block projection / auto-describe / analyze_attachment ref lookup
│ ├── model.js # capability-declaration patch: deepseek routes declare image (attachment admission pass-through)
│ ├── vision.js # facade: config resolution + resolveImage/analyzeImage(Buffer) + self-check
│ ├── deepseek-web.js # DeepSeekWebClient (session/PoW/upload/SSE, ported from client.ts)
│ ├── screen.js # screenshot tool logic (ported from tools.ts: describe_screen etc.)
│ ├── platform.js # screenshot & window enumeration (ported from platform.ts, PowerShell, execSync pipe capture)
│ ├── pow.js # PoW solver (wasm-bindgen calling convention, ported from pow.ts)
│ └── wasm-base64.js # generated: official sha3_wasm_bg.wasm embedded as base64
├── wasm/sha3_wasm_bg.wasm # official PoW wasm (update source)
└── scripts/
├── embed-wasm.mjs # regenerate wasm-base64.js
└── smoke.mjs # local smoke test (SMOKE_SCREENSHOT=1 also runs a real screen capture)
License
MIT