dsh-vision-router 1.4.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -22
- package/README.zh.md +64 -22
- package/docs/update-check.md +8 -6
- package/docs/update-check.zh-CN.md +8 -6
- package/entry.js +6 -4
- package/index.js +934 -217
- package/lib/catalog-corrections.js +278 -0
- package/lib/client.js +280 -75
- package/lib/replay-delegation.js +90 -0
- package/lib/self-update.js +135 -12
- package/lib/vision-resilience.js +395 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
18
|
-
<a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v1.4.
|
|
19
|
-
<a href="tests"><img src="https://img.shields.io/badge/verified-
|
|
18
|
+
<a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v1.4.2"><img src="https://img.shields.io/badge/release-v1.4.2-5B4CF0?style=flat-square" alt="Release v1.4.2" /></a>
|
|
19
|
+
<a href="tests"><img src="https://img.shields.io/badge/verified-252%20tests-2EA44F?style=flat-square" alt="Verified: 252 tests" /></a>
|
|
20
20
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat-square" alt="License: MIT" /></a>
|
|
21
21
|
<a href="package.json"><img src="https://img.shields.io/badge/Node.js-%3E%3D22-339933?style=flat-square&logo=nodedotjs&logoColor=white" alt="Node.js >=22" /></a>
|
|
22
22
|
<img src="https://img.shields.io/badge/runtime-no%20Python-8A2BE2?style=flat-square" alt="No Python" />
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
<p align="center">💬 <strong>QQ community group: 1105463028</strong></p>
|
|
29
29
|
|
|
30
30
|
> [!WARNING]
|
|
31
|
-
> 📌 **Announcement (v1.4.
|
|
31
|
+
> 📌 **Announcement (v1.4.2)**
|
|
32
32
|
>
|
|
33
|
-
> **v1.4.
|
|
33
|
+
> **v1.4.2 now supports** Oh-DSH Desktop — the plugin no longer races the stock DeepSeek route on the bundled DSH 0.1.0-rc.5 runtime (fixes "DSH runtime exited before readiness"), opencode-go qwen3.6-plus vision calls reach the correct Anthropic endpoint, and "+ Auto Vision" twins keep the picker's reasoning effort across multi-step turns.
|
|
34
34
|
|
|
35
35
|
<p align="center">
|
|
36
36
|
<img src="assets/vision-demo.gif" width="640" alt="Demo: paste an image, the agent locates the send button with vision_ground / vision_crop / vision_pixel_diff and answers with coordinates" />
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
|
|
41
41
|
- [Why this exists](#why-this-exists)
|
|
42
42
|
- [How it compares](#how-it-compares)
|
|
43
|
+
- [Acknowledgements](#acknowledgements)
|
|
43
44
|
- [Quick start](#quick-start)
|
|
44
45
|
- [Highlights](#highlights)
|
|
45
46
|
- [How it works](#how-it-works)
|
|
@@ -61,20 +62,41 @@ Most DSH vision plugins bridge images to DeepSeek as *text descriptions* — los
|
|
|
61
62
|
|
|
62
63
|
## How it compares
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
**One-line take**: most dsh vision plugins turn images into *text descriptions* for DeepSeek
|
|
66
|
+
(description bridge — lossy); this plugin hands the image turn *straight to a vision model*
|
|
67
|
+
(routing bridge — pixel-faithful), with a built-in keyless free fallback.
|
|
65
68
|
|
|
66
|
-
| |
|
|
67
|
-
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
69
|
+
| | Manual model switching | MCP vision bridge | dsh-vision-router |
|
|
70
|
+
|---|---|---|---|
|
|
71
|
+
| Pixel fidelity | ✅ full (when switched) | ❌ text description only | ✅ full, on the image turn |
|
|
72
|
+
| Automatic | ❌ | ✅ | ✅ |
|
|
73
|
+
| Daily model untouched | ❌ (whole session swapped) | ✅ | ✅ |
|
|
74
|
+
| Provider failure recovery | ❌ | ❌ | ✅ fallback chains |
|
|
75
|
+
| Reusable structured queries | — | partial | ✅ JSON mode + caching |
|
|
76
|
+
| Free out-of-the-box | ❌ | ❌ | ✅ built-in keyless endpoint |
|
|
77
|
+
| Fits dsh composition | — | external server | ✅ one plugin row |
|
|
78
|
+
|
|
79
|
+
**Difference from existing dsh community projects** (all excellent, each with its own focus; descriptions reflect their READMEs as of 2026-08):
|
|
76
80
|
|
|
77
|
-
|
|
81
|
+
| Project | Approach | What this plugin adds |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| [dsh-vision-sidecar](https://github.com/121103qwq/dsh-vision-sidecar) | Pre-describes images with an external VLM; the description joins the session as a message to DeepSeek; LLM7.io anonymous endpoint by default (OVHcloud listed as a no-key alternative) | Description bridge; this plugin adds raw-image routing, with `vision_describe` covering descriptions on demand |
|
|
84
|
+
| [dsh-vision-proxy](https://github.com/Flyvhidbwo/dsh-vision-proxy) | Wraps a provider route and transcribes images into text in the request stream | Transcription bridge; this plugin wraps no provider — it rewrites routing through `agent/request` waterfalls |
|
|
85
|
+
| [dsh-vision-provider](https://github.com/libinyam/dsh-vision-provider) | Registers `DeepSeek + Vision` combined routes: images are described by the chosen vision model before reaching DeepSeek | Two-model bridge idea; this plugin adds automatic routing, fallback chains and tools on top |
|
|
86
|
+
| [modlens](https://github.com/liustack/modlens) | The first dsh vision plugin; reuses local Claude Code/Codex/OpenCode/Pi logins as vision engines | Engine-reuse idea; this plugin ships its own provider chain and depends on no other local CLI |
|
|
87
|
+
| [dsh-vision-toolkit](https://github.com/Anionex/dsh-vision-toolkit) | Ten intent-aware visual tools (Q&A/OCR/pixel verification/UI restoration), called explicitly on demand | Broader tool set; this plugin adds whole-turn auto-routing and a keyless free fallback |
|
|
88
|
+
| [dsh-tool-vision](https://github.com/Scorp1o117/dsh-tool-vision) | An `inspect_image` tool plus an `agent/pre-step` waterfall bridge (pasted images become tool hints before entering the log) | Similar waterfall bridge; this plugin adds turn routing, fallback chains, caching and the free endpoint |
|
|
89
|
+
|
|
90
|
+
## Acknowledgements
|
|
91
|
+
|
|
92
|
+
This project borrows ideas from all of the above — especially the keyless free-endpoint
|
|
93
|
+
exploration (LLM7.io and OVHcloud anonymous tiers) by
|
|
94
|
+
[dsh-vision-sidecar](https://github.com/121103qwq/dsh-vision-sidecar). Thanks to the authors of
|
|
95
|
+
[dsh-vision-proxy](https://github.com/Flyvhidbwo/dsh-vision-proxy),
|
|
96
|
+
[dsh-vision-provider](https://github.com/libinyam/dsh-vision-provider),
|
|
97
|
+
[modlens](https://github.com/liustack/modlens),
|
|
98
|
+
[dsh-vision-toolkit](https://github.com/Anionex/dsh-vision-toolkit), and
|
|
99
|
+
[dsh-tool-vision](https://github.com/Scorp1o117/dsh-tool-vision).
|
|
78
100
|
|
|
79
101
|
## Quick start
|
|
80
102
|
|
|
@@ -176,7 +198,7 @@ Default `progressiveTools: false`: all eleven deep tools stay registered from pl
|
|
|
176
198
|
| `vision_ocr` | Text transcription: local tesseract (chi_sim+eng) first, vision model fallback | — |
|
|
177
199
|
| `vision_trace` | SVG vectorization (potrace posterization; icons/logos) | SVG |
|
|
178
200
|
| `vision_extract_foreground` | Cutout via border flood fill (uniform backgrounds) | transparent PNG |
|
|
179
|
-
| `vision_html_screenshot` | Screenshot a local HTML file (headless system Chrome) | PNG |
|
|
201
|
+
| `vision_html_screenshot` | Screenshot a local HTML file (headless system Chrome); `fullPage: true` captures the whole page and reports `pageHeight` | PNG |
|
|
180
202
|
| `vision_long_screenshot_ocr` | Long-screenshot transcription: overlapping chunks, tesseract first / vision model fallback, stitched Markdown | chunk PNGs + Markdown + manifest |
|
|
181
203
|
|
|
182
204
|
Formats are sniffed from magic bytes, so extensionless content-addressed attachment files work everywhere (no `.png` renaming needed).
|
|
@@ -194,6 +216,7 @@ vision_colors image="ref.png" top=8
|
|
|
194
216
|
vision_trace image="icon.png" steps=4
|
|
195
217
|
vision_extract_foreground image="logo.png"
|
|
196
218
|
vision_html_screenshot source="page.html" width=1200 height=720
|
|
219
|
+
vision_html_screenshot source="page.html" width=1200 height=720 fullPage=true
|
|
197
220
|
vision_long_screenshot_ocr image="chat-log.png" chunkHeight=1200 overlap=120
|
|
198
221
|
```
|
|
199
222
|
|
|
@@ -282,6 +305,7 @@ Everything is optional; defaults work out of the box. Edit via the Web card or a
|
|
|
282
305
|
| `timeoutMs` | `120000` | per vision call deadline |
|
|
283
306
|
| `artifactsDir` | `.dsh-vision-router/artifacts` | artifact directory (relative to the session workspace) |
|
|
284
307
|
| `proxy` / `proxyHosts` | `''` / openrouter hosts | optional proxy for vision provider hosts only |
|
|
308
|
+
| `catalogCorrections` | `true` | built-in catalog-routing corrections: when the installed pi-ai catalog routes a known model to the wrong wire protocol (e.g. `opencode-go/qwen3.6-plus` to OpenAI chat completions while OpenCode Go only serves it on `/v1/messages`), the plugin answers that backend directly over the corrected protocol. Each correction disarms itself once the catalog is fixed upstream |
|
|
285
309
|
|
|
286
310
|
## Requirements
|
|
287
311
|
|
|
@@ -316,6 +340,25 @@ npx @deepseek-ai/dsh --profile web --dump-config | grep vision-router
|
|
|
316
340
|
|
|
317
341
|
When first adding the plugin to an already long-lived Web profile, let that Web process reload the plugin bundle; the host discovers the browser bundle through `dsh.client` at startup. **After the plugin is loaded, model-catalog and wrapper-scope changes hot-update and do not require a restart.**
|
|
318
342
|
|
|
343
|
+
### Oh-DSH Desktop
|
|
344
|
+
|
|
345
|
+
[Oh-DSH Desktop](https://github.com/hust-open-atom-club/oh-dsh) ships its own packaged DSH runtime and its own home layout: the desktop surface runs the `desktop` profile under `~/.ohdsh` and does **not** load ordinary `~/.dsh` profiles. The `--profile web` commands above therefore install into the wrong environment on that product.
|
|
346
|
+
|
|
347
|
+
Install into the desktop profile by pointing `DSH_HOME` at the Oh-DSH home:
|
|
348
|
+
|
|
349
|
+
```sh
|
|
350
|
+
DSH_HOME=~/.ohdsh npx @deepseek-ai/dsh plugin --profile desktop add dsh-vision-router
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
(Windows PowerShell: run `$env:DSH_HOME = "$env:USERPROFILE\.ohdsh"` first, then the same command.)
|
|
354
|
+
|
|
355
|
+
> [!WARNING]
|
|
356
|
+
> Oh-DSH Desktop ≤ 0.1.5 bundles DSH `0.1.0-rc.5`. `dsh-vision-router` v1.4.1 and earlier crash that runtime at startup (`configurable provider "deepseek-official" is already declared`, surfacing as `DSH runtime exited before readiness`). Install v1.4.2+.
|
|
357
|
+
|
|
358
|
+
If a broken install already keeps the Desktop from starting, open `~/.ohdsh/profiles/desktop/package.json`, remove the `dsh-vision-router` entry from both `dependencies` and `dsh.profile.bundles`, save, and restart the Desktop.
|
|
359
|
+
|
|
360
|
+
Oh-DSH Desktop's built-in plugin marketplace (search → prepare → isolated preview → apply, with a `previous` snapshot for recovery) also works once the community catalog lists this plugin; do not mix marketplace installs with the direct command above. The bundled `@oh-dsh/vision` (`view_image`) coexists with this plugin — the tool names do not collide.
|
|
361
|
+
|
|
319
362
|
### Disable / re-enable
|
|
320
363
|
|
|
321
364
|
```yaml
|
|
@@ -328,16 +371,17 @@ Set it back to `false` to re-enable. Unloading removes the wrapper routes, tools
|
|
|
328
371
|
### Upgrade
|
|
329
372
|
|
|
330
373
|
```sh
|
|
331
|
-
# normal npm/npx install
|
|
332
|
-
|
|
374
|
+
# normal npm/npx install — install the version you want explicitly; a bare
|
|
375
|
+
# `update` is silently held back for releases younger than 24h (pnpm v11)
|
|
376
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-vision-router@<version>
|
|
333
377
|
|
|
334
378
|
# DeepSeek Harness source checkout
|
|
335
|
-
pnpm dsh plugin --profile web
|
|
379
|
+
pnpm dsh plugin --profile web add dsh-vision-router@<version>
|
|
336
380
|
```
|
|
337
381
|
|
|
338
|
-
Settings live in the profile's settings provider and survive upgrades.
|
|
382
|
+
Settings live in the profile's settings provider and survive upgrades. The settings card's one-click update installs the registry-confirmed version explicitly and verifies the installed manifest afterwards — it never reports success on a package-manager exit code alone.
|
|
339
383
|
|
|
340
|
-
> **A fresh release does not take effect (`downloaded 0` / `added 0`):** pnpm v11 holds versions younger than 24h back; `npx dsh-vision-router repair` fixes the stale version-pinned profile exemption so updates take effect immediately.
|
|
384
|
+
> **A fresh release does not take effect (`downloaded 0` / `added 0`):** pnpm v11 holds versions younger than 24h back; install the target version explicitly as above (pnpm auto-exempts it), or `npx dsh-vision-router repair` fixes the stale version-pinned profile exemption so updates take effect immediately.
|
|
341
385
|
|
|
342
386
|
> **Upgrading from a pre-bundle-patch install (v0.x):** the package now mounts
|
|
343
387
|
> itself through its own bundle patch, so a leftover manual row in
|
package/README.zh.md
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
18
|
-
<a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v1.4.
|
|
19
|
-
<a href="tests"><img src="https://img.shields.io/badge/verified-
|
|
18
|
+
<a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v1.4.2"><img src="https://img.shields.io/badge/release-v1.4.2-5B4CF0?style=flat-square" alt="Release v1.4.2" /></a>
|
|
19
|
+
<a href="tests"><img src="https://img.shields.io/badge/verified-252%20tests-2EA44F?style=flat-square" alt="Verified: 252 tests" /></a>
|
|
20
20
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat-square" alt="License: MIT" /></a>
|
|
21
21
|
<a href="package.json"><img src="https://img.shields.io/badge/Node.js-%3E%3D22-339933?style=flat-square&logo=nodedotjs&logoColor=white" alt="Node.js >=22" /></a>
|
|
22
22
|
<img src="https://img.shields.io/badge/runtime-no%20Python-8A2BE2?style=flat-square" alt="No Python" />
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
<p align="center">💬 <strong>QQ 用户交流群:1105463028</strong></p>
|
|
29
29
|
|
|
30
30
|
> [!WARNING]
|
|
31
|
-
> 📌 **公告(v1.4.
|
|
31
|
+
> 📌 **公告(v1.4.2)**
|
|
32
32
|
>
|
|
33
|
-
> **v1.4.0
|
|
33
|
+
> **v1.4.2 现已支持**:Oh-DSH Desktop 兼容——在内置的 DSH 0.1.0-rc.5 上不再与官方 DeepSeek 路由竞争导致启动崩溃(修复「DSH runtime exited before readiness」);opencode-go qwen3.6-plus 视觉调用走正确的 Anthropic 端点;「+ 自动识图」twin 组在多步对话中保留选择器里的推理等级。
|
|
34
34
|
|
|
35
35
|
<p align="center">
|
|
36
36
|
<img src="assets/vision-demo.gif" width="640" alt="演示:粘贴图片,Agent 用 vision_ground / vision_crop / vision_pixel_diff 定位发送按钮并给出坐标" />
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
|
|
41
41
|
- [为什么做这个](#为什么做这个)
|
|
42
42
|
- [对比同类插件](#对比同类插件)
|
|
43
|
+
- [致谢](#致谢)
|
|
43
44
|
- [快速开始](#快速开始)
|
|
44
45
|
- [亮点](#亮点)
|
|
45
46
|
- [工作原理](#工作原理)
|
|
@@ -61,20 +62,39 @@
|
|
|
61
62
|
|
|
62
63
|
## 对比同类插件
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
**一句话讲清区别**:其他 dsh 视觉插件大多"把图片转成文字描述再喂给 DeepSeek"(描述桥,有信息损耗);
|
|
66
|
+
本插件主打"**图片轮直接交给视觉模型看原图**"(路由桥,像素保真),同时内置免 Key 免费模型兜底。
|
|
65
67
|
|
|
66
|
-
| |
|
|
67
|
-
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
68
|
+
| | 手动切换模型 | MCP 视觉桥 | 本插件 |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| 像素保真 | ✅ 完整(切换后) | ❌ 只有文字描述 | ✅ 完整,图片轮内 |
|
|
71
|
+
| 自动化 | ❌ | ✅ | ✅ |
|
|
72
|
+
| 日常模型不受影响 | ❌(整会话被换) | ✅ | ✅ |
|
|
73
|
+
| 供应商失败恢复 | ❌ | ❌ | ✅ 降级链 |
|
|
74
|
+
| 可复用的结构化查询 | — | 部分 | ✅ JSON 模式 + 缓存 |
|
|
75
|
+
| 免费开箱即用 | ❌ | ❌ | ✅ 内置免 Key 免费端点 |
|
|
76
|
+
| 贴合 dsh 组合体系 | — | 外部服务器 | ✅ 一行插件行 |
|
|
77
|
+
|
|
78
|
+
**与现有 dsh 社区方案的差异**(均为优秀项目,各有侧重;描述以各家 README 2026-08 状态为准):
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
| 项目 | 思路 | 本插件的差异 |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| [dsh-vision-sidecar](https://github.com/121103qwq/dsh-vision-sidecar) | 图片先经外部 VLM 做 OCR/描述,描述作为会话消息交给 DeepSeek;默认 LLM7.io 匿名端点(OVHcloud 为无 Key 备选) | 描述桥方案;本插件提供"原图直看"路由,描述能力由 `vision_describe` 按需替代 |
|
|
83
|
+
| [dsh-vision-proxy](https://github.com/Flyvhidbwo/dsh-vision-proxy) | 包装 provider 路由,请求流里把图片转译成文本再交给 DeepSeek | 转译桥方案;本插件不包装 provider,通过 `agent/request` 瀑布改写路由 |
|
|
84
|
+
| [dsh-vision-provider](https://github.com/libinyam/dsh-vision-provider) | 注册 `DeepSeek + Vision` 组合路由:图片先经所选视觉模型转成描述,再交给 DeepSeek | 双模型桥思路;本插件在此基础上增加自动路由、降级链与工具 |
|
|
85
|
+
| [modlens](https://github.com/liustack/modlens) | 最早的 dsh 视觉插件;复用本机 Claude Code/Codex/OpenCode/Pi 等登录态作为视觉引擎 | 引擎复用思路;本插件自带供应商链,不依赖本机其他 CLI |
|
|
86
|
+
| [dsh-vision-toolkit](https://github.com/Anionex/dsh-vision-toolkit) | 10 个意图化视觉工具(Q&A/OCR/像素校验/UI 还原),按需显式调用 | 工具集更全;本插件多出整轮自动路由与免 Key 免费兜底 |
|
|
87
|
+
| [dsh-tool-vision](https://github.com/Scorp1o117/dsh-tool-vision) | `inspect_image` 工具 + `agent/pre-step` 瀑布图片桥(粘贴图入日志前转成工具提示) | 瀑布桥思路相近;本插件多出轮次路由、降级链、缓存与免费端点 |
|
|
88
|
+
|
|
89
|
+
## 致谢
|
|
90
|
+
|
|
91
|
+
本插件借鉴了以上全部社区项目的思路,特别是 [dsh-vision-sidecar](https://github.com/121103qwq/dsh-vision-sidecar)
|
|
92
|
+
对免注册免 Key 视觉端点的探索(LLM7.io 与 OVHcloud 匿名层)。感谢
|
|
93
|
+
[dsh-vision-proxy](https://github.com/Flyvhidbwo/dsh-vision-proxy)、
|
|
94
|
+
[dsh-vision-provider](https://github.com/libinyam/dsh-vision-provider)、
|
|
95
|
+
[modlens](https://github.com/liustack/modlens)、
|
|
96
|
+
[dsh-vision-toolkit](https://github.com/Anionex/dsh-vision-toolkit)、
|
|
97
|
+
[dsh-tool-vision](https://github.com/Scorp1o117/dsh-tool-vision) 作者们的探索。
|
|
78
98
|
|
|
79
99
|
## 快速开始
|
|
80
100
|
|
|
@@ -176,7 +196,7 @@ Agent 仅根据参考图复刻 UI,再用 `vision_pixel_diff` 验证最终结
|
|
|
176
196
|
| `vision_ocr` | 文字转写:本地 tesseract(中英)优先,视觉模型兜底 | — |
|
|
177
197
|
| `vision_trace` | SVG 矢量化(potrace 分色;图标/logo) | SVG |
|
|
178
198
|
| `vision_extract_foreground` | 边界洪泛抠图(纯色背景) | 透明 PNG |
|
|
179
|
-
| `vision_html_screenshot` | 给本地 HTML 文件截图(无头系统 Chrome
|
|
199
|
+
| `vision_html_screenshot` | 给本地 HTML 文件截图(无头系统 Chrome);`fullPage: true` 截整页并返回 `pageHeight` | PNG |
|
|
180
200
|
| `vision_long_screenshot_ocr` | 长截图转写:重叠分片,tesseract 优先 / 视觉模型回退,按序拼接 Markdown | 分片 PNG + Markdown + manifest |
|
|
181
201
|
|
|
182
202
|
图片格式按**魔数识别**,无扩展名的内容寻址附件文件也能直接用(不用再复制成 `.png`)。
|
|
@@ -194,6 +214,7 @@ vision_colors image="ref.png" top=8
|
|
|
194
214
|
vision_trace image="icon.png" steps=4
|
|
195
215
|
vision_extract_foreground image="logo.png"
|
|
196
216
|
vision_html_screenshot source="page.html" width=1200 height=720
|
|
217
|
+
vision_html_screenshot source="page.html" width=1200 height=720 fullPage=true
|
|
197
218
|
vision_long_screenshot_ocr image="chat-log.png" chunkHeight=1200 overlap=120
|
|
198
219
|
```
|
|
199
220
|
|
|
@@ -282,6 +303,7 @@ Web 配置页在 **设置 → 插件 → 插件配置** 下注册「视觉路由
|
|
|
282
303
|
| `timeoutMs` | `120000` | 单次视觉调用超时 |
|
|
283
304
|
| `artifactsDir` | `.dsh-vision-router/artifacts` | 产物目录(相对会话工作区) |
|
|
284
305
|
| `proxy` / `proxyHosts` | `''` / openrouter 域名 | 仅视觉供应商域名可选的本地代理 |
|
|
306
|
+
| `catalogCorrections` | `true` | 内置目录纠错:当已安装的 pi-ai 目录把已知模型路由到错误协议时(例如 `opencode-go/qwen3.6-plus` 被指向 OpenAI chat completions,而 OpenCode Go 只在 `/v1/messages` 上提供该模型),插件直接按正确协议应答该后端;上游目录修复后每条纠错自动失效 |
|
|
285
307
|
|
|
286
308
|
## 环境要求
|
|
287
309
|
|
|
@@ -316,6 +338,25 @@ npx @deepseek-ai/dsh --profile web --dump-config | grep vision-router
|
|
|
316
338
|
|
|
317
339
|
首次把插件装进已经长期运行的 Web profile 时,需要让 Web 进程重新加载插件本体;宿主在启动时通过 `dsh.client` 声明发现浏览器端包。**插件加载完成后,模型目录与包装范围的变化会热更新,不需要为这些变化重启。**
|
|
318
340
|
|
|
341
|
+
### Oh-DSH Desktop
|
|
342
|
+
|
|
343
|
+
[Oh-DSH Desktop](https://github.com/hust-open-atom-club/oh-dsh) 自带一套独立打包的 DSH 运行时和独立的数据目录:桌面端实际运行的是 `~/.ohdsh` 下的 `desktop` profile,**不会**加载普通 `~/.dsh` 的 profile。因此上面 `--profile web` 的命令在 Oh-DSH Desktop 上会装错环境。
|
|
344
|
+
|
|
345
|
+
把 `DSH_HOME` 指向 Oh-DSH 的数据目录再安装即可:
|
|
346
|
+
|
|
347
|
+
```sh
|
|
348
|
+
DSH_HOME=~/.ohdsh npx @deepseek-ai/dsh plugin --profile desktop add dsh-vision-router
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
(Windows PowerShell 先执行 `$env:DSH_HOME = "$env:USERPROFILE\.ohdsh"`,再运行同一命令。)
|
|
352
|
+
|
|
353
|
+
> [!WARNING]
|
|
354
|
+
> Oh-DSH Desktop ≤ 0.1.5 内置的是 DSH `0.1.0-rc.5`。`dsh-vision-router` v1.4.1 及更早版本会让该运行时在启动时崩溃(报 `configurable provider "deepseek-official" is already declared`,在 Oh-DSH Desktop 里表现为 `DSH runtime exited before readiness`)。请安装 v1.4.2+。
|
|
355
|
+
|
|
356
|
+
如果错误安装已经导致 Desktop 无法启动:打开 `~/.ohdsh/profiles/desktop/package.json`,从 `dependencies` 和 `dsh.profile.bundles` 中删掉 `dsh-vision-router` 条目,保存后重启 Desktop。
|
|
357
|
+
|
|
358
|
+
Oh-DSH Desktop 内置的插件市场(搜索 → 准备 → 隔离预览 → 应用,并保留 `previous` 快照用于恢复)在社区目录收录本插件后同样可用;不要与上面的直接安装命令混用。其内置的 `@oh-dsh/vision`(`view_image`)与本插件可共存,工具名不冲突。
|
|
359
|
+
|
|
319
360
|
### 禁用 / 恢复
|
|
320
361
|
|
|
321
362
|
```yaml
|
|
@@ -328,16 +369,17 @@ npx @deepseek-ai/dsh --profile web --dump-config | grep vision-router
|
|
|
328
369
|
### 升级
|
|
329
370
|
|
|
330
371
|
```sh
|
|
331
|
-
# 普通 npm / npx 安装
|
|
332
|
-
|
|
372
|
+
# 普通 npm / npx 安装 —— 显式安装目标版本;裸 `update` 会被 pnpm v11
|
|
373
|
+
# 静默拦下发布不足 24 小时的新版本
|
|
374
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-vision-router@<版本号>
|
|
333
375
|
|
|
334
376
|
# DeepSeek Harness 源码仓库
|
|
335
|
-
pnpm dsh plugin --profile web
|
|
377
|
+
pnpm dsh plugin --profile web add dsh-vision-router@<版本号>
|
|
336
378
|
```
|
|
337
379
|
|
|
338
|
-
设置存放在 profile
|
|
380
|
+
设置存放在 profile 的设置提供方里,升级不丢失。设置卡里的一键更新会自动显式安装 registry 已确认的版本,并在命令结束后核对实际安装版本——绝不只凭包管理器退出码就报成功。
|
|
339
381
|
|
|
340
|
-
> **新版本一直不生效(`downloaded 0` / `added 0`):** pnpm v11 会拦下发布不足 24
|
|
382
|
+
> **新版本一直不生效(`downloaded 0` / `added 0`):** pnpm v11 会拦下发布不足 24 小时的版本;按上面方式显式安装目标版本(pnpm 会自动写入豁免),或运行 `npx dsh-vision-router repair` 修复过期的带版本号豁免条目后,更新立即生效。
|
|
341
383
|
|
|
342
384
|
> **从 bundle 补丁之前(v0.x)升级:** 现在插件由自带的 bundle 补丁自动挂载,
|
|
343
385
|
> 若 `~/.dsh/profiles/<profile>/cordis.patch.yml` 里还残留旧版手动行,会与之
|
package/docs/update-check.md
CHANGED
|
@@ -18,25 +18,27 @@ DSH and the plugin may have been launched through different paths, including `np
|
|
|
18
18
|
When an update is available, the plugin inspects the CLI entry of the current process. One-click update is enabled only when that entry can be traced to a real `@deepseek-ai/dsh` package and can be executed safely by the current Node runtime. In that case Vision Router runs the documented DSH updater through the **same DSH CLI that is already hosting the plugin**:
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
|
-
dsh plugin --profile <current-profile>
|
|
21
|
+
dsh plugin --profile <current-profile> add dsh-vision-router@<latest>
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
The
|
|
24
|
+
The registry-confirmed target version is installed explicitly rather than through a bare `update`. This matters because pnpm 11 applies `minimumReleaseAge` (default 1440 minutes): a plain `pnpm update` silently keeps the current version while every candidate release is younger than 24h and still exits 0 ("Already up to date") — a false-success update that leaves the old version running after restart. `add <name>@<version>` installs the confirmed release (pnpm auto-exempts the requested version from the policy when needed). For non-registry installs (git/file/link/workspace specs) the updater keeps `update` semantics and only verifies the result.
|
|
25
|
+
|
|
26
|
+
The subprocess uses `execFile` with `shell: false`; no shell command is constructed from browser input. The update endpoint also requires a process-local token returned by the same-origin update-check endpoint. After the updater exits, the plugin reads the `dsh-vision-router` manifest under the profile's `node_modules` and verifies that the installed version actually reached the target — **a zero exit code alone is never reported as success**. Only a verified update asks the user to restart DSH so the new plugin bundle is loaded.
|
|
25
27
|
|
|
26
28
|
If the CLI cannot be verified — for example a raw TypeScript source entry that needs a workspace-specific loader — the one-click button is not offered. This commonly applies to a DSH source checkout launched with `pnpm dsh`: version checking still works, but updating remains under the source workspace's own pnpm workflow. The card keeps the version information and release-notes link and tells the user to update through their original DSH installation path instead.
|
|
27
29
|
|
|
28
30
|
## Manual recovery
|
|
29
31
|
|
|
30
|
-
If automatic update is unavailable, the version check fails, or a one-click update fails, the settings card still shows direct Project/Releases links and a manual command. For a DeepSeek Harness source checkout run:
|
|
32
|
+
If automatic update is unavailable, the version check fails, or a one-click update fails, the settings card still shows direct Project/Releases links and a manual command. When a newer version is known, the shown commands install that version explicitly, which bypasses the release-age withholding described above. For a DeepSeek Harness source checkout run:
|
|
31
33
|
|
|
32
34
|
```sh
|
|
33
|
-
pnpm dsh plugin --profile web
|
|
35
|
+
pnpm dsh plugin --profile web add dsh-vision-router@<latest>
|
|
34
36
|
```
|
|
35
37
|
|
|
36
38
|
For normal npm/npx DSH usage run:
|
|
37
39
|
|
|
38
40
|
```sh
|
|
39
|
-
npx @deepseek-ai/dsh plugin --profile web
|
|
41
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-vision-router@<latest>
|
|
40
42
|
```
|
|
41
43
|
|
|
42
|
-
The settings card substitutes the active profile when it can determine one.
|
|
44
|
+
The settings card substitutes the active profile when it can determine one. If the version still does not change after an update command, check the profile's `pnpm-workspace.yaml` for a version-pinned `minimumReleaseAgeExclude` entry — `npx dsh-vision-router repair` rewrites stale pins to bare names so future releases resolve again (see `docs/doctor.md`).
|
|
@@ -18,25 +18,27 @@ Vision Router 会检查是否有新的已发布版本;当当前运行中的 DS
|
|
|
18
18
|
发现新版本后,插件会检查当前进程真正使用的 DSH CLI 入口。只有该入口能够向上验证到真实的 `@deepseek-ai/dsh` 包,并且可以由当前 Node 运行时安全执行时,设置卡才显示“一键更新”。此时调用的不是某个猜出来的包管理器,而是**当前正在托管插件的同一套 DSH CLI**:
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
|
-
dsh plugin --profile <当前 profile>
|
|
21
|
+
dsh plugin --profile <当前 profile> add dsh-vision-router@<最新版>
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
这里会**显式安装 registry 已确认的目标版本**,而不是裸 `update`。原因是 pnpm 11 默认启用 `minimumReleaseAge`(1440 分钟):当候选新版本发布不足 24 小时时,裸 `pnpm update` 会静默保留当前版本并仍然以退出码 0 结束(输出 “Already up to date”)——这就是“点了更新、提示成功、重启后版本没变”的假成功。`add <包名>@<版本>` 会安装确认过的发布版(pnpm 需要时会自动为新版本写入策略豁免)。对于非 registry 安装(git / file / link / workspace 规格),更新器保持 `update` 语义、只校验结果。
|
|
25
|
+
|
|
26
|
+
子进程通过 `execFile` 且 `shell: false` 启动,不会把浏览器输入拼成 shell 命令。更新接口还要求由同源更新检查接口返回的本进程临时 token,避免网页跨站请求直接触发更新。更新命令退出后,插件会读取 profile `node_modules` 下 `dsh-vision-router` 的清单并核对安装版本确实达到目标——**仅凭退出码 0 永远不会被当作成功**。只有校验通过的更新才会提示用户重启 DSH,让新插件 bundle 真正加载。
|
|
25
27
|
|
|
26
28
|
若无法可靠验证当前 CLI——例如直接运行需要 workspace 专用 loader 的 TypeScript 源码入口——就不会显示一键更新按钮。**源码仓库里通过 `pnpm dsh` 启动通常属于这种情况:版本检查仍然可以正常工作,只是一键更新继续交给源码工作区自己的 pnpm 流程。** 此时仍会显示当前/最新版本和 Release Notes,并提示用户沿用原来的 DSH 安装方式手动更新。
|
|
27
29
|
|
|
28
30
|
## 手动兜底
|
|
29
31
|
|
|
30
|
-
如果自动更新不可用、版本检查失败,或一键更新失败,设置卡仍会直接显示项目主页 / Releases
|
|
32
|
+
如果自动更新不可用、版本检查失败,或一键更新失败,设置卡仍会直接显示项目主页 / Releases 入口和可执行的手动命令。发现新版本时,显示的命令会带版本号显式安装,从而绕过上面描述的发布龄拦截。DeepSeek Harness 源码仓库通过 pnpm 启动时使用:
|
|
31
33
|
|
|
32
34
|
```sh
|
|
33
|
-
pnpm dsh plugin --profile web
|
|
35
|
+
pnpm dsh plugin --profile web add dsh-vision-router@<最新版>
|
|
34
36
|
```
|
|
35
37
|
|
|
36
38
|
普通 npm / npx DSH 使用:
|
|
37
39
|
|
|
38
40
|
```sh
|
|
39
|
-
npx @deepseek-ai/dsh plugin --profile web
|
|
41
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-vision-router@<最新版>
|
|
40
42
|
```
|
|
41
43
|
|
|
42
|
-
如果插件能识别当前 profile,设置页会把命令里的 `web` 自动替换成实际 profile
|
|
44
|
+
如果插件能识别当前 profile,设置页会把命令里的 `web` 自动替换成实际 profile。若执行后版本仍未变化,请检查 profile 的 `pnpm-workspace.yaml` 里是否有版本钉住的 `minimumReleaseAgeExclude` 条目——`npx dsh-vision-router repair` 会把过期的钉住条目改写为裸名,让后续新版本恢复正常解析(见 `docs/doctor.md`)。
|
package/entry.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import z from '@deepseek-ai/schemastery'
|
|
10
10
|
import * as core from './index.js'
|
|
11
11
|
import { installVisionRouterFileLogging } from './lib/file-logger.js'
|
|
12
|
+
import { contextWithDelegatedReplay } from './lib/replay-delegation.js'
|
|
12
13
|
|
|
13
14
|
// Schemastery object schemas expose set() as the supported way to replace a
|
|
14
15
|
// field schema. This mutates the Config object that index.js itself later uses
|
|
@@ -21,13 +22,14 @@ export const Config = core.Config
|
|
|
21
22
|
|
|
22
23
|
// Defense in depth for direct/programmatic callers that invoke apply() without
|
|
23
24
|
// first running the Cordis Config resolver: only an explicit true enables the
|
|
24
|
-
// schema-changing progressive mode. The wrapped context changes
|
|
25
|
-
//
|
|
26
|
-
//
|
|
25
|
+
// schema-changing progressive mode. The wrapped context changes logger plus a
|
|
26
|
+
// private llm view used only by Vision Router: wrapper -> delegate calls can
|
|
27
|
+
// restore adapter-owned replay identity without mutating the host LLM service.
|
|
27
28
|
export function apply(ctx, config = {}) {
|
|
28
29
|
const logging = installVisionRouterFileLogging(ctx)
|
|
30
|
+
const runtimeCtx = contextWithDelegatedReplay(logging.ctx)
|
|
29
31
|
try {
|
|
30
|
-
const result = core.apply(
|
|
32
|
+
const result = core.apply(runtimeCtx, {
|
|
31
33
|
...config,
|
|
32
34
|
progressiveTools: config.progressiveTools === true,
|
|
33
35
|
})
|