dsh-vision-router 2.2.1 → 2.2.3

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
@@ -253,7 +253,7 @@ The diagram covers the eleven image-processing tools. `vision_present` (durable
253
253
  | `vision_present` | Publish a generated or edited local image as a durable chat attachment so the user can see it | image attachment |
254
254
  | `vision_pixel_diff` | Per-pixel comparison: diff ratio + worst 8×8-grid regions | red heatmap PNG + JSON report |
255
255
  | `vision_colors` | Dominant colors (hex + share) | — |
256
- | `vision_ocr` | Text transcription: local tesseract (chi_sim+eng) first, vision model fallback | — |
256
+ | `vision_ocr` | Text transcription: configurable default engine (`auto` / local Tesseract / vision model); an explicit per-call engine still wins | — |
257
257
  | `vision_trace` | SVG vectorization (potrace posterization; icons/logos) | SVG |
258
258
  | `vision_extract_foreground` | Cutout via border flood fill (uniform backgrounds) | transparent PNG |
259
259
  | `vision_html_screenshot` | Screenshot a local HTML file (headless system Chrome); `fullPage: true` captures the whole page and reports `pageHeight` | PNG |
@@ -357,8 +357,8 @@ Everything is optional; defaults work out of the box. Prefer **Settings → Visi
357
357
  | `rewriteImages` | `true` | rewrite image blocks in the model input (cached description or tool-hint marker); the UI log keeps images |
358
358
  | `desktopScreenshot` | `false` | privacy opt-in for the model-callable `vision_screenshot` desktop-capture tool; checked live before every capture |
359
359
  | `freeFallback` | `true` | append the anonymous OVH models after explicit local/custom HTTP backends; turning this off never disables an explicitly configured local backend |
360
- | `localOllama` | `{ enabled: false, baseURL: 'http://127.0.0.1:11434/v1', model: 'qwen2.5vl', format: 'openai' }` | local vision backend; when enabled, `local-ollama` leads the HTTP vision chain, is skipped automatically when down, and supports OpenAI or Anthropic wire format |
361
- | `localLmStudio` | `{ enabled: false, baseURL: 'http://localhost:1234/v1', model: '', format: 'openai' }` | local LM Studio backend after Ollama; enter the exact model identifier from LM Studio Developer or `/v1/models` |
360
+ | `localOllama` | `{ enabled: false, baseURL: 'http://127.0.0.1:11434/v1', model: 'qwen2.5vl', format: 'openai', maxTokens: 4096, reasoningEffort: 'none' }` | local vision backend; OpenAI mode disables supported model reasoning by default so the output budget is spent on answer text |
361
+ | `localLmStudio` | `{ enabled: false, baseURL: 'http://localhost:1234/v1', model: '', format: 'openai', maxTokens: 4096, reasoningEffort: 'none' }` | local LM Studio backend after Ollama; LM Studio 0.4+ can use `format: 'lmstudio'` for documented native reasoning control |
362
362
  | `visionTurnBudgetMs` | `0` | whole-turn vision wall-clock budget; `0` means unlimited. Concrete provider calls/tools still keep their own hard deadlines |
363
363
  | `downscale` / `downscaleMaxPixels` | `true` / `4000000` | pre-call downscale and its pixel budget (latency guard) |
364
364
  | `cache` / `cacheTtlSeconds` / `cacheMaxEntries` | `true` / `3600` / `200` | vision answer cache |
@@ -409,19 +409,19 @@ ollama pull qwen2.5vl
409
409
  - When enabled, `local-ollama` heads the HTTP vision chain. For a strict local-only setup, remove cloud vision rows/custom HTTP endpoints and turn off `freeFallback`.
410
410
  - The selected loopback Ollama model is prewarmed through Ollama's native API and kept resident for 30 minutes. If it is cold when Ollama is the primary image backend, loading completes before the normal vision-task budget starts; a short `/api/ps` probe keeps a dead service on the fast fallback path. Remote Ollama URLs are never auto-warmed.
411
411
  - **LM Studio works the same way** — enable `localLmStudio` with its OpenAI-compatible endpoint (default `http://localhost:1234/v1`) and enter the exact model identifier shown in Developer or `/v1/models`. It sits after `local-ollama` and before custom/cloud HTTP backends.
412
- - Each local backend can speak **OpenAI or Anthropic format** via `format` (default `openai`). Anthropic mode routes to `/v1/messages` with `anthropic-version` and base64 image sources; `x-api-key` is sent only when a key is configured. LM Studio needs version 0.4.1 or newer for this endpoint.
412
+ - Local backends keep **OpenAI** as the compatibility default and can also use **Anthropic**. LM Studio additionally offers **LM Studio native** mode (`format: 'lmstudio'`, LM Studio 0.4+) at `/api/v1/chat`; use it when you need documented reasoning control (`reasoningEffort: 'none'` maps to `reasoning: off`). `maxTokens` is configurable and defaults to 4096.
413
413
  - If a local backend is down or the call times out, its entry is skipped automatically and the chain falls through to the cloud backends — no call breaks.
414
414
  - `vision_screenshot` is disabled by default. After the separate Desktop screenshot opt-in, `identify=true` uses the same Ollama → LM Studio fallback.
415
415
 
416
416
  ## Requirements
417
417
 
418
418
  - DeepSeek Harness Web profile. Normal installs can use `npx @deepseek-ai/dsh ...`; source checkouts use `pnpm dsh ...`. A bare `dsh ...` command only works when the CLI is already on your shell `PATH`.
419
- - **DSH Host support policy:** DVR 2.1.x keeps DSH `0.1.0-rc.8` as the public minimum and currently supports the released stable channel through `0.1.5-rc.2`. Exact `0.1.6-alpha.1` coverage is **verification evidence only**, not a preview support promise; scheduled `latest`/`alpha` canaries monitor drift without changing the support policy. DVR 2.0.x was the final train with public support for rc.6/rc.7. See [DSH Host support window](docs/architecture/dsh-support-window.md).
419
+ - **DSH Host support policy:** DVR 2.2.x keeps DSH `0.1.0-rc.8` as the public minimum and currently supports the released stable channel through `0.1.5-rc.3`. Exact `0.1.7-rc.2` (`next`) coverage is **verification evidence only**, not a preview support promise; scheduled `latest`/`alpha` canaries monitor drift without changing the support policy. DVR 2.0.x was the final train with public support for rc.6/rc.7. See [DSH Host support window](docs/architecture/dsh-support-window.md).
420
420
  - Node ≥ 22 (host side).
421
421
  - No API key for the default free chain; a credential reference (`apiKeyEnv`) only for paid `httpProviders`.
422
422
  - Chrome / Chromium / Edge is needed only for `vision_html_screenshot`; every other tool works without a browser.
423
423
  - Desktop capture is opt-in. Windows and macOS use OS-provided capture facilities; Linux needs ImageMagick `import` or `scrot` and a capturable desktop session (Wayland support depends on the environment).
424
- - Tesseract is optional: `vision_ocr` falls back to the vision model when the local engine is absent.
424
+ - Tesseract is optional. `vision_ocr` defaults to `ocrEngine: auto` (local Tesseract first, vision fallback), and Settings → Advanced → **Default OCR engine** can force Tesseract-only or vision-model-only behavior without uninstalling Tesseract. An explicit per-call `engine=tesseract|vision` always overrides the default.
425
425
 
426
426
  ## Install and lifecycle
427
427
 
package/README.zh.md CHANGED
@@ -251,7 +251,7 @@ Agent 仅根据参考图复刻 UI,再用 `vision_pixel_diff` 验证最终结
251
251
  | `vision_present` | 把生成或编辑后的本地图片发布为持久聊天附件,供用户查看 | 图片附件 |
252
252
  | `vision_pixel_diff` | 逐像素对比:差异率 + 最差 8×8 网格区域 | 红色热力图 PNG + JSON 报告 |
253
253
  | `vision_colors` | 主色提取(十六进制 + 占比) | — |
254
- | `vision_ocr` | 文字转写:本地 tesseract(中英)优先,视觉模型兜底 | — |
254
+ | `vision_ocr` | 文字转写:默认引擎可配置为 `auto` / 本地 Tesseract / 视觉模型;单次显式 engine 仍优先 | — |
255
255
  | `vision_trace` | SVG 矢量化(potrace 分色;图标/logo) | SVG |
256
256
  | `vision_extract_foreground` | 边界洪泛抠图(纯色背景) | 透明 PNG |
257
257
  | `vision_html_screenshot` | 给本地 HTML 文件截图(无头系统 Chrome);`fullPage: true` 截整页并返回 `pageHeight` | PNG |
@@ -355,8 +355,8 @@ Web profile 现在提供一级 **设置 → Vision Router** 页面。常规页
355
355
  | `rewriteImages` | `true` | 模型输入层改写图片块(缓存描述或工具提示标记);界面日志保留图片 |
356
356
  | `desktopScreenshot` | `false` | 模型可调用的 `vision_screenshot` 桌面截屏隐私开关;每次截屏前实时检查 |
357
357
  | `freeFallback` | `true` | 在显式本地/自定义 HTTP 后端之后追加匿名 OVH 模型;关闭它不会停用用户明确配置的本地后端 |
358
- | `localOllama` | `{ enabled: false, baseURL: 'http://127.0.0.1:11434/v1', model: 'qwen2.5vl', format: 'openai' }` | 本地视觉后端;开启后排在 HTTP 视觉链前部,服务未运行会自动跳过,支持 OpenAI / Anthropic 协议 |
359
- | `localLmStudio` | `{ enabled: false, baseURL: 'http://localhost:1234/v1', model: '', format: 'openai' }` | Ollama 之后的本地 LM Studio 后端;填写 Developer 页或 `/v1/models` 返回的真实模型 ID |
358
+ | `localOllama` | `{ enabled: false, baseURL: 'http://127.0.0.1:11434/v1', model: 'qwen2.5vl', format: 'openai', maxTokens: 4096, reasoningEffort: 'none' }` | 本地视觉后端;OpenAI 模式默认关闭受支持模型的推理,把输出预算留给正文 |
359
+ | `localLmStudio` | `{ enabled: false, baseURL: 'http://localhost:1234/v1', model: '', format: 'openai', maxTokens: 4096, reasoningEffort: 'none' }` | Ollama 之后的本地 LM Studio 后端;LM Studio 0.4+ 可选 `format: 'lmstudio'` 使用官方原生推理控制 |
360
360
  | `visionTurnBudgetMs` | `0` | 整轮视觉总墙钟预算;`0` = 不设整轮上限。具体 provider调用/工具仍有自己的硬超时 |
361
361
  | `downscale` / `downscaleMaxPixels` | `true` / `4000000` | 调用前压缩及其像素预算(延迟保护) |
362
362
  | `cache` / `cacheTtlSeconds` / `cacheMaxEntries` | `true` / `3600` / `200` | 视觉答案缓存 |
@@ -407,19 +407,19 @@ ollama pull qwen2.5vl
407
407
  - 开启后 `local-ollama` 排在 HTTP 视觉链前部。若要严格纯本地,请移除云视觉行/自定义 HTTP 端点,并关闭 `freeFallback`。
408
408
  - 选中的本机 loopback Ollama 模型会通过原生 API 预热并保持 30 分钟驻留。如果模型在 Ollama 作为首个图片后端时已经冷却,加载会在正常视觉任务预算开始之前完成;短 `/api/ps` 探测保证服务未运行/挂死时仍快速进入 fallback。远程 Ollama URL 不会自动预热。
409
409
  - **LM Studio 同理**——开启 `localLmStudio`,填 OpenAI 兼容端点(默认 `http://localhost:1234/v1`),并使用 Developer 页或 `/v1/models` 返回的真实模型标识。它排在 `local-ollama` 之后、自定义/云 HTTP 后端之前。
410
- - 每个本地后端可通过 `format` 选择 **OpenAI 或 Anthropic 格式**(默认 `openai`)。Anthropic 模式走 `/v1/messages`,带 `anthropic-version` 并把图片转为 base64 source;只有配置了 Key 才发送 `x-api-key`。LM Studio 需 0.4.1 或更高版本才提供该端点。
410
+ - 本地后端继续以 **OpenAI** 为兼容默认,也可选 **Anthropic**。LM Studio 额外提供 **LM Studio 原生**模式(`format: 'lmstudio'`,需 LM Studio 0.4+),走 `/api/v1/chat`;需要稳定关闭推理时推荐该模式,因为官方 API 明确支持 `reasoning: off`。`maxTokens` 可配置,默认 4096。
411
411
  - 任一本地后端未运行或调用超时时自动跳过,继续降级到云链。
412
412
  - `vision_screenshot` 默认关闭。单独开启「桌面截屏」隐私开关后,`identify=true` 使用同样的 Ollama → LM Studio 降级顺序。
413
413
 
414
414
  ## 环境要求
415
415
 
416
416
  - DeepSeek Harness 的 Web profile。普通安装可用 `npx @deepseek-ai/dsh ...`;从源码仓库运行时用 `pnpm dsh ...`。只有 CLI 已经进入系统 `PATH` 时才能直接写 `dsh ...`。
417
- - **DSH Host 支持策略:** DVR 2.1.x 的公开最低 Host 仍为 DSH `0.1.0-rc.8`,当前正式发布通道已验证并支持到 `0.1.5-rc.2`。对 `0.1.6-alpha.1` 的精确覆盖**只属于验证证据**,不代表对 preview 的公开支持承诺;定时 `latest`/`alpha` canary 只负责发现上游漂移,也不会自动改变支持策略。DVR 2.0.x 是最后公开支持 rc.6/rc.7 的版本线。详见 [DSH Host 支持窗口](docs/architecture/dsh-support-window.md)。
417
+ - **DSH Host 支持策略:** DVR 2.2.x 的公开最低 Host 仍为 DSH `0.1.0-rc.8`,当前正式发布通道已验证并支持到 `0.1.5-rc.3`。对 `0.1.7-rc.2`(`next`)的精确覆盖**只属于验证证据**,不代表对 preview 的公开支持承诺;定时 `latest`/`alpha` canary 只负责发现上游漂移,也不会自动改变支持策略。DVR 2.0.x 是最后公开支持 rc.6/rc.7 的版本线。详见 [DSH Host 支持窗口](docs/architecture/dsh-support-window.md)。
418
418
  - Node ≥ 22(宿主侧)。
419
419
  - 默认免费链路无需 API Key;付费 `httpProviders` 只需一个凭据引用(`apiKeyEnv`)。
420
420
  - 只有 `vision_html_screenshot` 需要 Chrome / Chromium / Edge;其余工具无浏览器也能用。
421
421
  - 桌面截屏必须显式开启。Windows/macOS 使用系统截屏能力;Linux 需安装 ImageMagick `import` 或 `scrot`,且必须处于可截取的桌面会话(Wayland 支持取决于环境)。
422
- - tesseract 可选:本地引擎缺失时 `vision_ocr` 自动退回视觉模型。
422
+ - tesseract 可选。`vision_ocr` 默认使用 `ocrEngine: auto`(本地 Tesseract 优先、失败或空结果再回退视觉模型);也可在「设置 → 高级 → OCR 默认引擎」强制仅 Tesseract 或直接使用视觉模型,无需卸载 Tesseract。单次调用显式 `engine=tesseract|vision` 始终覆盖默认设置。
423
423
 
424
424
  ## 安装与生命周期
425
425
 
package/cordis.patch.yml CHANGED
@@ -43,6 +43,17 @@
43
43
  config:
44
44
  progressiveTools: false
45
45
 
46
+ # DSH 的 live patch/HMR 旧实现会把 loader dispose 的 disabled=true 就地写回
47
+ # bundle insert 对象,随后 recompose 又复用同一个对象(upstream #2854)。
48
+ # 0.1.7-rc.2 仍保留该共享对象边界;Desktop supervisor + 多 bundle 场景可因此
49
+ # 反复卸载/重挂 DVR(issue #547)。在 insert 之后再按 id 显式恢复 enabled,
50
+ # 让每次 recompose 都覆盖被污染的 disabled 值。新 Include 会立即命中上面的
51
+ # insert;旧 Include 若尚不能在同一 patch list 中索引新 insert,则只会跳过这条
52
+ # overlay,保持旧 Host 原有启动行为。上游 clone insert 后可审计删除。
53
+ - id: vision-router
54
+ name: dsh-vision-router
55
+ disabled: false
56
+
46
57
  # Vision Router 的附件产品契约:Host attachment store 是 durable 图片的唯一
47
58
  # owner,视觉工具只读取 Host 已持久化、校验后的 canonical pixels。DSH rc.8
48
59
  # 以前 Host 会把已准入的源编码直接持久化;0.1.2-alpha.1 开始又增加独立的
@@ -8,11 +8,11 @@ The matrix is capability-based. Runtime code must feature-detect the seam it nee
8
8
 
9
9
  | CI fixture | DSH package line | Role |
10
10
  | --- | --- | --- |
11
- | `minimum-contract` | `0.1.0-rc.6` | Historical compatibility-retention fixture. The name is legacy; DVR 2.1.x public support starts at rc.8. |
11
+ | `minimum-contract` | `0.1.0-rc.6` | Historical compatibility-retention fixture. The name is legacy; DVR 2.1.x and later 2.x public support starts at rc.8. |
12
12
  | `legacy-contract` | `0.1.0-rc.8` | Public support-floor fixture carrying batch attachments and dimension policy. |
13
- | `current-contract` | `0.1.5-rc.2` | Current stable Host contract baseline. Must remain green. |
14
- | `preview-contract` / exact preview gates | `0.1.6-alpha.1` | Required verification evidence only; not a public preview-support claim. |
15
- | retained preview regression | `0.1.5-alpha.2` | Older preview regression fixture retained while the 0.1.6 preview line is qualified. |
13
+ | `current-contract` | `0.1.5-rc.3` | Current stable Host contract baseline. Must remain green. |
14
+ | `preview-contract` / exact preview gates | `0.1.7-rc.2` (`next`) | Required verification evidence only; not a public preview-support claim. |
15
+ | retained preview regression | `0.1.5-alpha.2` | Older preview regression fixture retained as an older preview regression while the 0.1.7 next line is qualified. |
16
16
  | `latest-dsh` / alpha canaries | resolved dynamically from npm dist-tags | Scheduled drift surveillance only. Never changes support policy by itself. |
17
17
 
18
18
  Node 22 and Node 24 remain the general required runtime matrix. The Host contract jobs are additive; they do not replace the normal test matrix.
@@ -21,7 +21,7 @@ Node 22 and Node 24 remain the general required runtime matrix. The Host contrac
21
21
 
22
22
  `yes` means the fixture has a direct positive test or feature probe. `no` means a direct negative probe exists. `compat` means the fixture proves Vision Router can safely carry the newer input/config through that Host, but does **not** claim the Host owns that capability. `probe` means the capability is intentionally not inferred from the version label and is verified at runtime/contract-test time.
23
23
 
24
- | Capability | minimum-contract rc.6 | legacy-contract rc.8 | current-contract rc.2 (0.1.5) | Evidence / detection |
24
+ | Capability | minimum-contract rc.6 | legacy-contract rc.8 | current-contract rc.3 (0.1.5) | Evidence / detection |
25
25
  | --- | --- | --- | --- | --- |
26
26
  | Batch attachment save | no | yes | yes | `hasBatchAttachmentContract()` checks the released `attachments.saveImages` prototype; `tests/rc6-rc7-compat.test.js`; contract CI. |
27
27
  | Max image dimension policy | compat | yes | yes | All fixtures parse the complete attachment-local row; rc.8/current positively retain the field and the established admission tests exercise the 10000/10001 boundary. Older Schemastery passthrough is not treated as ownership evidence. |
@@ -38,7 +38,7 @@ Node 22 and Node 24 remain the general required runtime matrix. The Host contrac
38
38
  | Public entry boot | yes | yes | yes | packed plugin public entry import in each Host contract fixture. |
39
39
  | Packaged tarball install | yes | yes | yes | each Host contract fixture packs the plugin then installs the tarball into an isolated Host package. |
40
40
 
41
- Preview-only evidence: the `0.1.6-alpha.1` contract fixture additionally mounts the Host-owned `@deepseek-ai/dsh-compaction-image-offload` projection and proves that one offloaded image occurrence stays offloaded across live requests, `SessionStore.fork()`, JSONL process restart, and cold resume, while a new occurrence of the same durable attachment remains a retained image. This is verification evidence for the preview contract only; it does not expand the public support window.
41
+ Preview-only evidence: the `0.1.7-rc.2` (`next`) contract fixture additionally mounts the Host-owned `@deepseek-ai/dsh-compaction-image-offload` projection and proves that one offloaded image occurrence stays offloaded across live requests, `SessionStore.fork()`, JSONL process restart, and cold resume, while a new occurrence of the same durable attachment remains a retained image. This is verification evidence for the preview contract only; it does not expand the public support window.
42
42
 
43
43
  ## Compatibility inventory and exit criteria
44
44
 
@@ -8,12 +8,12 @@ The public support policy contains only released Host semantics. Preview/canary
8
8
 
9
9
  | Role | DSH train | Meaning |
10
10
  |---|---|---|
11
- | Minimum Supported Host | `0.1.0-rc.8` | Oldest Host generation that DVR 2.1.x publicly supports. |
12
- | Current Stable Host | `0.1.5-rc.2` | Current npm stable-channel release covered by required exact Host and browser evidence. |
11
+ | Minimum Supported Host | `0.1.0-rc.8` | Oldest Host generation that DVR 2.2.x publicly supports. |
12
+ | Current Stable Host | `0.1.5-rc.3` | Current npm stable-channel release covered by required exact Host and browser evidence. |
13
13
 
14
- DVR `2.1.x` therefore keeps `0.1.0-rc.8` as its public floor and supports released Host trains through the current stable channel. Runtime branching remains capability-based rather than version-string-driven.
14
+ DVR `2.2.x` therefore keeps `0.1.0-rc.8` as its public floor and supports released Host trains through the current stable channel. Runtime branching remains capability-based rather than version-string-driven.
15
15
 
16
- DSH `0.1.5-rc.1` remains explicitly admitted for existing installations; current exact stable evidence has advanced to `0.1.5-rc.2`. Advancing this evidence does not raise the public minimum.
16
+ DSH `0.1.5-rc.1` / `0.1.5-rc.2` remain admitted for existing installations; current exact stable evidence has advanced to `0.1.5-rc.3`. Advancing this evidence does not raise the public minimum.
17
17
 
18
18
  No later support-floor increase is currently announced.
19
19
 
@@ -23,8 +23,8 @@ Compatibility evidence answers a different question: what exact upstream release
23
23
 
24
24
  | Evidence role | DSH source | Meaning |
25
25
  |---|---|---|
26
- | Exact stable evidence | `0.1.5-rc.2` | Required Host/wire and real Host + Chromium coverage for the current stable release. |
27
- | Exact preview evidence | `0.1.6-alpha.1` | Required preview Host/wire/lifecycle/browser evidence. This is not a preview support promise. |
26
+ | Exact stable evidence | `0.1.5-rc.3` | Required Host/wire and real Host + Chromium coverage for the current stable release. |
27
+ | Exact preview evidence | `0.1.7-rc.2` (`next`) | Required preview Host/wire/lifecycle/browser evidence. This is not a preview support promise. |
28
28
  | Stable drift canary | npm dist-tag `latest` | Scheduled, dynamically resolved surveillance. A failure starts compatibility investigation; it does not rewrite support policy. |
29
29
  | Preview drift canary | npm dist-tag `alpha` | Scheduled, dynamically resolved surveillance with preview-specific lifecycle coverage. A failure does not rewrite support policy. |
30
30
 
@@ -43,7 +43,7 @@ DVR 2.0.x minimum: DSH 0.1.0-rc.6
43
43
  DVR 2.1.x minimum: DSH 0.1.0-rc.8
44
44
  ```
45
45
 
46
- Users still on rc.6/rc.7 should upgrade DSH before upgrading to DVR 2.1.x.
46
+ Users still on rc.6/rc.7 should upgrade DSH before upgrading to DVR 2.1.x or any later 2.x train. DVR 2.2.x inherits the same rc.8 floor; this maintenance update does not raise it.
47
47
 
48
48
  This support-floor transition does **not** require deleting every rc.6-era compatibility seam in the same release. Compatibility code is retired only after a separate proof shows it is unreachable or unnecessary on every supported Host and durable-history path.
49
49
 
@@ -50,7 +50,7 @@ H1 is complete as an egress contract, not as a new production dependency. Exact
50
50
  4. The same contract runs against the exact current stable Host and exact preview evidence on Linux, macOS, and Windows through the existing source-contract matrix.
51
51
  5. Production code contains no `@deepseek-ai/dsh-http-proxy` dependency or import. `proxyRouteFor()` is used only by the exact-source test as an oracle for the Host decision.
52
52
 
53
- The current stable evidence advances to DSH `0.1.5-rc.2`; `0.1.5-rc.1` remains explicitly peer-admitted, and the public minimum remains `0.1.0-rc.8`.
53
+ The current stable evidence advances to DSH `0.1.5-rc.3`; `0.1.5-rc.1` / `0.1.5-rc.2` remain explicitly peer-admitted, exact next-channel evidence is `0.1.7-rc.2`, and the public minimum remains `0.1.0-rc.8`.
54
54
 
55
55
  ## H2 — Scope Host-owned override authority
56
56
 
@@ -0,0 +1,21 @@
1
+ # v2.2.2
2
+
3
+ DSH Vision Router 2.2.2 is an urgent browser compatibility hotfix for DSH 0.1.7-rc.1.
4
+
5
+ ## Highlights
6
+
7
+ - Fixes Vision Router being left pending at Web startup on DSH 0.1.7-rc.1 with `waiting for service: settingsScope`.
8
+ - Adapts the legacy `ctx.settingsScope.bind({ namespace })` consumer face to DSH 0.1.7's official `configForms.get(namespace)` service without hard-requiring either service generation.
9
+ - Keeps the real legacy `settingsScope` path preferred on older supported Hosts, so the fix does not raise the existing Host floor.
10
+ - Preserves the existing local settings permission and remote-risk wrappers over both settings backends.
11
+ - Adds loader-level regression coverage for both DSH 0.1.7 `configForms` and legacy `settingsScope` Hosts.
12
+
13
+ ## Validation
14
+
15
+ - Node 22 and Node 24 CI passed on the compatibility fix.
16
+ - Architecture Closure, P1 Routing Parity, P3 Compatibility Convergence, DSH Contract, exact-source, browser smoke, adversarial compatibility, fuzz, dependency review, fetch composition, and native multimodal cold-resume gates passed on PR #538.
17
+ - The public minimum DSH Host remains `0.1.0-rc.8`.
18
+
19
+ ## Upgrade
20
+
21
+ Users affected by the DSH 0.1.7 startup failure should upgrade Vision Router to 2.2.2. No settings migration is required.
@@ -0,0 +1,22 @@
1
+ # v2.2.3
2
+
3
+ DSH Vision Router 2.2.3 is a compatibility and stability hotfix focused on DSH 0.1.7-rc.2, long-running browser Hosts, local vision backends, and release recovery.
4
+
5
+ ## Highlights
6
+
7
+ - Qualifies exact DSH `0.1.7-rc.2` support without raising the public Host floor. Session format v4 and the new Settings Forms + ConfigEditor composition are explicitly recognized while unknown future contracts still fail closed.
8
+ - Fixes the UOS/Desktop multi-bundle HMR/recompose failure class reported in #547: the Vision Router bundle now restores its inserted row after Loader `disabled=true` mutation instead of inheriting a disabled row across recomposition.
9
+ - Makes local reasoning/output budgets configurable so Ollama/LM Studio-compatible local vision backends are not forced into one fixed response budget.
10
+ - Adds a configurable default OCR engine policy and hardens structured-answer fallback, long-OCR blank retry handling, and one-time Session event-feed activation backfill.
11
+ - Makes npm publication recovery idempotent: public-registry propagation is classified as missing/transient/exact/mismatch, delayed visibility is tolerated, and mismatched or fatal identities fail closed.
12
+
13
+ ## DSH 0.1.7-rc.2 validation
14
+
15
+ - Exact DSH source: `0.1.7-rc.2` at `477b4f420553e8a52c2fbccc464d7561b239c443`.
16
+ - Node 22/24 compatibility gates and Windows/macOS/Linux exact-source checks pass.
17
+ - Real `dsh web` + Chromium coverage passes for startup, Vision mode, mixed attachments, Settings mount/save/reload/readback, and live bundle recomposition.
18
+ - The public minimum supported DSH Host remains `0.1.0-rc.8`; existing 2.2.x settings require no migration.
19
+
20
+ ## Upgrade
21
+
22
+ Users on DSH 0.1.7-rc.2, especially Desktop/multi-bundle or local-model setups, should upgrade to 2.2.3 after release. No settings migration is required.
package/index.js CHANGED
@@ -249,6 +249,8 @@ export const Config = z.object({
249
249
  // (its own cap) and the vision-model fallback only the rest — never two
250
250
  // full timeouts added together.
251
251
  ocrTimeoutMs: z.number().step(1).min(1000).max(120000).default(30000),
252
+ // Default engine for vision_ocr. Per-call engine=tesseract|vision remains authoritative.
253
+ ocrEngine: z.union(['auto', 'tesseract', 'vision']).default('auto'),
252
254
  proxy: z.string().default(''),
253
255
  proxyHosts: z.array(z.string()).default([...DEFAULT_PROXY_HOSTS]),
254
256
  // Remote browsers are intentionally unable to use DSH's broad settings.*
@@ -312,6 +314,8 @@ export const Config = z.object({
312
314
  // 设置卡用 placeholder 提示识别任务常用的建议值。
313
315
  temperature: z.number().min(0).max(2),
314
316
  top_p: z.number().min(0).max(1),
317
+ maxTokens: z.number().step(1).min(256).max(32768).default(4096),
318
+ reasoningEffort: z.union(['provider_default', 'none', 'low', 'medium', 'high', 'max']).default('none'),
315
319
  })
316
320
  .default({}),
317
321
  // ── dsh-vision 并入:本地 LM Studio 视觉后端(与 Ollama 同层级)───────────
@@ -326,10 +330,14 @@ export const Config = z.object({
326
330
  model: z.string().default(''),
327
331
  // 请求格式:'openai'(/chat/completions,默认)| 'anthropic'
328
332
  // (/messages,LM Studio 的 OpenAI 兼容服务同样提供)。
329
- format: z.union(['openai', 'anthropic']).default('openai'),
333
+ // LM Studio 0.4+ 的 native /api/v1/chat 明确支持 reasoning=off;
334
+ // OpenAI Chat Completions 仍保留给旧版/兼容服务。
335
+ format: z.union(['openai', 'anthropic', 'lmstudio']).default('openai'),
330
336
  // 与 localOllama 相同:显式设置才透传,留空尊重服务端默认。
331
337
  temperature: z.number().min(0).max(2),
332
338
  top_p: z.number().min(0).max(1),
339
+ maxTokens: z.number().step(1).min(256).max(32768).default(4096),
340
+ reasoningEffort: z.union(['provider_default', 'none', 'low', 'medium', 'high', 'max']).default('none'),
333
341
  })
334
342
  .default({}),
335
343
  // Legacy compatibility only: older profiles may still contain these two
@@ -2545,7 +2553,7 @@ export function apply(ctx, config = {}, runtime = {}) {
2545
2553
  const ocrPolicy =
2546
2554
  '不要默认把 OCR 当第二步;仅在需要逐字保真时用 vision_ocr,并把结果当作需要结合上下文验证的证据。' +
2547
2555
  'UI/截图语义通常用 vision_describe 或 vision_detect,精确定位用 vision_ground。' +
2548
- 'vision_ocr 的 engine=auto 始终先尝试本地 Tesseract,失败或空结果时再回退视觉模型;结构化模式不会改变这一顺序。' +
2556
+ 'vision_ocr 未显式指定 engine 时遵循设置中的 OCR 默认引擎;单次显式 engine=tesseract/vision 始终优先。' +
2549
2557
  '完成至少 1 次后续证据调用后,证据充分就直接作答,不要为了流程继续调用。'
2550
2558
  bootstrapReminder = {
2551
2559
  role: 'user',
@@ -3062,9 +3070,9 @@ ctx.logger?.info(
3062
3070
 
3063
3071
  }
3064
3072
  }
3065
- const fallback = `vision_describe: the model did not produce valid JSON. Raw output:\n${text.slice(0, 2000)}`
3066
- if (cacheEnabled()) cache.set(key, fallback)
3067
- return fallback
3073
+ const invalidJson = new Error('vision_describe backend did not produce valid JSON after one correction retry')
3074
+ invalidJson.code = 'INVALID_REQUEST'
3075
+ throw invalidJson
3068
3076
  }
3069
3077
  if (text !== '') {
3070
3078
  if (cacheEnabled()) cache.set(key, text)
@@ -3188,9 +3196,9 @@ ctx.logger?.info(
3188
3196
 
3189
3197
  }
3190
3198
  }
3191
- const fallback = `vision_describe: the model did not produce valid JSON. Raw output:\n${text.slice(0, 2000)}`
3192
- if (cacheEnabled()) cache.set(key, fallback)
3193
- return fallback
3199
+ const invalidJson = new Error('vision_describe backend did not produce valid JSON after one correction retry')
3200
+ invalidJson.code = 'INVALID_REQUEST'
3201
+ throw invalidJson
3194
3202
  }
3195
3203
  if (text !== '') {
3196
3204
  if (cacheEnabled()) cache.set(key, text)
@@ -4195,10 +4203,11 @@ ctx.logger?.info(
4195
4203
  deepToolDefs.push({
4196
4204
  name: 'vision_ocr',
4197
4205
  description:
4198
- 'Transcribe TEXT from an image. ENGINE POLICY: omitted engine / engine=auto always tries local ' +
4199
- 'Tesseract (chi_sim+eng) first — fast, free, offline — then falls back to a vision model if local ' +
4200
- 'OCR fails or returns no text. Structured 1+x follow-up does not change this order. Explicit ' +
4201
- 'engine=tesseract or engine=vision is always honored. Returns the text and which engine produced it. ' +
4206
+ 'Transcribe TEXT from an image. ENGINE POLICY: explicit engine=tesseract or engine=vision always wins. ' +
4207
+ 'Otherwise the configured OCR engine policy applies. The default auto policy tries local Tesseract ' +
4208
+ '(chi_sim+eng) first — fast, free, offline — then falls back to a vision model if local OCR fails or ' +
4209
+ 'returns no text. Structured 1+x follow-up does not change the selected policy. Returns the text and ' +
4210
+ 'which engine produced it. ' +
4202
4211
  'SCOPE: vision_ocr reads letters, it does NOT recognize people, objects or scenes. Never use it ' +
4203
4212
  'as a fallback when vision_describe fails to identify who/what is in a picture ("这是谁" / ' +
4204
4213
  '"这是什么东西" questions are answered by vision_describe, not OCR). If vision_describe returns ' +
@@ -4227,7 +4236,7 @@ ctx.logger?.info(
4227
4236
  },
4228
4237
  engine: {
4229
4238
  type: 'string',
4230
- description: '"auto" (default): always try local Tesseract first, then fall back to the vision model if local OCR fails or returns no text. Structured 1+x does not change this order; use explicit "tesseract"/"vision" to force an engine.',
4239
+ description: '"auto": use the configured OCR engine policy (default policy is local Tesseract first, then vision fallback); explicit "tesseract"/"vision" always overrides the configured default for this call.',
4231
4240
  },
4232
4241
  },
4233
4242
  additionalProperties: false,
@@ -4236,7 +4245,7 @@ ctx.logger?.info(
4236
4245
  async execute(args, exec) {
4237
4246
  const imageInput = resolveOcrImageInput(args)
4238
4247
  const session = exec?.agent?.session
4239
- const engine = resolveVisionOcrEngine(args.engine)
4248
+ const engine = resolveVisionOcrEngine(args.engine, current().ocrEngine)
4240
4249
  const degraded = degradedLocalState(session, imageInput)
4241
4250
  if (
4242
4251
  engine !== 'vision' &&
@@ -4465,8 +4474,11 @@ ctx.logger?.info(
4465
4474
  used = 'failed'
4466
4475
  text = ''
4467
4476
  } else {
4468
- const retryText = retry.text.trim()
4469
- if (retryText !== '') text = retryText
4477
+ // An ok retry that came back blank means the stricter prompt
4478
+ // found no visible text. The first answer was already judged
4479
+ // a hallucination (12k+ chars) — keeping it here would
4480
+ // publish it as engine-verified. Same contract as EMPTY below.
4481
+ text = retry.text.trim()
4470
4482
  used = 'vision'
4471
4483
  }
4472
4484
  } else {