dsh-vision-router 3.0.0 → 3.0.1
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 +8 -2
- package/README.zh.md +6 -2
- package/docs/architecture/3.0-r11-adversarial-review.md +11 -5
- package/docs/architecture/dsh-support-window.md +8 -0
- package/docs/releases/v3.0.1.md +77 -0
- package/index.js +2 -0
- package/lib/core-primitives.js +8 -1
- package/lib/local-vision-stabilizer.js +2 -1
- package/lib/runtime-composition.js +8 -6
- package/lib/settings-client-017-compat.js +7 -3
- package/lib/vision-background-benchmark.js +14 -2
- package/lib/vision-diagnostics-routes.js +9 -1
- package/lib/vision-model-visibility-boundary-main.js +15 -16
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -42,9 +42,15 @@
|
|
|
42
42
|
> **Data leaves your machine by default.** When a cloud vision model is used, Vision Router sends the image (or a derived crop), the vision prompt and related request metadata to that provider. A fresh install has an anonymous OVHcloud vision fallback enabled, so "free" and "no key" do **not** mean offline. Do not use the cloud chain for confidential, regulated or classified material. See [Data flow and strict local-only use](#data-flow-and-strict-local-only-use).
|
|
43
43
|
|
|
44
44
|
> [!WARNING]
|
|
45
|
-
> 📌 **Announcement (v3.0.
|
|
45
|
+
> 📌 **Announcement (v3.0.1)**
|
|
46
46
|
>
|
|
47
|
-
> **v3.0.
|
|
47
|
+
> **v3.0.1: five corrective fixes on the 3.0 line.** The Vision Router settings surface
|
|
48
|
+
> reads and writes real values on the Desktop shell, the model picker no longer groups the
|
|
49
|
+
> same model twice, and every provider leg that can reach a remote provider — background
|
|
50
|
+
> profiling, the local vision stabilizer, the settings "test connection" probe and the
|
|
51
|
+
> LM Studio native transport — now follows the same `proxy` / `proxyHosts` decision as
|
|
52
|
+
> foreground vision turns. Supported Hosts are unchanged: DSH 0.1.x from `0.1.5-rc.1`,
|
|
53
|
+
> DSH 0.2.x from verified `0.2.0-rc.2`. [What’s new →](docs/releases/v3.0.1.md)
|
|
48
54
|
|
|
49
55
|
<p align="center">
|
|
50
56
|
<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" />
|
package/README.zh.md
CHANGED
|
@@ -42,9 +42,13 @@
|
|
|
42
42
|
> **默认配置会让数据出网。** 使用云端视觉模型时,Vision Router 会将图片(或由它裁剪出的局部)、识图提示词及相关请求元数据发送给对应供应商。新安装默认开启 OVHcloud 匿名视觉兜底,因此“免费”和“免 Key”不等于离线。涉密、涉案、内部或其他受限材料请勿使用云端链路。详见[数据流向与严格纯本地配置](#数据流向与严格纯本地配置)。
|
|
43
43
|
|
|
44
44
|
> [!WARNING]
|
|
45
|
-
> 📌 **公告(v3.0.
|
|
45
|
+
> 📌 **公告(v3.0.1)**
|
|
46
46
|
>
|
|
47
|
-
> **v3.0.
|
|
47
|
+
> **v3.0.1:3.0 线上的五处修正。** Desktop 壳上的 Vision Router 设置面能读取并写入真实值,
|
|
48
|
+
> 模型选择器不再把同一模型重复分组;所有可能触达远程 provider 的腿 —— 后台基准分析、本地视觉
|
|
49
|
+
> 稳定器、设置里的「测试连接」探针、LM Studio native 传输 —— 现在都与前台视觉轮次遵守同一套
|
|
50
|
+
> `proxy` / `proxyHosts` 判定。支持的 Host 不变:DSH 0.1.x 自 `0.1.5-rc.1` 起,DSH 0.2.x 自
|
|
51
|
+
> 已验证的 `0.2.0-rc.2` 起。 [查看完整更新 →](docs/releases/v3.0.1.md)
|
|
48
52
|
|
|
49
53
|
<p align="center">
|
|
50
54
|
<img src="assets/vision-demo.gif" width="640" alt="演示:粘贴图片,Agent 用 vision_ground / vision_crop / vision_pixel_diff 定位发送按钮并给出坐标" />
|
|
@@ -425,11 +425,17 @@ keeps a guarding test here** except the two noted under residual risk.
|
|
|
425
425
|
mechanism in turn (both edits fail the test, restoring passes). It is wired into
|
|
426
426
|
`pnpm test`, so a regression now fails in the ordinary battery instead of only in
|
|
427
427
|
a real-Host desktop gate.
|
|
428
|
-
2. ~~conditional proxy bypass in the provider probes~~ — **closed in this round
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
turns
|
|
428
|
+
2. ~~conditional proxy bypass in the provider probes~~ — **closed in this round,
|
|
429
|
+
and completed afterwards**: the probes take the Router-owned provider transport
|
|
430
|
+
(`runtime.providerTransport` handed to the diagnostics routes), which owns the
|
|
431
|
+
`proxy` / `proxyHosts` decision, so a configured `proxy` reaches them exactly as
|
|
432
|
+
it reaches vision turns — for every provider shape. The first shape of this fix
|
|
433
|
+
ran the probes inside the legacy configured-pair scope, which only covers
|
|
434
|
+
non-router-owned providers; a `vision-http` direct backend (the plugin's default)
|
|
435
|
+
therefore still probed with ambient fetch (#633). The legacy boundary fetch is
|
|
436
|
+
kept as the fallback for Hosts that only configure the legacy pair scope, and the
|
|
437
|
+
same transport now also reaches the LM Studio **native** transport leg, which had
|
|
438
|
+
dropped it (#634). The first attempt resolved `globalThis.fetch` at call time and was
|
|
433
439
|
**rejected by the project's own `L1-sealed-process-global` rule** — the same
|
|
434
440
|
class as findings 1 and #519 — so the fix instead has the boundary own and
|
|
435
441
|
advertise its wrapper (`currentLegacyGlobalProxyFetch()`), keeping every
|
|
@@ -81,6 +81,14 @@ Version labels describe support policy and CI evidence; runtime branching still
|
|
|
81
81
|
|
|
82
82
|
DVR must not turn these tables into widespread version-string conditionals. Runtime compatibility continues to feature-detect the concrete Host seam it needs. If a capability cannot be proven safely, the compatibility path fails open or reports an explicit unsupported/unknown state according to that seam's contract.
|
|
83
83
|
|
|
84
|
+
The same rule binds the contract gate. `scripts/dsh-host-contract-smoke.mjs` derives the settings
|
|
85
|
+
seam from the Host it is pointed at (`EXPECT_SETTINGS_MODE=auto`): the `0.1.5` train exposes
|
|
86
|
+
`SettingsProvider.register()`, while the `0.1.7` release and every `0.2.x` Host since — `0.2.0-rc.2`
|
|
87
|
+
through the `0.2.1` alpha line — replace it with `SettingsForms.describe()` plus ConfigEditor
|
|
88
|
+
`configuration()`/`edit()`. A gate that pins one shape reports an unsupported Host for a Host DVR
|
|
89
|
+
supports, so the floating canaries derive the seam, the pinned legs keep naming theirs explicitly,
|
|
90
|
+
and a Host with neither reviewed seam fails the gate by name instead of passing silently.
|
|
91
|
+
|
|
84
92
|
## Compatibility-retirement rule
|
|
85
93
|
|
|
86
94
|
The 2.3.x `0.1.5` train floor makes any compatibility path used only by pre-`0.1.5` Hosts eligible for a fresh deletion audit, but does not automatically authorize deletion. Durable session formats, replay envelopes, adapter wire shapes, and other historical inputs may outlive the Host version that originally produced them.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# v3.0.1
|
|
2
|
+
|
|
3
|
+
DSH Vision Router 3.0.1 is a corrective release on the 3.0 line. It ships the five
|
|
4
|
+
consumer-visible fixes that were merged after v3.0.0 was tagged: two in the Desktop
|
|
5
|
+
settings surface and three in the provider egress paths, where a configured `proxy` /
|
|
6
|
+
`proxyHosts` must reach every leg that talks to a provider. There are no new peers, no
|
|
7
|
+
settings migration, no Session format change and no public API change.
|
|
8
|
+
|
|
9
|
+
## Highlights
|
|
10
|
+
|
|
11
|
+
- **Desktop settings values (#619).** A Host that exposes a legacy-shaped
|
|
12
|
+
`settingsScope` can return an empty `vision-router` namespace while its native config
|
|
13
|
+
forms keep working. That scope is now kept only as the delegate for every other
|
|
14
|
+
namespace instead of bypassing the local settings bridge, so the Vision Router
|
|
15
|
+
settings surface reads and writes real values on the Desktop shell.
|
|
16
|
+
- **Model picker catalog (#620).** The model-visibility boundary now patches every
|
|
17
|
+
loader instance it can reach — including one published after the boundary installs —
|
|
18
|
+
so the picker no longer groups the same model twice.
|
|
19
|
+
- **Background and local provider legs (#623).** The Router-owned provider transport is
|
|
20
|
+
threaded into the local vision stabilizer, the host/security boundaries and the
|
|
21
|
+
background benchmark, so those legs honor `proxy` / `proxyHosts` exactly like
|
|
22
|
+
foreground vision turns.
|
|
23
|
+
- **Connection probe egress (#633).** The settings "test connection" probe now takes the
|
|
24
|
+
Router-owned transport (`runtime.providerTransport`) instead of relying on the legacy
|
|
25
|
+
configured-pair scope, which by construction cannot cover a `vision-http` direct
|
|
26
|
+
backend — the plugin's default shape. The legacy boundary fetch stays as the fallback
|
|
27
|
+
for Hosts that only configure the legacy scope.
|
|
28
|
+
- **LM Studio native transport (#634).** `callLocalBackend`'s `format: 'lmstudio'`
|
|
29
|
+
branch no longer drops `providerTransport`, and the native `POST /api/v1/chat` goes
|
|
30
|
+
through `transport.fetch`, matching the openai and anthropic legs. A remote LM Studio
|
|
31
|
+
behind a proxy is reached like every other provider.
|
|
32
|
+
- **Internal hardening (no package behavior change).** Exact Node-runtime and Playwright
|
|
33
|
+
system-package caches, Desktop adversary sharding and scenario concurrency, a Host
|
|
34
|
+
contract gate that derives the settings seam from the Host it meets, an alpha canary
|
|
35
|
+
that runs every contract instead of stopping at the first failure, and completed e2e
|
|
36
|
+
workflow trigger coverage.
|
|
37
|
+
|
|
38
|
+
## Host support window
|
|
39
|
+
|
|
40
|
+
Unchanged from 3.0.0:
|
|
41
|
+
|
|
42
|
+
- DSH 0.1.x: `>=0.1.5-rc.1 <0.2.0-0`
|
|
43
|
+
- DSH 0.2.x: `>=0.2.0-rc.2 <0.3.0-0`
|
|
44
|
+
- ordinary development Host: exact `0.2.0-rc.2`
|
|
45
|
+
|
|
46
|
+
The 0.2.x train is admitted from the verified `0.2.0-rc.2` boundary. The `0.2.1` alpha
|
|
47
|
+
line is inside that admitted range and is exercised by the scheduled drift canaries,
|
|
48
|
+
which read the settings seam from the Host they install; the exact-evidence boundary is
|
|
49
|
+
still `0.2.0-rc.2`.
|
|
50
|
+
|
|
51
|
+
## Validation
|
|
52
|
+
|
|
53
|
+
- every fix carries a failing-first reproduction that fails on the pre-fix commit and
|
|
54
|
+
passes on this release commit — the Desktop settings and picker boundaries, the local
|
|
55
|
+
and background transport legs, the `vision-http` probe, and the LM Studio native
|
|
56
|
+
transport;
|
|
57
|
+
- the full gate battery on the exact release commit: install, build, `build:check`,
|
|
58
|
+
source-ownership lint, source→artifact evidence, reproducible clean build, typecheck,
|
|
59
|
+
the test suite, client-source synchronization, the Host support-window contract, and
|
|
60
|
+
the packed public-API contract;
|
|
61
|
+
- a real-Host pass on this exact build against an installed DSH checkout: the Host proxy
|
|
62
|
+
egress contract, the settings lifecycle in a real browser (mount, save, reload and
|
|
63
|
+
readback of the Vision Router section) and the Desktop Host injection contract
|
|
64
|
+
(structured injections, token exchange, authenticated index and DVR RPC);
|
|
65
|
+
- the real-Host matrix (Windows Node 22/24 Desktop, macOS renderer, Linux real Host +
|
|
66
|
+
Chromium), the adversarial compatibility/fuzz gates and the resource-stress gates;
|
|
67
|
+
- an adversarial review of this delta, including a provider-egress sweep over every
|
|
68
|
+
server-side entry point. The one candidate that looked like a further bypass — Ollama
|
|
69
|
+
cold start — is gated to loopback hosts and was recorded as falsified rather than
|
|
70
|
+
patched.
|
|
71
|
+
|
|
72
|
+
## Upgrade
|
|
73
|
+
|
|
74
|
+
Drop-in replacement for 3.0.0: no settings migration, no Session format change and no
|
|
75
|
+
new peer dependency. Upgrading `dsh plugin --profile web add github:ysr666/dsh-vision-router`
|
|
76
|
+
(or the pinned `dsh-vision-router@3.0.1`) keeps existing Vision Router settings and
|
|
77
|
+
Session data readable as before.
|
package/index.js
CHANGED
|
@@ -4849,6 +4849,8 @@ ctx.logger?.info(
|
|
|
4849
4849
|
// only the three coherent domain faces it already computes; route lifecycle,
|
|
4850
4850
|
// bounded /models probing and JSON response semantics live outside Core.
|
|
4851
4851
|
installVisionDiagnosticsRoutes(ctx, {
|
|
4852
|
+
// Same egress as real vision turns: the Router-owned provider transport.
|
|
4853
|
+
transport: runtime?.providerTransport,
|
|
4852
4854
|
connection: {
|
|
4853
4855
|
candidatePairs: pairs,
|
|
4854
4856
|
localBackends: () => localProvidersOf(current()),
|
package/lib/core-primitives.js
CHANGED
|
@@ -1937,7 +1937,11 @@ async function callLmStudioNative(provider, messages, options = {}) {
|
|
|
1937
1937
|
...(typeof options.temperature === 'number' ? { temperature: options.temperature } : {}),
|
|
1938
1938
|
...(typeof options.top_p === 'number' ? { top_p: options.top_p } : {}),
|
|
1939
1939
|
}
|
|
1940
|
-
const
|
|
1940
|
+
const transport = options.providerTransport
|
|
1941
|
+
const requestFetch = typeof transport?.fetch === 'function'
|
|
1942
|
+
? (input, init) => transport.fetch(input, init, { providerName: provider.name, allowProxy: true })
|
|
1943
|
+
: fetch
|
|
1944
|
+
const response = await requestFetch(`${apiRoot}/api/v1/chat`, {
|
|
1941
1945
|
method: 'POST',
|
|
1942
1946
|
headers: { 'content-type': 'application/json' },
|
|
1943
1947
|
body: JSON.stringify(body),
|
|
@@ -1984,6 +1988,9 @@ export async function callLocalBackend(provider, messages, options = {}) {
|
|
|
1984
1988
|
return callLmStudioNative(provider, messages, {
|
|
1985
1989
|
maxTokens,
|
|
1986
1990
|
signal: options.signal,
|
|
1991
|
+
// The native LM Studio transport is a provider leg like the openai/anthropic
|
|
1992
|
+
// ones: it must use the Router-owned transport so proxy/proxyHosts apply.
|
|
1993
|
+
providerTransport: options.providerTransport,
|
|
1987
1994
|
...(typeof provider.reasoningEffort === 'string' ? { reasoningEffort: provider.reasoningEffort } : {}),
|
|
1988
1995
|
...sampling,
|
|
1989
1996
|
})
|
|
@@ -43,7 +43,7 @@ export async function triggerDesktopScreenshotPermission({
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export function installLocalVisionStabilizer(ctx, config = {}, core) {
|
|
46
|
+
export function installLocalVisionStabilizer(ctx, config = {}, core, installOptions = {}) {
|
|
47
47
|
config = normalizeRuntimeVisionConfig(config)
|
|
48
48
|
if (!ctx || typeof ctx !== 'object') return { ctx, bootConfig: config }
|
|
49
49
|
|
|
@@ -270,6 +270,7 @@ export function installLocalVisionStabilizer(ctx, config = {}, core) {
|
|
|
270
270
|
const text = await core.callLocalBackend(local, await localMessages(options), {
|
|
271
271
|
maxTokens: local.maxTokens ?? 4096,
|
|
272
272
|
signal: options.signal,
|
|
273
|
+
providerTransport: installOptions?.providerTransport,
|
|
273
274
|
resolveCredential,
|
|
274
275
|
})
|
|
275
276
|
if (text !== '') {
|
|
@@ -98,7 +98,7 @@ function legacyCoreVisionSettings(ctx, fallback) {
|
|
|
98
98
|
return { ...current, autoActivateOnImage: false }
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
function installHostAndSecurityBoundaries(ctx, config, core) {
|
|
101
|
+
function installHostAndSecurityBoundaries(ctx, config, core, providerTransport) {
|
|
102
102
|
// SessionVisionIndex calls planGuardStopShadows before Core.apply. Keep that
|
|
103
103
|
// one helper behind the live-locale facade; the final Core itself still gets
|
|
104
104
|
// the ordinary composition identity and is localized by the scoped context.
|
|
@@ -144,6 +144,7 @@ function installHostAndSecurityBoundaries(ctx, config, core) {
|
|
|
144
144
|
ollamaColdStartCtx,
|
|
145
145
|
hardenedConfig,
|
|
146
146
|
core,
|
|
147
|
+
{ providerTransport },
|
|
147
148
|
)
|
|
148
149
|
|
|
149
150
|
const routingProduct = resolveVisionRoutingProduct(bootConfig)
|
|
@@ -260,7 +261,7 @@ function createRuntimeOwners(host, core) {
|
|
|
260
261
|
}
|
|
261
262
|
}
|
|
262
263
|
|
|
263
|
-
function installRoutingAndHostProducts(host, owners, core) {
|
|
264
|
+
function installRoutingAndHostProducts(host, owners, core, providerTransport) {
|
|
264
265
|
const { capabilityStore, logging, runtimeConfig, runtimePerformanceStore } = host
|
|
265
266
|
const { sessionVisionModeCompat } = owners
|
|
266
267
|
// Final structured-flow guard sits closest to core.apply so it sees the
|
|
@@ -281,7 +282,7 @@ function installRoutingAndHostProducts(host, owners, core) {
|
|
|
281
282
|
runtimeConfig,
|
|
282
283
|
core,
|
|
283
284
|
capabilityStore,
|
|
284
|
-
{ logger: logging.logger },
|
|
285
|
+
{ logger: logging.logger, providerTransport },
|
|
285
286
|
)
|
|
286
287
|
const sessionTurnResolver = createSessionTurnResolver(backgroundProfiling.ctx)
|
|
287
288
|
const sessionEventTailReader = createSessionEventTailReader(backgroundProfiling.ctx)
|
|
@@ -479,9 +480,10 @@ function applyMatureCoreBridge(host, owners, routing, execution, core, runtime)
|
|
|
479
480
|
}
|
|
480
481
|
|
|
481
482
|
export function applyVisionRuntimeComposition(ctx, config = {}, core, runtime = {}) {
|
|
482
|
-
const
|
|
483
|
+
const providerTransport = runtime?.providerTransport
|
|
484
|
+
const host = installHostAndSecurityBoundaries(ctx, config, core, providerTransport)
|
|
483
485
|
const owners = createRuntimeOwners(host, core)
|
|
484
|
-
const routing = installRoutingAndHostProducts(host, owners, core)
|
|
485
|
-
const execution = installExecutionBoundaries(host, owners, routing, core,
|
|
486
|
+
const routing = installRoutingAndHostProducts(host, owners, core, providerTransport)
|
|
487
|
+
const execution = installExecutionBoundaries(host, owners, routing, core, providerTransport)
|
|
486
488
|
return applyMatureCoreBridge(host, owners, routing, execution, core, runtime)
|
|
487
489
|
}
|
|
@@ -197,13 +197,17 @@ export const SETTINGS_017_CLIENT_PRELUDE = String.raw`(function(){
|
|
|
197
197
|
get: function(target, property) {
|
|
198
198
|
if (property === 'settingsScope') {
|
|
199
199
|
var original = safeGet(target, 'settingsScope');
|
|
200
|
-
if (original && typeof original.bind === 'function') return original;
|
|
201
200
|
// DSH 0.1.7 configForms only mirrors Config fields declared volatile.
|
|
202
201
|
// DVR must keep its public Config ordinary for the older supported Host
|
|
203
202
|
// window, so its namespace intentionally uses the local-only ConfigEditor
|
|
204
|
-
// bridge
|
|
203
|
+
// bridge. Even when a Host exposes a legacy-shaped settingsScope, its
|
|
204
|
+
// vision-router view may be empty; keep it only as the delegate for
|
|
205
|
+
// every other namespace instead of letting it bypass the local bridge.
|
|
205
206
|
var official = configFormsBinder(target);
|
|
206
|
-
return syntheticBinder(
|
|
207
|
+
return syntheticBinder(
|
|
208
|
+
ctx,
|
|
209
|
+
original && typeof original.bind === 'function' ? original : official
|
|
210
|
+
);
|
|
207
211
|
}
|
|
208
212
|
if (property === 'get') {
|
|
209
213
|
var getter = Reflect.get(target, property, target);
|
|
@@ -758,7 +758,7 @@ export function createBackgroundCapabilityProfiler({
|
|
|
758
758
|
}, interval)
|
|
759
759
|
try { policyTimer?.unref?.() } catch {}
|
|
760
760
|
|
|
761
|
-
const runner = runAxisBenchmark ??
|
|
761
|
+
const runner = runAxisBenchmark ?? runAxis
|
|
762
762
|
await runner({
|
|
763
763
|
ctx,
|
|
764
764
|
config: current,
|
|
@@ -768,6 +768,7 @@ export function createBackgroundCapabilityProfiler({
|
|
|
768
768
|
axis: work.axis,
|
|
769
769
|
signal: controller.signal,
|
|
770
770
|
logger,
|
|
771
|
+
options: invokerOptions,
|
|
771
772
|
onProgress(progress = {}) {
|
|
772
773
|
if (!runningWork || runningWork.candidate.key !== work.candidate.key || runningWork.axis !== work.axis) return
|
|
773
774
|
const completed = Math.max(0, Number(progress.completed) || 0)
|
|
@@ -999,6 +1000,16 @@ export function installBackgroundCapabilityProfiling(ctx, config, core, store, o
|
|
|
999
1000
|
const logger = options.logger ?? ctx?.logger
|
|
1000
1001
|
const imageVerdictStore = options.imageVerdictStore ?? createImageInputVerdictStore({ logger })
|
|
1001
1002
|
const backgroundStopStore = options.backgroundStopStore ?? createBackgroundBenchmarkStopStore({ logger })
|
|
1003
|
+
// Provider transport is one explicit runtime capability shared by automatic
|
|
1004
|
+
// profiling and the user-triggered exact check. Top-level ownership wins so
|
|
1005
|
+
// a stale nested test/customization bag cannot silently bypass live proxy
|
|
1006
|
+
// policy after composition or HMR changes.
|
|
1007
|
+
const invokerOptions = {
|
|
1008
|
+
...(options.invokerOptions ?? {}),
|
|
1009
|
+
...(options.providerTransport === undefined
|
|
1010
|
+
? {}
|
|
1011
|
+
: { providerTransport: options.providerTransport }),
|
|
1012
|
+
}
|
|
1002
1013
|
const profiler = createBackgroundCapabilityProfiler({
|
|
1003
1014
|
ctx,
|
|
1004
1015
|
config,
|
|
@@ -1006,6 +1017,7 @@ export function installBackgroundCapabilityProfiling(ctx, config, core, store, o
|
|
|
1006
1017
|
store,
|
|
1007
1018
|
logger,
|
|
1008
1019
|
...options,
|
|
1020
|
+
invokerOptions,
|
|
1009
1021
|
imageVerdictStore,
|
|
1010
1022
|
backgroundStopStore,
|
|
1011
1023
|
})
|
|
@@ -1120,7 +1132,7 @@ export function installBackgroundCapabilityProfiling(ctx, config, core, store, o
|
|
|
1120
1132
|
provider: body.provider,
|
|
1121
1133
|
model: body.model,
|
|
1122
1134
|
signal: AbortSignal.timeout(VISION_CHECK_TIMEOUT_MS),
|
|
1123
|
-
invokerOptions
|
|
1135
|
+
invokerOptions,
|
|
1124
1136
|
})
|
|
1125
1137
|
await profiler.recordImageSupported(body.provider, body.model)
|
|
1126
1138
|
sendJson(res, 200, result)
|
|
@@ -106,7 +106,15 @@ export function installVisionDiagnosticsRoutes(ctx, options = {}) {
|
|
|
106
106
|
// inside the adapter's proxy scope) do not have. Use the fetch the boundary
|
|
107
107
|
// currently owns, with the module-load capture as the fallback.
|
|
108
108
|
const injectedFetch = typeof options.fetchImpl === 'function' ? options.fetchImpl : undefined
|
|
109
|
-
|
|
109
|
+
// Probes must describe the egress real vision turns use. That egress is the
|
|
110
|
+
// Router-owned provider transport, which also owns the proxy/proxyHosts decision;
|
|
111
|
+
// the legacy pair scope below only covers non-router-owned providers, so a
|
|
112
|
+
// vision-http direct backend would otherwise probe with ambient fetch.
|
|
113
|
+
const transport = options.transport
|
|
114
|
+
const transportFetch = typeof transport?.fetch === 'function'
|
|
115
|
+
? (input, init) => transport.fetch(input, init, { allowProxy: true })
|
|
116
|
+
: undefined
|
|
117
|
+
const resolveFetch = () => injectedFetch ?? transportFetch ?? currentLegacyGlobalProxyFetch() ?? moduleFetch
|
|
110
118
|
const connectionConfig = () => {
|
|
111
119
|
try {
|
|
112
120
|
const live = ctx?.get?.('settings')?.get?.('vision-router')
|
|
@@ -419,6 +419,7 @@ export const VISION_MODEL_VISIBILITY_PRELUDE = String.raw`(function(){
|
|
|
419
419
|
function create() {
|
|
420
420
|
var result = originalCreate.apply(this, arguments);
|
|
421
421
|
patchLoader(loader);
|
|
422
|
+
if (result && result !== loader) patchLoader(result);
|
|
422
423
|
return result;
|
|
423
424
|
}
|
|
424
425
|
try { Object.defineProperty(create, '__visionRouterModelVisibility', { value: true }); } catch (_) {}
|
|
@@ -427,31 +428,29 @@ export const VISION_MODEL_VISIBILITY_PRELUDE = String.raw`(function(){
|
|
|
427
428
|
}
|
|
428
429
|
|
|
429
430
|
function install() {
|
|
430
|
-
if (window.__ModuleLoader__) {
|
|
431
|
-
patchLoader(window.__ModuleLoader__);
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
431
|
var descriptor = Object.getOwnPropertyDescriptor(window, '__ModuleLoader__');
|
|
432
|
+
var current;
|
|
433
|
+
try { current = window.__ModuleLoader__; } catch (_) { current = undefined; }
|
|
434
|
+
if (current) patchLoader(current);
|
|
435
435
|
if (descriptor && descriptor.configurable === false) return;
|
|
436
|
-
var
|
|
436
|
+
var previousGet = descriptor && descriptor.get;
|
|
437
|
+
var previousSet = descriptor && descriptor.set;
|
|
438
|
+
var stored = descriptor && Object.prototype.hasOwnProperty.call(descriptor, 'value')
|
|
439
|
+
? descriptor.value
|
|
440
|
+
: current;
|
|
437
441
|
Object.defineProperty(window, '__ModuleLoader__', {
|
|
438
442
|
configurable: true,
|
|
439
|
-
enumerable:
|
|
440
|
-
get: function(){ return stored; },
|
|
443
|
+
enumerable: !descriptor || descriptor.enumerable !== false,
|
|
444
|
+
get: function(){ return previousGet ? previousGet.call(window) : stored; },
|
|
441
445
|
set: function(value) {
|
|
442
|
-
stored = value;
|
|
443
|
-
patchLoader(value);
|
|
444
|
-
Object.defineProperty(window, '__ModuleLoader__', {
|
|
445
|
-
configurable: true,
|
|
446
|
-
enumerable: true,
|
|
447
|
-
writable: true,
|
|
448
|
-
value: stored
|
|
449
|
-
});
|
|
446
|
+
if (previousSet) previousSet.call(window, value); else stored = value;
|
|
447
|
+
try { patchLoader(previousGet ? previousGet.call(window) : value); } catch (_) {}
|
|
450
448
|
}
|
|
451
449
|
});
|
|
450
|
+
if (stored) patchLoader(stored);
|
|
452
451
|
}
|
|
453
452
|
|
|
454
|
-
install();
|
|
453
|
+
try { install(); } catch (_) {}
|
|
455
454
|
})();`
|
|
456
455
|
|
|
457
456
|
export function injectVisionModelVisibilityBoundary(html) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vision-router",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Eyes for text-only DeepSeek Harness agents: built-in free vision chain + pixel-level tools. Remote vision providers, including the default free fallback, receive image content unless strict local-only use is configured.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"@deepseek-ai/dsh-storage-domain": "0.2.0-rc.2"
|
|
90
90
|
},
|
|
91
91
|
"scripts": {
|
|
92
|
-
"test": "node --test tests/index-modularization.test.js tests/adapter-prepare-call-compat.test.js tests/core.test.js tests/issue-374-delegated-call-config.test.js tests/grounding-coordinate-frame.test.js tests/grounding-coordinate-runtime.test.js tests/capability-advisory.test.js tests/vision-execution-policy.test.js tests/vision-backend-diagnostics.test.js tests/live-model-discovery.test.js tests/cache-atomic-write-concurrency.test.js tests/live-model-credential-resolution.test.js tests/vision-model-registry.test.js tests/live-model-client-stability.test.js tests/providers-persistence.test.js tests/provider-directory-fallback.test.js tests/model-catalog-policy.test.js tests/settings-ia-client-prelude.test.js tests/settings-ia-fj.test.js tests/settings-ia-acceptance-regression.test.js tests/settings-migration.test.js tests/settings-section-order.test.js tests/attachment-admission-policy.test.js tests/vision-resilience.test.js tests/degraded-local-evidence.test.js tests/vision-resilience-lifecycle.test.js tests/vision-breaker-readonly.test.js tests/alpha1-browser-lifecycle-integration.test.js tests/issue-367-remote-session-inject.test.js tests/vision-mode-toggle-injection.test.js tests/client.test.js tests/issue-307-regression.test.js tests/issue-284-vision-mode-toggle.test.js tests/issue-284-vision-mode-hardening.test.js tests/issue-284-attachment-id-hint.test.js tests/issue-284-model-visibility.test.js tests/issue-284-vision-selection-effort.test.js tests/client-presentation-boundary.test.js tests/clipboard-image-paste-compat.test.js tests/remote-settings-bridge.test.js tests/remote-settings-v2-contract.test.js tests/remote-settings-risk-confirmation.test.js tests/local-remote-settings-permission.test.js tests/artifact-path-security.test.js tests/http-compat.test.js tests/catalog-corrections.test.js tests/release-registry-identity.test.js tests/update-check.test.js tests/update-check-signal-lifecycle.test.js tests/self-update.test.js tests/doctor.test.js tests/doctor-cli.test.js tests/legacy-session-repair.test.js tests/profile-pnpm-diagnostics.test.js tests/doctor-v2.test.js tests/doctor-cli-v2.test.js tests/doctor-runtime.test.js tests/dsh-host-capabilities.test.js tests/doctor-host-capabilities.test.js tests/session-repair-v2.test.js tests/activation-shim-contract.test.js tests/bundle-defaults.test.js tests/file-logger.test.js tests/official-deepseek-catalog.test.js tests/replay-delegation.test.js tests/twin-image-capability-fallback.test.js tests/twin-image-custom-wrapper.test.js tests/adversarial-hardening.test.js tests/vision-adversarial-hardening-v2.test.js tests/vision-capability-benchmark-visual-proof.test.js tests/wrapper-directory.test.js tests/logging-ui.test.js tests/manifest-dependencies.test.js tests/architecture-2.3-gate.test.js tests/esm-cycle-audit.test.js tests/structured-bootstrap.test.js tests/structured-bootstrap-gate.test.js tests/vision-model-guidance-contract.test.js tests/local-ollama.test.js tests/local-only-vision.test.js tests/ollama-cold-start.test.js tests/ollama-cold-start-loaded.test.js tests/zero-regression-gate.test.js tests/runtime-e2e.test.js tests/local-vision-stabilizer.test.js tests/local-connection-probe.test.js tests/vision-diagnostics-routes.test.js tests/repetition-guard.test.js tests/guide-scroll-gate.test.js tests/settings-scroll-jank-regression.test.js tests/free-cloud-first.test.js tests/dsh-host-compat.test.js tests/native-image-coexistence.test.js tests/issue-276-session-image-ownership.test.js tests/issue-276-entry-policy-bridge.test.js tests/issue-276-policy-hardening.test.js tests/issue-289-native-nonintervention.test.js tests/issue-512-tool-restriction.test.js tests/issue-606-session-source-ownership.test.js tests/pi-ai-bridge-wire-compat.test.js tests/fetch-wrapper-lifecycle.test.js tests/fetch-wrapper-composition.test.js tests/provider-probe-proxy-scope.test.js tests/lifecycle-invariants.test.js tests/vision-tool-settings-generation.test.js tests/release-package-content-identity.test.js tests/release-state-machine.test.js tests/mixed-router.test.js tests/depth-tier.test.js tests/depth-quota-behavior.test.js tests/structured-flow-hardening.test.js tests/structured-flow-adversarial.test.js tests/vision-budget-activation.test.js tests/runtime-boundary-fixes.test.js tests/security-resource-boundaries.test.js tests/security-property-fuzz.test.js tests/security-adversarial-fuzz-contract.test.js tests/runtime-i18n.test.js tests/long-ocr-empty-retry.test.js tests/tesseract-adaptive-ocr.test.js tests/tesseract-node24-boot.test.js tests/session-vision-state.test.js tests/session-vision-state-integration.test.js tests/session-vision-event-feed.test.js tests/session-vision-policy.test.js tests/session-vision-policy-domain.test.js tests/session-vision-delegation.test.js tests/session-vision-delegation-boundary.test.js tests/subagent-vision-inheritance-characterization.test.js tests/subagent-vision-runtime-integration.test.js tests/subagent-vision-cold-resume.test.js tests/image-resource-governor.test.js tests/resource-retention-lifecycle.test.js tests/pixel-diff-stream.test.js tests/large-image-resource-integration.test.js tests/structured-guard-idempotency.test.js tests/vision-routing-product.test.js tests/vision-runtime-performance.test.js tests/vision-routing-settings-prelude.test.js tests/v2-settings-ia-integration.test.js tests/vision-capability-router.test.js tests/vision-capability-reference.test.js tests/vision-capability-benchmark.test.js tests/vision-capability-grounding-proof-contract.test.js tests/vision-capability-probe.test.js tests/vision-capability-axis-freshness.test.js tests/vision-capability-shadow-health.test.js tests/vision-capability-benchmark-service.test.js tests/vision-capability-preflight-hardening.test.js tests/vision-capability-benchmark-contract.test.js tests/vision-capability-benchmark-client.test.js tests/vision-capability-benchmark-client-productization.test.js tests/vision-capability-adapter-route.test.js tests/vision-background-benchmark.test.js tests/vision-background-lifecycle.test.js tests/vision-background-benchmark-productization.test.js tests/vision-capability-benchmark-budget.test.js tests/vision-image-input-verdict.test.js tests/vision-capability-failure-classification.test.js tests/vision-capability-gate-client.test.js tests/v2-product-review-fixes.test.js tests/qa-top5-reliability.test.js tests/qa-screenshot-runtime.test.js tests/qa-runtime-identity.test.js tests/qa-turn-budget-cancellation.test.js tests/qa-cancellation-publication.test.js tests/qa-reliability-tail.test.js tests/qa-endpoint-route-alias.test.js tests/settings-native-card-semantics.test.js tests/settings-native-card-lazy-data.test.js tests/settings-invalid-staged-dirty.test.js tests/vision-toggle-root-hardening.test.js && pnpm test:regression-closure && node --test tests/vision-backend-runtime-policy.test.js",
|
|
92
|
+
"test": "node --test tests/index-modularization.test.js tests/adapter-prepare-call-compat.test.js tests/core.test.js tests/issue-374-delegated-call-config.test.js tests/grounding-coordinate-frame.test.js tests/grounding-coordinate-runtime.test.js tests/capability-advisory.test.js tests/vision-execution-policy.test.js tests/vision-backend-diagnostics.test.js tests/live-model-discovery.test.js tests/cache-atomic-write-concurrency.test.js tests/live-model-credential-resolution.test.js tests/vision-model-registry.test.js tests/live-model-client-stability.test.js tests/providers-persistence.test.js tests/provider-directory-fallback.test.js tests/model-catalog-policy.test.js tests/settings-ia-client-prelude.test.js tests/settings-ia-fj.test.js tests/settings-ia-acceptance-regression.test.js tests/settings-migration.test.js tests/settings-section-order.test.js tests/attachment-admission-policy.test.js tests/vision-resilience.test.js tests/degraded-local-evidence.test.js tests/vision-resilience-lifecycle.test.js tests/vision-breaker-readonly.test.js tests/alpha1-browser-lifecycle-integration.test.js tests/issue-367-remote-session-inject.test.js tests/vision-mode-toggle-injection.test.js tests/client.test.js tests/issue-307-regression.test.js tests/issue-284-vision-mode-toggle.test.js tests/issue-284-vision-mode-hardening.test.js tests/issue-284-attachment-id-hint.test.js tests/issue-284-model-visibility.test.js tests/issue-284-vision-selection-effort.test.js tests/client-presentation-boundary.test.js tests/clipboard-image-paste-compat.test.js tests/remote-settings-bridge.test.js tests/remote-settings-v2-contract.test.js tests/remote-settings-risk-confirmation.test.js tests/local-remote-settings-permission.test.js tests/artifact-path-security.test.js tests/http-compat.test.js tests/catalog-corrections.test.js tests/release-registry-identity.test.js tests/update-check.test.js tests/update-check-signal-lifecycle.test.js tests/self-update.test.js tests/doctor.test.js tests/doctor-cli.test.js tests/legacy-session-repair.test.js tests/profile-pnpm-diagnostics.test.js tests/doctor-v2.test.js tests/doctor-cli-v2.test.js tests/doctor-runtime.test.js tests/dsh-host-capabilities.test.js tests/doctor-host-capabilities.test.js tests/session-repair-v2.test.js tests/activation-shim-contract.test.js tests/bundle-defaults.test.js tests/file-logger.test.js tests/official-deepseek-catalog.test.js tests/replay-delegation.test.js tests/twin-image-capability-fallback.test.js tests/twin-image-custom-wrapper.test.js tests/adversarial-hardening.test.js tests/vision-adversarial-hardening-v2.test.js tests/vision-capability-benchmark-visual-proof.test.js tests/wrapper-directory.test.js tests/logging-ui.test.js tests/manifest-dependencies.test.js tests/architecture-2.3-gate.test.js tests/host-settings-seam.test.js tests/drift-canary-settings-seam.test.js tests/esm-cycle-audit.test.js tests/structured-bootstrap.test.js tests/structured-bootstrap-gate.test.js tests/vision-model-guidance-contract.test.js tests/local-ollama.test.js tests/local-only-vision.test.js tests/ollama-cold-start.test.js tests/ollama-cold-start-loaded.test.js tests/zero-regression-gate.test.js tests/runtime-e2e.test.js tests/local-vision-stabilizer.test.js tests/local-connection-probe.test.js tests/vision-diagnostics-routes.test.js tests/repetition-guard.test.js tests/guide-scroll-gate.test.js tests/settings-scroll-jank-regression.test.js tests/free-cloud-first.test.js tests/dsh-host-compat.test.js tests/native-image-coexistence.test.js tests/issue-276-session-image-ownership.test.js tests/issue-276-entry-policy-bridge.test.js tests/issue-276-policy-hardening.test.js tests/issue-289-native-nonintervention.test.js tests/issue-512-tool-restriction.test.js tests/issue-606-session-source-ownership.test.js tests/pi-ai-bridge-wire-compat.test.js tests/fetch-wrapper-lifecycle.test.js tests/fetch-wrapper-composition.test.js tests/provider-probe-proxy-scope.test.js tests/lifecycle-invariants.test.js tests/vision-tool-settings-generation.test.js tests/release-package-content-identity.test.js tests/release-state-machine.test.js tests/mixed-router.test.js tests/depth-tier.test.js tests/depth-quota-behavior.test.js tests/structured-flow-hardening.test.js tests/structured-flow-adversarial.test.js tests/vision-budget-activation.test.js tests/runtime-boundary-fixes.test.js tests/security-resource-boundaries.test.js tests/security-property-fuzz.test.js tests/security-adversarial-fuzz-contract.test.js tests/runtime-i18n.test.js tests/long-ocr-empty-retry.test.js tests/tesseract-adaptive-ocr.test.js tests/tesseract-node24-boot.test.js tests/session-vision-state.test.js tests/session-vision-state-integration.test.js tests/session-vision-event-feed.test.js tests/session-vision-policy.test.js tests/session-vision-policy-domain.test.js tests/session-vision-delegation.test.js tests/session-vision-delegation-boundary.test.js tests/subagent-vision-inheritance-characterization.test.js tests/subagent-vision-runtime-integration.test.js tests/subagent-vision-cold-resume.test.js tests/image-resource-governor.test.js tests/resource-retention-lifecycle.test.js tests/pixel-diff-stream.test.js tests/large-image-resource-integration.test.js tests/structured-guard-idempotency.test.js tests/vision-routing-product.test.js tests/vision-runtime-performance.test.js tests/vision-routing-settings-prelude.test.js tests/v2-settings-ia-integration.test.js tests/vision-capability-router.test.js tests/vision-capability-reference.test.js tests/vision-capability-benchmark.test.js tests/vision-capability-grounding-proof-contract.test.js tests/vision-capability-probe.test.js tests/vision-capability-axis-freshness.test.js tests/vision-capability-shadow-health.test.js tests/vision-capability-benchmark-service.test.js tests/vision-capability-preflight-hardening.test.js tests/vision-capability-benchmark-contract.test.js tests/vision-capability-benchmark-client.test.js tests/vision-capability-benchmark-client-productization.test.js tests/vision-capability-adapter-route.test.js tests/vision-background-benchmark.test.js tests/vision-background-lifecycle.test.js tests/vision-background-benchmark-productization.test.js tests/vision-capability-benchmark-budget.test.js tests/vision-image-input-verdict.test.js tests/vision-capability-failure-classification.test.js tests/vision-capability-gate-client.test.js tests/v2-product-review-fixes.test.js tests/qa-top5-reliability.test.js tests/qa-screenshot-runtime.test.js tests/qa-runtime-identity.test.js tests/qa-turn-budget-cancellation.test.js tests/qa-cancellation-publication.test.js tests/qa-reliability-tail.test.js tests/qa-endpoint-route-alias.test.js tests/settings-native-card-semantics.test.js tests/settings-native-card-lazy-data.test.js tests/settings-invalid-staged-dirty.test.js tests/vision-toggle-root-hardening.test.js && pnpm test:regression-closure && node --test tests/vision-backend-runtime-policy.test.js",
|
|
93
93
|
"test:core": "node --test tests/core.test.js tests/degraded-local-evidence.test.js tests/runtime-e2e.test.js tests/structured-bootstrap.test.js tests/structured-flow-hardening.test.js tests/structured-flow-adversarial.test.js tests/vision-execution-policy.test.js tests/vision-backend-runtime-policy.test.js",
|
|
94
94
|
"test:routing": "node --test tests/issue-374-delegated-call-config.test.js tests/twin-image-capability-fallback.test.js tests/twin-image-custom-wrapper.test.js tests/vision-routing-product.test.js tests/vision-capability-router.test.js tests/vision-capability-probe.test.js tests/vision-capability-shadow-health.test.js tests/vision-runtime-performance.test.js tests/vision-background-benchmark.test.js tests/vision-image-input-verdict.test.js",
|
|
95
95
|
"test:session": "node --test tests/session-vision-state.test.js tests/session-vision-state-integration.test.js tests/session-vision-policy.test.js tests/session-vision-delegation.test.js tests/session-vision-delegation-boundary.test.js tests/subagent-vision-inheritance-characterization.test.js tests/subagent-vision-runtime-integration.test.js tests/subagent-vision-cold-resume.test.js tests/session-vision-policy-domain.test.js tests/replay-delegation.test.js tests/legacy-session-repair.test.js tests/session-repair-v2.test.js tests/issue-276-session-image-ownership.test.js",
|