dsh-vision-router 1.2.3 → 1.4.0

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 CHANGED
@@ -15,7 +15,7 @@
15
15
  </p>
16
16
 
17
17
  <p align="center">
18
- <a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v1.2.1"><img src="https://img.shields.io/badge/release-v1.2.1-5B4CF0?style=flat-square" alt="Release v1.2.1" /></a>
18
+ <a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v1.4.0"><img src="https://img.shields.io/badge/release-v1.4.0-5B4CF0?style=flat-square" alt="Release v1.4.0" /></a>
19
19
  <a href="tests"><img src="https://img.shields.io/badge/verified-149%20tests-2EA44F?style=flat-square" alt="Verified: 149 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&amp;logo=nodedotjs&amp;logoColor=white" alt="Node.js >=22" /></a>
@@ -28,18 +28,26 @@
28
28
  <p align="center">💬 <strong>QQ community group: 1105463028</strong></p>
29
29
 
30
30
  > [!WARNING]
31
- > 📌 **Announcement (v1.2.3)**
31
+ > 📌 **Announcement (v1.4.0)**
32
32
  >
33
- > v1.2.3 fixes DSH Desktop's re-appearing first-run dialog: the onboarding "seen" flag and the model-guide step now persist in the profile settings file instead of origin-scoped `localStorage`, which a random per-launch port (`--port 0`) wiped on every boot (issue #78).
34
- >
35
- > v1.2.2 closed the last attachment-id gap — ids announced for images the host persisted itself (e.g. `read_image` re-uploads, `sha256:…`) now resolve in `vision_describe` and every pixel tool (issue #72) — stopped `vision_present` and other tool-result image blocks from ever locking a text-model session with `UNSUPPORTED_CONTENT` (issue #74; already-locked sessions heal after upgrading), and warned loudly when a stale sharp left over from a pre-v1.2 upgrade would break the pixel tools with `colourspace: parameter space not set` (issue #75).
36
- >
37
- > v1.2.1 hardened the pixel loop: all eleven pixel tools now accept uploaded-image attachment ids directly (no more `cannot read …/sha256:…` round trips), artifact filenames carry collision-free fingerprints, `vision_ground` retries degenerate boxes, the model guide replays fully from step 1 (leaving the settings first), and the settings card scrolls smoothly even with hundreds of models per provider.
33
+ > **v1.4.0 now supports** automatic recognition and direct-channel bridging of undeclared vision models, doctor repair of stale version-pinned exemptions, and a spotlight-guided onboarding walkthrough — plus hardened settings-save verification and vision-backend compatibility.
38
34
 
39
35
  <p align="center">
40
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" />
41
37
  </p>
42
38
 
39
+ ## Contents
40
+
41
+ - [Why this exists](#why-this-exists)
42
+ - [How it compares](#how-it-compares)
43
+ - [Quick start](#quick-start)
44
+ - [Highlights](#highlights)
45
+ - [How it works](#how-it-works)
46
+ - [Tools](#tools)
47
+ - [Configuration](#configuration)
48
+ - [Install and lifecycle](#install-and-lifecycle)
49
+ - [Troubleshooting](#troubleshooting)
50
+
43
51
  ## Why this exists
44
52
 
45
53
  Most DSH vision plugins bridge images to DeepSeek as *text descriptions* — lossy, one-shot, and blind to pixels. This plugin keeps the **original pixels on the vision model's side** and DeepSeek on the reasoning side, and makes looking at an image an **ordinary tool call**:
@@ -70,24 +78,25 @@ Both are MIT-licensed and one command away. Pick this plugin when you want image
70
78
 
71
79
  ## Quick start
72
80
 
73
- ### 1. Install and load the plugin
81
+ ### 1. Install the plugin
74
82
 
75
- Recommended for normal npm/npx installs (the same launch style used by the DSH README):
83
+ For normal npm/npx installs, installation is a single command:
76
84
 
77
85
  ```sh
78
86
  npx @deepseek-ai/dsh plugin --profile web add dsh-vision-router
79
- npx @deepseek-ai/dsh web
80
87
  ```
81
88
 
89
+ > [!NOTE]
90
+ > Third-party `dsh-web-plugin-manager` / `dshpm` **v0.4.2+** is also compatible: its quality gate now correctly allows `@deepseek-ai/schemastery` as a runtime dependency. The official DSH CLI above remains the recommended install path.
91
+
82
92
  If you run DeepSeek Harness from a source checkout with pnpm, use the workspace script instead — `dsh` is not necessarily on your shell `PATH`:
83
93
 
84
94
  ```sh
85
95
  cd deepseek-harness
86
96
  pnpm dsh plugin --profile web add dsh-vision-router
87
- pnpm dsh web
88
97
  ```
89
98
 
90
- If you already installed the DSH CLI globally and `dsh` is on `PATH`, the shorter `dsh ...` form works too.
99
+ If you already installed the DSH CLI globally and `dsh` is on `PATH`, the shorter `dsh ...` form works too. After installation, start or reload DSH Web as you normally do.
91
100
 
92
101
  > [!NOTE]
93
102
  > If you install the plugin **into a Web process that was already running long-term**, let that DSH Web process reload once so the plugin bundle itself is discovered. After the plugin is loaded, adding/removing models or changing wrapper scope **hot-updates without further DSH restarts**.
@@ -110,7 +119,7 @@ The auto-vision group follows the live DSH model catalog. Adding models or chang
110
119
 
111
120
  ### 3. Paste or upload the image
112
121
 
113
- After choosing the “+ Auto Vision” group, paste or upload an image normally. The agent auto-mounts the vision tools and can use `vision_describe`, `vision_ground`, `vision_crop`, and the rest across multiple steps when needed.
122
+ After choosing the “+ Auto Vision” group, paste or upload an image normally. By default the complete vision tool schema is stable from session start, so the agent can immediately use `vision_describe`, `vision_ground`, `vision_crop`, and the rest across multiple steps when needed.
114
123
 
115
124
  The built-in anonymous OVH vision fallback is already configured, so normal image use needs no signup or API key. **The lower-right chat picker selects only the brain/conversation model**; vision backends do not belong there. Advanced options live under **Settings → Plugins → Plugin config → 视觉路由(自动识图)**: each vision-backend row selects one image-capable user model already configured under **Settings → Models**. Leaving every user row empty is valid; the OVH chain remains the final fallback. `Vision HTTP` is an internal transport route, not a model group users should select.
116
125
 
@@ -129,7 +138,7 @@ The built-in anonymous OVH vision fallback is already configured, so normal imag
129
138
  - **Automatic failover with classified errors.** Region blocks, ToS filtering, 402 quota, 429 rate limits (with Retry-After backoff), context overflow, network failures — the chain walks providers one by one and only reports after all of them failed, with actionable advice.
130
139
  - **Image memory.** Vision answers are cached by attachment content hash; later text turns substitute the recorded description (marked as untrusted evidence), so DeepSeek genuinely remembers earlier images without re-spending vision calls.
131
140
  - **A verifiable pixel loop.** Reference → `vision_html_screenshot` → `vision_pixel_diff` (ratio + red heatmap + worst-region ranking) → fix → repeat until the mismatch converges. UI restoration becomes measurable instead of eyeballed.
132
- - **Progressive schema exposure.** Only a zero-arg `vision_activate` bootstrap is always visible; image turns auto-mount all eleven deep tools with a one-time usage note, and a `vision-tools` skill is registered for text-only turns.
141
+ - **Stable tool schema.** All eleven deep tools are registered from session start by default, avoiding a mid-conversation tool-list expansion that can invalidate long-context KV/prefix caches. `progressiveTools: true` remains an advanced boot-time opt-in; only then does `vision_activate` mount the tools on demand. See [`docs/progressive-tools-cache.md`](docs/progressive-tools-cache.md).
133
142
  - **Selective proxy.** Only the configured vision provider hosts go through your local proxy; DeepSeek stays direct.
134
143
 
135
144
  ### Pixel loop in practice
@@ -150,7 +159,7 @@ The vision model is **only the eyes**; DeepSeek is **always the brain**. An imag
150
159
 
151
160
  ## Tools
152
161
 
153
- All eleven deep tools mount automatically on image turns (`autoActivateOnImage`); text turns can mount them via `vision_activate` or the `/vision-tools` skill. Built on sharp / potrace / tesseract / system Chrome — no Python:
162
+ Default `progressiveTools: false`: all eleven deep tools stay registered from plugin startup, so text and image turns can call them immediately. If you explicitly set `progressiveTools: true` in the profile/composition `cordis.patch.yml`, progressive mode is restored: only `vision_activate` is exposed initially, the full tool set mounts on first use, and the `vision-tools` skill is registered. This is a boot-time switch; restart DSH after changing it. Built on sharp / potrace / tesseract / system Chrome — no Python:
154
163
 
155
164
  <p align="center">
156
165
  <img src="assets/vision-tools.svg" width="100%" alt="Eleven vision tools available in DSH Vision Router." />
@@ -266,7 +275,7 @@ Everything is optional; defaults work out of the box. Edit via the Web card or a
266
275
  | `wrapperRoute` / `chainRoute` | `deepseek-vision` / `vision-chain` | admission wrapper route name / fallback chain route name (empty disables) |
267
276
  | `stealth` | `false` | take over the official `deepseek-official` route (official row only; custom routes are auto-wrapped by default) |
268
277
  | `textProvider` | `deepseek-official` / `deepseek-v4-pro` | the model that reasons (your daily model) |
269
- | `tool` / `progressiveTools` / `autoActivateOnImage` | `true` ×3 | vision tools on / progressive mounting / auto-mount on image turns |
278
+ | `tool` / `progressiveTools` / `autoActivateOnImage` | `true` / `false` / `true` | vision tools on / progressive mounting (off by default for a stable tool schema) / image-turn auto-mount when progressive mode is enabled; `progressiveTools` is boot-time config |
270
279
  | `rewriteImages` | `true` | rewrite image blocks in the model input (cached description or tool-hint marker); the UI log keeps images |
271
280
  | `downscale` / `downscaleMaxPixels` | `true` / `4000000` | pre-call downscale and its pixel budget (latency guard) |
272
281
  | `cache` / `cacheTtlSeconds` / `cacheMaxEntries` | `true` / `3600` / `200` | vision answer cache |
@@ -286,18 +295,23 @@ Everything is optional; defaults work out of the box. Edit via the Web card or a
286
295
 
287
296
  ### Install
288
297
 
289
- Normal npm/npx install:
298
+ Normal npm/npx install — one command:
290
299
 
291
300
  ```sh
292
301
  npx @deepseek-ai/dsh plugin --profile web add dsh-vision-router
293
- npx @deepseek-ai/dsh --profile web --dump-config | grep vision-router
294
302
  ```
295
303
 
296
304
  From a DeepSeek Harness source checkout:
297
305
 
298
306
  ```sh
299
307
  pnpm dsh plugin --profile web add dsh-vision-router
300
- pnpm dsh --profile web --dump-config | grep vision-router
308
+ ```
309
+
310
+ Optional verification:
311
+
312
+ ```sh
313
+ npx @deepseek-ai/dsh --profile web --dump-config | grep vision-router
314
+ # source checkout: pnpm dsh --profile web --dump-config | grep vision-router
301
315
  ```
302
316
 
303
317
  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.**
@@ -323,6 +337,8 @@ pnpm dsh plugin --profile web update dsh-vision-router
323
337
 
324
338
  Settings live in the profile's settings provider and survive upgrades.
325
339
 
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.
341
+
326
342
  > **Upgrading from a pre-bundle-patch install (v0.x):** the package now mounts
327
343
  > itself through its own bundle patch, so a leftover manual row in
328
344
  > `~/.dsh/profiles/<profile>/cordis.patch.yml` duplicates it and `dsh web`
package/README.zh.md CHANGED
@@ -15,7 +15,7 @@
15
15
  </p>
16
16
 
17
17
  <p align="center">
18
- <a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v1.2.1"><img src="https://img.shields.io/badge/release-v1.2.1-5B4CF0?style=flat-square" alt="Release v1.2.1" /></a>
18
+ <a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v1.4.0"><img src="https://img.shields.io/badge/release-v1.4.0-5B4CF0?style=flat-square" alt="Release v1.4.0" /></a>
19
19
  <a href="tests"><img src="https://img.shields.io/badge/verified-149%20tests-2EA44F?style=flat-square" alt="Verified: 149 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&amp;logo=nodedotjs&amp;logoColor=white" alt="Node.js >=22" /></a>
@@ -28,18 +28,26 @@
28
28
  <p align="center">💬 <strong>QQ 用户交流群:1105463028</strong></p>
29
29
 
30
30
  > [!WARNING]
31
- > 📌 **公告(v1.2.3)**
31
+ > 📌 **公告(v1.4.0)**
32
32
  >
33
- > v1.2.3 现已支持:修复 DSH Desktop 每次启动都重复弹出首次引导的问题——引导「已读」标记与模型引导步骤改存 profile 设置文件(不再依赖按 origin 隔离、每次随机端口重启即清零的 `localStorage`)(issue #78)。
34
- >
35
- > v1.2.2 现已支持:补上最后一处附件 ID 缺口——宿主 `read_image` 回挂图片公布的 `sha256:…` ID 现在可被 `vision_describe` 与全部像素工具解析(issue #72);`vision_present` 等工具结果里的图像块不再把文本模型会话锁死在 `UNSUPPORTED_CONTENT`(issue #74,已锁死的历史会话升级后自动修复);检测到 v1.1.x 升级残留的旧版 sharp 时明确告警,把玄学的 `colourspace` 报错变成一眼可见的修复指引(issue #75)。
36
- >
37
- > v1.2.1 加固像素闭环:十一个像素工具可直接接受上传图片的附件 ID(告别 `cannot read …/sha256:…` 的绕路),产物文件名带指纹不再互相覆盖,`vision_ground` 对退化框自动重试,模型引导支持从第 1 步完整重放(先退出设置页),设置卡片在数百模型目录下滚动依然流畅。
33
+ > **v1.4.0 现已支持**:未声明视觉模型的自动识别与直连桥接、doctor 修复过期版本钉住豁免、引导流程聚光灯高亮——并增强设置保存校验与视觉后端兼容性。
38
34
 
39
35
  <p align="center">
40
36
  <img src="assets/vision-demo.gif" width="640" alt="演示:粘贴图片,Agent 用 vision_ground / vision_crop / vision_pixel_diff 定位发送按钮并给出坐标" />
41
37
  </p>
42
38
 
39
+ ## 目录
40
+
41
+ - [为什么做这个](#为什么做这个)
42
+ - [对比同类插件](#对比同类插件)
43
+ - [快速开始](#快速开始)
44
+ - [亮点](#亮点)
45
+ - [工作原理](#工作原理)
46
+ - [工具](#工具)
47
+ - [配置项](#配置项)
48
+ - [安装与生命周期](#安装与生命周期)
49
+ - [故障排查](#故障排查)
50
+
43
51
  ## 为什么做这个
44
52
 
45
53
  大多数 DSH 视觉插件把图片“翻译”成一段文字描述再喂给 DeepSeek——有损、一次性、看不见像素。本插件把**原图像素留在视觉模型侧**、把推理留在 DeepSeek 侧,并把“看图”变成一次**普通的工具调用**:
@@ -70,24 +78,25 @@
70
78
 
71
79
  ## 快速开始
72
80
 
73
- ### 1. 安装并让插件加载
81
+ ### 1. 安装插件
74
82
 
75
- 普通 npm / npx 安装方式推荐这样用(与 DSH 官方 README 的启动方式一致):
83
+ 普通 npm / npx 安装只需要一条命令:
76
84
 
77
85
  ```sh
78
86
  npx @deepseek-ai/dsh plugin --profile web add dsh-vision-router
79
- npx @deepseek-ai/dsh web
80
87
  ```
81
88
 
89
+ > [!NOTE]
90
+ > 第三方 `dsh-web-plugin-manager` / `dshpm` **v0.4.2+** 现已兼容:其质量门已正确放行作为运行时依赖的 `@deepseek-ai/schemastery`。上面的官方 DSH CLI 仍是推荐安装方式。
91
+
82
92
  如果你是从 DeepSeek Harness 源码仓库通过 pnpm 运行,`dsh` 不一定在系统 `PATH` 里,请改用工作区脚本:
83
93
 
84
94
  ```sh
85
95
  cd deepseek-harness
86
96
  pnpm dsh plugin --profile web add dsh-vision-router
87
- pnpm dsh web
88
97
  ```
89
98
 
90
- 如果你已经全局安装 DSH CLI,并且终端里能直接执行 `dsh`,也可以继续使用较短的 `dsh ...` 写法。
99
+ 如果你已经全局安装 DSH CLI,并且终端里能直接执行 `dsh`,也可以继续使用较短的 `dsh ...` 写法。安装完成后,按你平时的方式启动或重新加载 DSH Web 即可。
91
100
 
92
101
  > [!NOTE]
93
102
  > 如果你是把插件**首次安装进一个已经长期运行的 Web 进程**,需要让 DSH Web 进程重新加载一次插件本体。插件加载完成后,新增/删除模型、修改自动识图包装范围都会**热更新,无需再重启 DSH**。
@@ -110,7 +119,7 @@ opencode-go + 自动识图 ← 发图片时选这个
110
119
 
111
120
  ### 3. 直接粘贴或上传图片
112
121
 
113
- 选好「+ 自动识图」模型组后,直接往对话里贴图即可。Agent 会自动挂载视觉工具,通过 `vision_describe`、`vision_ground`、`vision_crop` 等工具看图,需要时连续多步操作。
122
+ 选好「+ 自动识图」模型组后,直接往对话里贴图即可。默认情况下完整视觉工具表从会话开始就保持稳定,Agent 可直接调用 `vision_describe`、`vision_ground`、`vision_crop` 等工具看图,需要时连续多步操作。
114
123
 
115
124
  默认已经有内置 OVH 匿名视觉兜底,无需注册、无需 Key。**聊天页右下角只选择“脑子/会话模型”**;视觉模型不要在那里选。高级配置在 **设置 → 插件 → 插件配置 → 视觉路由(自动识图)**:视觉后端链每一行只选择一个你在 **设置 → 模型** 中已经配置且支持图片输入的用户模型;一行都不填也可以,OVH 免费链会固定在最后兜底。插件内部的 `Vision HTTP` 只是传输实现,不是用户需要选择的模型组。
116
125
 
@@ -129,7 +138,7 @@ opencode-go + 自动识图 ← 发图片时选这个
129
138
  - **自动降级 + 分类报错。** 地区限制、ToS 风控、402 额度、429 限流(尊重 Retry-After 退避重试)、上下文超长、网络故障——链路逐供应商尝试,全部失败才报错并给出可操作的建议。
130
139
  - **图片记忆。** 视觉答案按附件内容哈希缓存;后续文字轮用记录的描述替换历史图片(标注为不可信证据),DeepSeek 真正“记得”之前发过的图,且不重复消耗视觉调用。
131
140
  - **可验证的像素闭环。** 参照图 → `vision_html_screenshot` → `vision_pixel_diff`(差异率 + 红色热力图 + 最差区域排行)→ 修复 → 再对比,直到差异收敛。UI 还原从“目测”变成“实测”。
132
- - **渐进式 schema 暴露。** 平时只有一个零参引导工具 `vision_activate`;图片轮自动挂载全部 11 个深看工具(附一次性使用提示),并为纯文字轮注册 `vision-tools` 技能。
141
+ - **稳定工具 schema。** 默认从会话开始就注册完整 11 个深看工具,避免图片轮中途扩展工具列表导致长上下文的 KV / prefix cache 失效。仍保留 `progressiveTools: true` 作为高级启动期 opt-in;开启后才使用 `vision_activate` 按需挂载。详见 [`docs/progressive-tools-cache.md`](docs/progressive-tools-cache.md)。
133
142
  - **选择性代理。** 只有配置的视觉供应商域名走本地代理;DeepSeek 保持直连。
134
143
 
135
144
  ### 像素闭环实测
@@ -150,7 +159,7 @@ Agent 仅根据参考图复刻 UI,再用 `vision_pixel_diff` 验证最终结
150
159
 
151
160
  ## 工具
152
161
 
153
- 11 个深看工具在图片轮自动挂载(`autoActivateOnImage`);文字轮可通过 `vision_activate` 或 `/vision-tools` 技能挂载。全部基于 sharp / potrace / tesseract / 系统 Chrome——无 Python:
162
+ 默认 `progressiveTools: false`:11 个深看工具从插件启动时就保持常驻,文本轮和图片轮都可直接调用。若你在 profile / composition 的 `cordis.patch.yml` 中显式开启 `progressiveTools: true`,才会恢复渐进模式:初始只暴露 `vision_activate`,首次需要时再挂载完整工具,并注册 `vision-tools` 技能。该开关是启动期配置,修改后需重启 DSH。全部工具基于 sharp / potrace / tesseract / 系统 Chrome——无 Python:
154
163
 
155
164
  <p align="center">
156
165
  <img src="assets/vision-tools-zh.svg" width="100%" alt="DSH Vision Router 的 11 个视觉工具。" />
@@ -266,7 +275,7 @@ Web 配置页在 **设置 → 插件 → 插件配置** 下注册「视觉路由
266
275
  | `wrapperRoute` / `chainRoute` | `deepseek-vision` / `vision-chain` | 准入包装路由名 / 降级链路由名(置空关闭) |
267
276
  | `stealth` | `false` | 接管官方 `deepseek-official` 路由(仅官方行;自定义路由默认由自动包装处理) |
268
277
  | `textProvider` | `deepseek-official` / `deepseek-v4-pro` | 负责思考的模型(你的日常模型) |
269
- | `tool` / `progressiveTools` / `autoActivateOnImage` | `true` ×3 | 视觉工具开关 / 渐进式挂载 / 图片轮自动挂载 |
278
+ | `tool` / `progressiveTools` / `autoActivateOnImage` | `true` / `false` / `true` | 视觉工具总开关 / 渐进式挂载(默认关闭以稳定工具 schema)/ 渐进模式下图片轮自动挂载;`progressiveTools` 为启动期配置 |
270
279
  | `rewriteImages` | `true` | 模型输入层改写图片块(缓存描述或工具提示标记);界面日志保留图片 |
271
280
  | `downscale` / `downscaleMaxPixels` | `true` / `4000000` | 调用前压缩及其像素预算(延迟保护) |
272
281
  | `cache` / `cacheTtlSeconds` / `cacheMaxEntries` | `true` / `3600` / `200` | 视觉答案缓存 |
@@ -286,18 +295,23 @@ Web 配置页在 **设置 → 插件 → 插件配置** 下注册「视觉路由
286
295
 
287
296
  ### 安装
288
297
 
289
- 普通 npm / npx 安装:
298
+ 普通 npm / npx 安装——一条命令:
290
299
 
291
300
  ```sh
292
301
  npx @deepseek-ai/dsh plugin --profile web add dsh-vision-router
293
- npx @deepseek-ai/dsh --profile web --dump-config | grep vision-router
294
302
  ```
295
303
 
296
304
  从 DeepSeek Harness 源码仓库运行:
297
305
 
298
306
  ```sh
299
307
  pnpm dsh plugin --profile web add dsh-vision-router
300
- pnpm dsh --profile web --dump-config | grep vision-router
308
+ ```
309
+
310
+ 可选验证:
311
+
312
+ ```sh
313
+ npx @deepseek-ai/dsh --profile web --dump-config | grep vision-router
314
+ # 源码仓库:pnpm dsh --profile web --dump-config | grep vision-router
301
315
  ```
302
316
 
303
317
  首次把插件装进已经长期运行的 Web profile 时,需要让 Web 进程重新加载插件本体;宿主在启动时通过 `dsh.client` 声明发现浏览器端包。**插件加载完成后,模型目录与包装范围的变化会热更新,不需要为这些变化重启。**
@@ -323,6 +337,8 @@ pnpm dsh plugin --profile web update dsh-vision-router
323
337
 
324
338
  设置存放在 profile 的设置提供方里,升级不丢失。
325
339
 
340
+ > **新版本一直不生效(`downloaded 0` / `added 0`):** pnpm v11 会拦下发布不足 24 小时的版本;运行 `npx dsh-vision-router repair` 修复过期的带版本号豁免条目后,更新立即生效。
341
+
326
342
  > **从 bundle 补丁之前(v0.x)升级:** 现在插件由自带的 bundle 补丁自动挂载,
327
343
  > 若 `~/.dsh/profiles/<profile>/cordis.patch.yml` 里还残留旧版手动行,会与之
328
344
  > 重复,`dsh web` 启动即报 `duplicate loader entry id: vision-router`。删除
package/cordis.patch.yml CHANGED
@@ -8,11 +8,15 @@
8
8
  # 挂载后是否接管官方 deepseek-official 路由由设置里的「隐身模式」开关决定
9
9
  # (默认关;开启后需自行在 profile 补丁层禁用 llm-deepseek 行)。
10
10
 
11
- # 挂载插件行。配置全部可选(默认即内置免费视觉端点 + 工具优先的图片流程),
12
- # 可在 Web 设置 > 插件 > 插件配置 的「视觉路由」卡片里实时修改。
11
+ # 挂载插件行。默认保持完整视觉工具表常驻(issue #81):虽然渐进挂载可以
12
+ # 少发一小段工具 schema,但图片轮首次扩展工具列表会改变请求前缀,可能让
13
+ # 长会话的 provider KV/prefix cache 整体失效。高级用户仍可在 profile /
14
+ # composition 补丁中显式把 progressiveTools 改回 true(启动期配置)。
13
15
  - insert:
14
16
  - id: vision-router
15
17
  name: dsh-vision-router
18
+ config:
19
+ progressiveTools: false
16
20
 
17
21
  # 放宽附件图片限制(部署默认 5MB / 4000 万像素 → 20MB / 1 亿像素),
18
22
  # 大尺寸设计稿/扫描图可过审。字段可选,不需要可在 profile 补丁层覆写。
package/docs/doctor.md CHANGED
@@ -32,7 +32,7 @@ To inspect only the Web profile:
32
32
  npx dsh-vision-router doctor --profile web
33
33
  ```
34
34
 
35
- The command locates the DSH home (`$DSH_HOME` when set, otherwise `~/.dsh`), scans profile `package.json` files, reports UTF-8 BOM bytes, validates the JSON after ignoring a leading BOM for diagnosis, and reports whether `dsh-vision-router` is present as a profile dependency and bundle layer.
35
+ The command locates the DSH home (`$DSH_HOME` when set, otherwise `~/.dsh`), scans profile `package.json` files, reports UTF-8 BOM bytes, validates the JSON after ignoring a leading BOM for diagnosis, reports whether `dsh-vision-router` is present as a profile dependency and bundle layer, and flags version-pinned `minimumReleaseAgeExclude` entries in the profile's `pnpm-workspace.yaml` that would hold back the next release.
36
36
 
37
37
  ## Repair the UTF-8 BOM startup failure
38
38
 
@@ -50,3 +50,21 @@ npx dsh-vision-router repair --profile web
50
50
  ```
51
51
 
52
52
  `repair` removes only the three-byte UTF-8 BOM prefix (`EF BB BF`) when it is present, then validates the remaining JSON. It does not reformat, regenerate, or otherwise rewrite the profile contents. If JSON is still invalid for another reason, the command reports that and stops rather than guessing a repair.
53
+
54
+ ## Repair a stale release-age exemption (the "update does nothing" gate)
55
+
56
+ pnpm v11 defaults `minimumReleaseAge` to 1440 minutes: a version published less than 24 hours ago is not resolved, so `dsh plugin update` silently keeps the previous version and prints `downloaded 0 / added 0`. An exemption entry that pins a version — `dsh-vision-router@1.2.0` — only exempts that one version and goes stale on the next release, which is why "a new release is out but the update does nothing" keeps recurring.
57
+
58
+ The doctor flags version-pinned entries for `dsh-vision-router` and the `@deepseek-ai/*` host packages:
59
+
60
+ ```text
61
+ ✗ web — … — release-age exemption version-pinned (dsh-vision-router@1.2.0) — releases younger than 24h will not be picked up
62
+ ```
63
+
64
+ Run:
65
+
66
+ ```sh
67
+ npx dsh-vision-router repair --profile web
68
+ ```
69
+
70
+ to rewrite them to bare names (`dsh-vision-router`, `@deepseek-ai/*`), which exempt every future version, so upgrades take effect immediately again. Unrelated entries and the rest of the file are left untouched.
@@ -0,0 +1,57 @@
1
+ # Progressive tools and prefix cache
2
+
3
+ 中文 | English
4
+
5
+ ## 中文
6
+
7
+ Vision Router 默认让完整视觉工具表从会话开始就保持稳定。正常通过 DSH bundle 安装时,组合层会提供:
8
+
9
+ ```yaml
10
+ - id: vision-router
11
+ name: dsh-vision-router
12
+ config:
13
+ progressiveTools: false
14
+ ```
15
+
16
+ 插件入口本身也把 `progressiveTools` 的 schema 默认值设为 `false`,因此即使后续 profile patch 整块覆盖了 bundle 的 `config`、但没有重述这个字段,也不会意外回到渐进模式。
17
+
18
+ 原因是很多模型服务的 KV / prefix cache 会把工具 schema 视为请求前缀的一部分。若长会话一开始只暴露 `vision_activate`,第一次图片轮再挂载完整视觉工具,工具列表发生变化后可能导致此前的大段会话前缀无法命中缓存。
19
+
20
+ 渐进式暴露仍然保留为高级 opt-in。如果你更在意平时请求中少携带工具 schema,而不依赖长会话前缀缓存,请在 **profile / composition 的 `cordis.patch.yml`** 中显式给 `vision-router` 设置:
21
+
22
+ ```yaml
23
+ - id: vision-router
24
+ config:
25
+ progressiveTools: true
26
+ ```
27
+
28
+ `progressiveTools` 决定插件启动时注册哪组工具,因此它是**启动期配置**;不要依赖运行中的 Web 设置热切换这个字段。修改 profile patch 后重启 DSH。
29
+
30
+ 开启后,平时只暴露 `vision_activate`,首次需要时再挂载完整视觉工具;默认关闭时,完整视觉工具从一开始就常驻。视觉工具本身的能力不变。
31
+
32
+ ## English
33
+
34
+ Vision Router keeps the complete vision tool schema stable from the beginning of a session by default. Normal DSH bundle installs provide this composition layer:
35
+
36
+ ```yaml
37
+ - id: vision-router
38
+ name: dsh-vision-router
39
+ config:
40
+ progressiveTools: false
41
+ ```
42
+
43
+ The public plugin entrypoint also makes `false` the schema default. Therefore a later profile patch that replaces the bundle `config` without restating this field cannot accidentally fall back to progressive mode.
44
+
45
+ Many model providers include tool schemas in the KV/prefix-cacheable request prefix. If a long conversation starts with only `vision_activate` and the first image turn later mounts the complete vision tool set, that prefix change can invalidate a large cached history.
46
+
47
+ Progressive exposure remains available as an advanced opt-in. If minimizing the always-present tool schema matters more than long-context prefix-cache stability, explicitly set it in the **profile/composition `cordis.patch.yml`**:
48
+
49
+ ```yaml
50
+ - id: vision-router
51
+ config:
52
+ progressiveTools: true
53
+ ```
54
+
55
+ `progressiveTools` determines which tools are registered at plugin startup, so it is a **boot-time setting**; do not rely on changing this field through live Web settings. Restart DSH after changing the profile patch.
56
+
57
+ When enabled, only `vision_activate` is exposed initially and the complete vision tool set mounts on first use. With the default disabled mode, the complete vision tool set is present from the start. The vision capabilities themselves are unchanged.
package/entry.js ADDED
@@ -0,0 +1,51 @@
1
+ // Public plugin entrypoint.
2
+ //
3
+ // Keep the large implementation in index.js, but normalize the progressive
4
+ // tools switch here before Cordis reads the exported Config. Issue #81 showed
5
+ // that changing the tool schema mid-session can invalidate provider prefix/KV
6
+ // caches for very long conversations, so progressive exposure is now an
7
+ // explicit opt-in rather than the implicit fallback.
8
+
9
+ import z from '@deepseek-ai/schemastery'
10
+ import * as core from './index.js'
11
+ import { installVisionRouterFileLogging } from './lib/file-logger.js'
12
+
13
+ // Schemastery object schemas expose set() as the supported way to replace a
14
+ // field schema. This mutates the Config object that index.js itself later uses
15
+ // for the settings namespace, so composition config and settings validation
16
+ // agree on the same default.
17
+ core.Config.set('progressiveTools', z.boolean().default(false))
18
+
19
+ export * from './index.js'
20
+ export const Config = core.Config
21
+
22
+ // Defense in depth for direct/programmatic callers that invoke apply() without
23
+ // first running the Cordis Config resolver: only an explicit true enables the
24
+ // schema-changing progressive mode. The wrapped context changes only logger:
25
+ // every existing vision-router diagnostic still reaches the host logger and is
26
+ // also persisted to ~/.dsh/logs/vision-router/vision-router.log.
27
+ export function apply(ctx, config = {}) {
28
+ const logging = installVisionRouterFileLogging(ctx)
29
+ try {
30
+ const result = core.apply(logging.ctx, {
31
+ ...config,
32
+ progressiveTools: config.progressiveTools === true,
33
+ })
34
+ if (result && typeof result.then === 'function') {
35
+ return result.catch((error) => {
36
+ logging.logger.error(
37
+ 'vision-router: plugin apply failed: %s',
38
+ error && error.stack ? error.stack : error && error.message ? error.message : String(error),
39
+ )
40
+ throw error
41
+ })
42
+ }
43
+ return result
44
+ } catch (error) {
45
+ logging.logger.error(
46
+ 'vision-router: plugin apply failed: %s',
47
+ error && error.stack ? error.stack : error && error.message ? error.message : String(error),
48
+ )
49
+ throw error
50
+ }
51
+ }