dsh-vision-router 2.2.8 → 3.0.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 +16 -7
- package/README.zh.md +16 -7
- package/docs/architecture/2.3.0-compat-retirement.md +147 -0
- package/docs/architecture/2.3.0-execution-plan.md +410 -0
- package/docs/architecture/2.3.0-final-audit.md +279 -0
- package/docs/architecture/2.3.0-reopened-plan.md +720 -0
- package/docs/architecture/3.0-architecture-plan.md +252 -0
- package/docs/architecture/3.0-r0-contract-ledger.md +137 -0
- package/docs/architecture/3.0-r1-source-artifact-boundary.md +98 -0
- package/docs/architecture/3.0-r10-final-correctness-closure.md +207 -0
- package/docs/architecture/3.0-r11-adversarial-review.md +441 -0
- package/docs/architecture/3.0-r5-browser-go-no-go.md +165 -0
- package/docs/architecture/3.0-r5-browser-typescript-gate.md +105 -0
- package/docs/architecture/3.0-r6-compat-retirement.md +203 -0
- package/docs/architecture/3.0-r7-public-api.md +151 -0
- package/docs/architecture/3.0-r8-ci-release.md +248 -0
- package/docs/architecture/3.0-r9-final-audit.md +370 -0
- package/docs/architecture/compat-inventory.md +26 -34
- package/docs/architecture/dsh-compatibility-matrix.md +65 -54
- package/docs/architecture/dsh-support-window.md +30 -22
- package/docs/architecture/final-closure-audit.md +2 -0
- package/docs/releases/v2.3.0.md +53 -0
- package/docs/releases/v3.0.0.md +85 -0
- package/entry.js +9 -57
- package/index.js +268 -761
- package/lib/agent-request-route-authority.js +1 -20
- package/lib/catalog-corrections.js +1 -2
- package/lib/client-maintenance-actions.js +145 -0
- package/lib/client-presentation-boundary-main.js +75 -17
- package/lib/client-presentation-boundary.js +53 -28
- package/lib/client.js +246 -144
- package/lib/core-apply-lifecycle.js +41 -0
- package/lib/core-cache.js +87 -0
- package/lib/core-primitives.js +91 -278
- package/lib/core-vision-surface-domain.js +63 -0
- package/lib/core-vision-surface.js +11 -77
- package/lib/delegated-call-config.js +15 -24
- package/lib/desktop-screenshot-tool.js +262 -0
- package/lib/doctor-cli.js +0 -0
- package/lib/doctor-runtime.js +4 -1
- package/lib/dsh-contract-compat.js +37 -256
- package/lib/dsh-host-capabilities.js +3 -9
- package/lib/dsh-settings-017-compat.js +17 -10
- package/lib/dsh-support-window.js +3 -3
- package/lib/file-logger.js +8 -3
- package/lib/grounding-coordinate-runtime.js +1 -2
- package/lib/http-body-limit.js +97 -79
- package/lib/http-compat.js +1 -2
- package/lib/image-offload-compat.js +30 -21
- package/lib/image-resource-governor.js +210 -228
- package/lib/legacy-global-proxy-boundary.js +46 -3
- package/lib/live-model-client-prelude.js +12 -4
- package/lib/live-model-discovery.js +134 -43
- package/lib/local-remote-settings-permission.js +33 -7
- package/lib/local-vision-stabilizer.js +31 -17
- package/lib/maintenance-routes.js +134 -0
- package/lib/native-image-coexistence.js +15 -3
- package/lib/ollama-cold-start.js +87 -23
- package/lib/pi-ai-bridge-wire-compat.js +3 -2
- package/lib/proxy-dispatcher-pool.js +151 -92
- package/lib/proxy-routing.js +75 -51
- package/lib/proxy-url-compat.js +3 -10
- package/lib/public-config.js +36 -0
- package/lib/public-entry.d.ts +148 -0
- package/lib/public-entry.js +19 -11
- package/lib/remote-settings-bridge.js +11 -0
- package/lib/remote-settings-risk-client-boundary.js +155 -0
- package/lib/remote-settings-risk-confirmation.js +17 -105
- package/lib/replay-delegation.js +12 -7
- package/lib/replay-envelope-v2-compat.js +12 -7
- package/lib/runtime-composition.js +127 -34
- package/lib/runtime-i18n-boundary.js +10 -11
- package/lib/screenshot-source-boundary.js +2 -2
- package/lib/session-affinity-runtime.js +113 -97
- package/lib/session-affinity.js +89 -76
- package/lib/session-event-history-compat.js +30 -0
- package/lib/session-message-source-compat.js +7 -3
- package/lib/session-query-readers.js +263 -0
- package/lib/session-surface-compat.js +30 -31
- package/lib/session-surface-policy-domain.js +85 -0
- package/lib/session-surface-policy.js +2 -111
- package/lib/session-turn-resolver.js +2 -6
- package/lib/session-vision-attachment-index.js +143 -0
- package/lib/session-vision-delegation-boundary.js +34 -0
- package/lib/session-vision-delegation.js +22 -0
- package/lib/session-vision-index.js +179 -116
- package/lib/session-vision-mode-authority.js +229 -192
- package/lib/session-vision-mode-boundary.js +65 -22
- package/lib/session-vision-policy-domain.js +304 -0
- package/lib/session-vision-policy.js +104 -0
- package/lib/session-vision-state.js +368 -378
- package/lib/settings-client-017-compat.js +9 -7
- package/lib/settings-client-loader-lifecycle.js +129 -0
- package/lib/sharp-runtime.js +0 -7
- package/lib/structured-flow-hardening.js +25 -6
- package/lib/tesseract-exec-compat.js +9 -1
- package/lib/turn-budget-context.js +47 -41
- package/lib/update-check.js +11 -2
- package/lib/vision-attachment-handle-runtime.js +176 -156
- package/lib/vision-backend-runtime-policy.js +19 -2
- package/lib/vision-background-benchmark.js +41 -4
- package/lib/vision-background-failure-policy.js +41 -41
- package/lib/vision-background-stop-store-core.js +217 -0
- package/lib/vision-background-stop-store.js +8 -179
- package/lib/vision-capability-benchmark-service.js +1 -0
- package/lib/vision-capability-benchmark.js +11 -61
- package/lib/vision-capability-evidence.js +35 -0
- package/lib/vision-capability-fingerprint.js +72 -0
- package/lib/vision-capability-identity.js +116 -61
- package/lib/vision-capability-router.js +13 -33
- package/lib/vision-chunk-assembler.js +95 -0
- package/lib/vision-diagnostics-routes.js +246 -0
- package/lib/vision-evidence-guidance.js +3 -1
- package/lib/vision-execution-order-apply.js +45 -55
- package/lib/vision-execution-order.js +19 -19
- package/lib/vision-execution-policy.js +12 -7
- package/lib/vision-model-registry.js +30 -17
- package/lib/vision-provider-transport.js +137 -176
- package/lib/vision-routing-authority.js +47 -48
- package/lib/vision-routing-product.js +26 -29
- package/lib/vision-routing-settings-prelude.js +8 -3
- package/lib/vision-runtime-performance-store.js +166 -0
- package/lib/vision-runtime-performance.js +13 -142
- package/lib/vision-toggle-root-hardening.js +22 -5
- package/lib/vision-tool-runtime-boundary.js +104 -31
- package/lib/web/dsh-settings-017-root-transport.js +27 -12
- package/lib/web/remote-settings-client.js +6 -9
- package/lib/web-capability-boundary.js +17 -7
- package/lib/wrapper-directory.js +14 -23
- package/package.json +56 -20
- package/lib/android-attachment-compat.js +0 -244
- package/lib/settings-client-rc8-lifecycle.js +0 -397
|
@@ -14,14 +14,11 @@ export const SETTINGS_017_CLIENT_PRELUDE = String.raw`(function(){
|
|
|
14
14
|
var connectionCache = typeof WeakMap === 'function' ? new WeakMap() : undefined;
|
|
15
15
|
|
|
16
16
|
function safeGet(ctx, name) {
|
|
17
|
-
if (!ctx) return undefined;
|
|
17
|
+
if (!ctx || typeof ctx.get !== 'function') return undefined;
|
|
18
18
|
try {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
} catch (_) {}
|
|
24
|
-
try { return ctx[name]; } catch (_) { return undefined; }
|
|
19
|
+
var value = ctx.get(name);
|
|
20
|
+
return value === undefined || value === null ? undefined : value;
|
|
21
|
+
} catch (_) { return undefined; }
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
function isLoopbackLocation(locationLike) {
|
|
@@ -212,6 +209,11 @@ export const SETTINGS_017_CLIENT_PRELUDE = String.raw`(function(){
|
|
|
212
209
|
var getter = Reflect.get(target, property, target);
|
|
213
210
|
if (typeof getter !== 'function') return getter;
|
|
214
211
|
return function(name) {
|
|
212
|
+
if (name === 'settingsScope') {
|
|
213
|
+
var original = safeGet(target, 'settingsScope');
|
|
214
|
+
if (original && typeof original.bind === 'function') return original;
|
|
215
|
+
return syntheticBinder(ctx, configFormsBinder(target));
|
|
216
|
+
}
|
|
215
217
|
var value = getter.call(target, name);
|
|
216
218
|
return name === 'connection' ? normalizeConnection(value) : value;
|
|
217
219
|
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { injectClientCarrierHtml, installClientScriptCarriers } from './client-script-carrier.js'
|
|
2
|
+
import {
|
|
3
|
+
LOCAL_PERMISSION_CLIENT_BOUNDARY_SOURCE,
|
|
4
|
+
LOCAL_REMOTE_SETTINGS_PERMISSION_FIELD,
|
|
5
|
+
LOCAL_REMOTE_SETTINGS_PERMISSION_PATH,
|
|
6
|
+
} from './local-remote-settings-permission.js'
|
|
7
|
+
import { REMOTE_SETTINGS_RISK_CLIENT_BOUNDARY_SOURCE } from './remote-settings-risk-client-boundary.js'
|
|
8
|
+
|
|
9
|
+
// Keep the legacy marker value so mixed-generation/HMR pages do not install
|
|
10
|
+
// a second lifecycle wrapper after the source/API rename.
|
|
11
|
+
const SETTINGS_CLIENT_LOADER_LIFECYCLE_MARK = 'data-vision-router-settings-rc8-lifecycle'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Supported Hosts can replace ModuleLoader.load() inside loader.create(). This
|
|
15
|
+
* compatibility owner only re-attaches the current local-permission and
|
|
16
|
+
* remote-risk product boundaries after that queue-to-live transition; product
|
|
17
|
+
* semantics stay in their capability owners.
|
|
18
|
+
*/
|
|
19
|
+
export const SETTINGS_CLIENT_LOADER_LIFECYCLE_PRELUDE = String.raw`(function(){
|
|
20
|
+
'use strict';
|
|
21
|
+
var TARGET = 'dsh-vision-router';
|
|
22
|
+
${LOCAL_PERMISSION_CLIENT_BOUNDARY_SOURCE}
|
|
23
|
+
var localPermissionBoundary = createLocalRemoteSettingsPermissionClientBoundary({
|
|
24
|
+
endpoint: '${LOCAL_REMOTE_SETTINGS_PERMISSION_PATH}',
|
|
25
|
+
field: '${LOCAL_REMOTE_SETTINGS_PERMISSION_FIELD}',
|
|
26
|
+
fetchImpl: typeof fetch === 'function'
|
|
27
|
+
? function(url, options) { return fetch(url, options); }
|
|
28
|
+
: undefined
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
${REMOTE_SETTINGS_RISK_CLIENT_BOUNDARY_SOURCE}
|
|
32
|
+
var riskBoundary = createRemoteSettingsRiskClientBoundary({
|
|
33
|
+
confirmImpl: function(message) {
|
|
34
|
+
return typeof window.confirm === 'function' && window.confirm(message) === true;
|
|
35
|
+
},
|
|
36
|
+
alertImpl: function(message) {
|
|
37
|
+
try { if (typeof window.alert === 'function') window.alert(message); } catch (_) {}
|
|
38
|
+
},
|
|
39
|
+
locale: function() {
|
|
40
|
+
try {
|
|
41
|
+
return String((document && document.documentElement && document.documentElement.lang)
|
|
42
|
+
|| (navigator && navigator.language) || '');
|
|
43
|
+
} catch (_) { return ''; }
|
|
44
|
+
},
|
|
45
|
+
location: function() {
|
|
46
|
+
try { return window && window.location; } catch (_) { return undefined; }
|
|
47
|
+
},
|
|
48
|
+
normalizeLoopback: true
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
function patchLiveLoader(loader) {
|
|
52
|
+
if (!loader || typeof loader.load !== 'function' || loader.load.__visionRouterSettingsRc8Lifecycle) return;
|
|
53
|
+
var original = loader.load;
|
|
54
|
+
function load(spec) {
|
|
55
|
+
if (spec && spec.id === TARGET && typeof spec.factory === 'function') {
|
|
56
|
+
var factory = spec.factory;
|
|
57
|
+
spec = Object.assign({}, spec, {
|
|
58
|
+
factory: function(require) {
|
|
59
|
+
var exports = factory(require);
|
|
60
|
+
if (exports && typeof exports.apply === 'function' && !exports.apply.__visionRouterSettingsRc8Lifecycle) {
|
|
61
|
+
var apply = exports.apply;
|
|
62
|
+
var wrappedApply = function(ctx) {
|
|
63
|
+
var rest = Array.prototype.slice.call(arguments, 1);
|
|
64
|
+
var nextCtx = riskBoundary.wrapContext(localPermissionBoundary.wrapContext(ctx));
|
|
65
|
+
return apply.apply(exports, [nextCtx].concat(rest));
|
|
66
|
+
};
|
|
67
|
+
Object.defineProperty(wrappedApply, '__visionRouterSettingsRc8Lifecycle', { value: true });
|
|
68
|
+
exports.apply = wrappedApply;
|
|
69
|
+
}
|
|
70
|
+
return exports;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return original.call(this, spec);
|
|
75
|
+
}
|
|
76
|
+
Object.defineProperty(load, '__visionRouterSettingsRc8Lifecycle', { value: true });
|
|
77
|
+
loader.load = load;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function patchCreate(loader) {
|
|
81
|
+
if (!loader || typeof loader.create !== 'function' || loader.create.__visionRouterSettingsRc8Lifecycle) return;
|
|
82
|
+
var originalCreate = loader.create;
|
|
83
|
+
function create() {
|
|
84
|
+
var result = originalCreate.apply(this, arguments);
|
|
85
|
+
patchLiveLoader(loader);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
Object.defineProperty(create, '__visionRouterSettingsRc8Lifecycle', { value: true });
|
|
89
|
+
loader.create = create;
|
|
90
|
+
if (loader.mode === 'live') patchLiveLoader(loader);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function install() {
|
|
94
|
+
if (window.__ModuleLoader__) {
|
|
95
|
+
patchCreate(window.__ModuleLoader__);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
var descriptor = Object.getOwnPropertyDescriptor(window, '__ModuleLoader__');
|
|
99
|
+
if (descriptor && descriptor.configurable === false) return;
|
|
100
|
+
var previousGet = descriptor && descriptor.get;
|
|
101
|
+
var previousSet = descriptor && descriptor.set;
|
|
102
|
+
var stored = descriptor && Object.prototype.hasOwnProperty.call(descriptor, 'value') ? descriptor.value : undefined;
|
|
103
|
+
Object.defineProperty(window, '__ModuleLoader__', {
|
|
104
|
+
configurable: true,
|
|
105
|
+
enumerable: !descriptor || descriptor.enumerable !== false,
|
|
106
|
+
get: function(){ return previousGet ? previousGet.call(window) : stored; },
|
|
107
|
+
set: function(value) {
|
|
108
|
+
if (previousSet) previousSet.call(window, value); else stored = value;
|
|
109
|
+
try { patchCreate(previousGet ? previousGet.call(window) : value); } catch (_) {}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
if (stored) patchCreate(stored);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
try { install(); } catch (_) {}
|
|
116
|
+
})();`
|
|
117
|
+
|
|
118
|
+
export function injectSettingsClientLoaderLifecyclePrelude(html) {
|
|
119
|
+
return injectClientCarrierHtml(html, SETTINGS_CLIENT_LOADER_LIFECYCLE_MARK, SETTINGS_CLIENT_LOADER_LIFECYCLE_PRELUDE)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function installSettingsClientLoaderLifecycle(ctx) {
|
|
123
|
+
installClientScriptCarriers(ctx, {
|
|
124
|
+
marker: SETTINGS_CLIENT_LOADER_LIFECYCLE_MARK,
|
|
125
|
+
prelude: SETTINGS_CLIENT_LOADER_LIFECYCLE_PRELUDE,
|
|
126
|
+
label: 'vision-router: settings client loader lifecycle',
|
|
127
|
+
injectHtml: injectSettingsClientLoaderLifecyclePrelude,
|
|
128
|
+
})
|
|
129
|
+
}
|
package/lib/sharp-runtime.js
CHANGED
|
@@ -10,7 +10,6 @@ import { Worker } from 'node:worker_threads'
|
|
|
10
10
|
import { createRequire } from 'node:module'
|
|
11
11
|
import { pathToFileURL } from 'node:url'
|
|
12
12
|
import { promisify } from 'node:util'
|
|
13
|
-
import { appendPromptToImageOnlyMessage, fetchWithOpenAICompatibility } from './http-compat.js'
|
|
14
13
|
import {
|
|
15
14
|
directSessionAffinityHeaders,
|
|
16
15
|
isOfficialOpenCodeGoUrl,
|
|
@@ -19,12 +18,6 @@ import {
|
|
|
19
18
|
sessionIdentityOf,
|
|
20
19
|
} from './session-affinity.js'
|
|
21
20
|
import { runWithVisionSessionAffinity, streamWithVisionSessionAffinity } from './session-affinity-runtime.js'
|
|
22
|
-
import {
|
|
23
|
-
routingCorrectionFor,
|
|
24
|
-
toAnthropicMessages,
|
|
25
|
-
callAnthropicCompatible,
|
|
26
|
-
anthropicMediaType,
|
|
27
|
-
} from './catalog-corrections.js'
|
|
28
21
|
import { createCachedUpdateChecker } from './update-check.js'
|
|
29
22
|
import { probeLocalBackends } from './local-connection-probe.js'
|
|
30
23
|
import { detectDshSelfUpdatePlan, runDshPluginUpdate } from './self-update.js'
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
} from './turn-budget-context.js'
|
|
5
5
|
import { runWithDepthConfig } from './depth-guidance.js'
|
|
6
6
|
import { runtimeLanguageFor } from './runtime-i18n.js'
|
|
7
|
+
import { visionRouterMessageSource } from './session-message-source-compat.js'
|
|
7
8
|
|
|
8
9
|
const STRUCTURED_EVIDENCE_TOOLS = new Set([
|
|
9
10
|
'vision_describe',
|
|
@@ -440,7 +441,7 @@ function appendGuardMessage(decision, payload, state, config) {
|
|
|
440
441
|
? '已达到本轮设置的深挖次数上限。不要再调用视觉工具;请基于已经获得的证据作答,并明确仍存在的不确定性。'
|
|
441
442
|
: '连续多次后续视觉调用都没有产出可用证据。不要继续重复调用视觉工具;请基于已经获得的证据作答,并明确仍存在的不确定性。',
|
|
442
443
|
}],
|
|
443
|
-
source:
|
|
444
|
+
source: visionRouterMessageSource(payload?.agent?.session),
|
|
444
445
|
}
|
|
445
446
|
return appendSyntheticGuardOnce(decision, baseMessages, state, message, true)
|
|
446
447
|
}
|
|
@@ -461,7 +462,7 @@ function appendGuardMessage(decision, payload, state, config) {
|
|
|
461
462
|
? 'The structured bootstrap is complete, but no usable task-directed visual evidence has been produced yet. Call at least one vision tool that can add or verify evidence, then answer after it succeeds.'
|
|
462
463
|
: '结构化预识别已经完成,但目前还没有产出可用的任务定向视觉证据。请至少调用一个能新增或验证证据的视觉工具,成功后再作答。',
|
|
463
464
|
}],
|
|
464
|
-
source:
|
|
465
|
+
source: visionRouterMessageSource(payload?.agent?.session),
|
|
465
466
|
}
|
|
466
467
|
return appendSyntheticGuardOnce(decision, baseMessages, state, message)
|
|
467
468
|
}
|
|
@@ -629,7 +630,7 @@ function wrapSettingsScope(scope) {
|
|
|
629
630
|
})
|
|
630
631
|
}
|
|
631
632
|
|
|
632
|
-
function wrapSettingsService(settings,
|
|
633
|
+
function wrapSettingsService(settings, bindScope) {
|
|
633
634
|
if (!settings || typeof settings !== 'object') return settings
|
|
634
635
|
return new Proxy(settings, {
|
|
635
636
|
get(target, property) {
|
|
@@ -642,7 +643,7 @@ function wrapSettingsService(settings, setScope) {
|
|
|
642
643
|
return (namespace, ...args) => {
|
|
643
644
|
const scope = register.call(target, namespace, ...args)
|
|
644
645
|
if (namespace !== 'vision-router') return scope
|
|
645
|
-
|
|
646
|
+
if (bindScope(scope) !== true) return scope
|
|
646
647
|
return wrapSettingsScope(scope)
|
|
647
648
|
}
|
|
648
649
|
},
|
|
@@ -651,7 +652,8 @@ function wrapSettingsService(settings, setScope) {
|
|
|
651
652
|
|
|
652
653
|
function wrapSettingsContext(childCtx, setScope) {
|
|
653
654
|
if (!childCtx || typeof childCtx !== 'object' || !childCtx.settings) return childCtx
|
|
654
|
-
const
|
|
655
|
+
const bindScope = (scope) => setScope(scope, childCtx)
|
|
656
|
+
const settings = wrapSettingsService(childCtx.settings, bindScope)
|
|
655
657
|
return new Proxy(childCtx, {
|
|
656
658
|
get(target, property) {
|
|
657
659
|
if (property === 'settings') return settings
|
|
@@ -665,7 +667,24 @@ export function installStructuredFlowHardening(ctx, config = {}) {
|
|
|
665
667
|
if (!ctx || typeof ctx !== 'object') return ctx
|
|
666
668
|
const states = new WeakMap()
|
|
667
669
|
let settingsScope
|
|
668
|
-
const setSettingsScope = (scope) => {
|
|
670
|
+
const setSettingsScope = (scope, ownerCtx) => {
|
|
671
|
+
if (!scope || (typeof scope !== 'object' && typeof scope !== 'function')) return false
|
|
672
|
+
// Settings is a dynamic child service. Never retain a scope unless the
|
|
673
|
+
// child fiber owns its lifetime; otherwise an HMR gap can read stale config.
|
|
674
|
+
try {
|
|
675
|
+
if (typeof ownerCtx?.effect !== 'function') return false
|
|
676
|
+
ownerCtx.effect(
|
|
677
|
+
() => () => {
|
|
678
|
+
if (settingsScope === scope) settingsScope = undefined
|
|
679
|
+
},
|
|
680
|
+
'vision-router: structured flow settings lifecycle',
|
|
681
|
+
)
|
|
682
|
+
} catch {
|
|
683
|
+
return false
|
|
684
|
+
}
|
|
685
|
+
settingsScope = scope
|
|
686
|
+
return true
|
|
687
|
+
}
|
|
669
688
|
const activeConfig = () => {
|
|
670
689
|
try {
|
|
671
690
|
const value = settingsScope && typeof settingsScope.get === 'function' ? settingsScope.get() : config
|
|
@@ -326,7 +326,15 @@ export function installVisionRouterExecFileCompat(ctx, options = {}) {
|
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
if (ctx && typeof ctx.effect === 'function') {
|
|
329
|
-
|
|
329
|
+
try {
|
|
330
|
+
ctx.effect(() => dispose, 'vision-router: execFile compatibility')
|
|
331
|
+
} catch (error) {
|
|
332
|
+
// The process-global execFile seam was already mutated above. If Cordis
|
|
333
|
+
// cannot own this generation, undo exactly this installation before the
|
|
334
|
+
// failure escapes so no orphan patch survives HMR/startup failure.
|
|
335
|
+
dispose()
|
|
336
|
+
throw error
|
|
337
|
+
}
|
|
330
338
|
}
|
|
331
339
|
return dispose
|
|
332
340
|
}
|
|
@@ -1,58 +1,64 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
2
|
-
|
|
3
|
-
const turnBudgetScope = new AsyncLocalStorage()
|
|
4
|
-
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
const turnBudgetScope = new AsyncLocalStorage();
|
|
5
3
|
function usableSignal(value) {
|
|
6
|
-
|
|
4
|
+
return value !== null
|
|
5
|
+
&& typeof value === 'object'
|
|
6
|
+
&& typeof value.aborted === 'boolean'
|
|
7
|
+
? value
|
|
8
|
+
: undefined;
|
|
7
9
|
}
|
|
8
|
-
|
|
9
10
|
function finiteDeadline(value) {
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
const number = Number(value);
|
|
12
|
+
return Number.isFinite(number) ? number : undefined;
|
|
13
|
+
}
|
|
14
|
+
function objectBudget(value) {
|
|
15
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
16
|
+
? value
|
|
17
|
+
: undefined;
|
|
12
18
|
}
|
|
13
|
-
|
|
14
19
|
/**
|
|
15
20
|
* Run one async tool execution inside an ambient turn-level budget.
|
|
16
21
|
* Nested budgets may tighten the parent, but may not discard an earlier parent
|
|
17
22
|
* deadline, cancellation signal or artifact-run identity.
|
|
18
23
|
*/
|
|
19
24
|
export function runWithVisionTurnBudget(budget, fn) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
parent
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
25
|
+
if (typeof fn !== 'function')
|
|
26
|
+
throw new TypeError('runWithVisionTurnBudget: fn must be a function');
|
|
27
|
+
const parent = turnBudgetScope.getStore();
|
|
28
|
+
const parentSignal = usableSignal(parent?.signal);
|
|
29
|
+
const childSignal = usableSignal(budget?.signal);
|
|
30
|
+
const parentDeadline = finiteDeadline(parent?.deadlineAt);
|
|
31
|
+
const childDeadline = finiteDeadline(budget?.deadlineAt);
|
|
32
|
+
let next = objectBudget(budget);
|
|
33
|
+
if (parentSignal && childSignal && parentSignal !== childSignal) {
|
|
34
|
+
next = { ...(next ?? {}), signal: AbortSignal.any([parentSignal, childSignal]) };
|
|
35
|
+
}
|
|
36
|
+
else if (parentSignal && !childSignal) {
|
|
37
|
+
next = { ...(next ?? {}), signal: parentSignal };
|
|
38
|
+
}
|
|
39
|
+
if (parentDeadline !== undefined && (childDeadline === undefined || parentDeadline < childDeadline)) {
|
|
40
|
+
next = { ...(next ?? {}), deadlineAt: parentDeadline };
|
|
41
|
+
}
|
|
42
|
+
if (typeof parent?.artifactRunId === 'string'
|
|
43
|
+
&& parent.artifactRunId !== ''
|
|
44
|
+
&& !(typeof next?.artifactRunId === 'string' && next.artifactRunId !== '')) {
|
|
45
|
+
next = { ...(next ?? {}), artifactRunId: parent.artifactRunId };
|
|
46
|
+
}
|
|
47
|
+
return turnBudgetScope.run(next, fn);
|
|
43
48
|
}
|
|
44
|
-
|
|
45
49
|
export function currentVisionTurnBudget() {
|
|
46
|
-
|
|
50
|
+
return turnBudgetScope.getStore();
|
|
47
51
|
}
|
|
48
|
-
|
|
49
52
|
export function currentVisionTurnBudgetSignal() {
|
|
50
|
-
|
|
53
|
+
return usableSignal(turnBudgetScope.getStore()?.signal);
|
|
51
54
|
}
|
|
52
|
-
|
|
53
55
|
export function remainingVisionTurnBudgetMs(now = Date.now) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
const budget = turnBudgetScope.getStore();
|
|
57
|
+
const deadlineAt = finiteDeadline(budget?.deadlineAt);
|
|
58
|
+
if (deadlineAt === undefined)
|
|
59
|
+
return undefined;
|
|
60
|
+
const clock = typeof now === 'function'
|
|
61
|
+
? now
|
|
62
|
+
: Date.now;
|
|
63
|
+
return Math.max(0, deadlineAt - Number(clock()));
|
|
58
64
|
}
|
package/lib/update-check.js
CHANGED
|
@@ -5,6 +5,15 @@ import { stripTrailingSlashes } from './string-normalization.js'
|
|
|
5
5
|
const require = createRequire(import.meta.url)
|
|
6
6
|
const packageJson = require('../package.json')
|
|
7
7
|
|
|
8
|
+
// Capture the process fetch once, at module evaluation, exactly like the
|
|
9
|
+
// Router-owned provider transport. Reading `globalThis.fetch` per call would
|
|
10
|
+
// re-admit DVR's own later-installed process-wide wrappers (legacy proxy,
|
|
11
|
+
// i18n/pi-ai bridge) into DVR's product-metadata requests, and would make the
|
|
12
|
+
// transport used for a request depend on when the request happens to run.
|
|
13
|
+
const moduleFetch = typeof globalThis.fetch === 'function'
|
|
14
|
+
? globalThis.fetch.bind(globalThis)
|
|
15
|
+
: undefined
|
|
16
|
+
|
|
8
17
|
export const PACKAGE_NAME = 'dsh-vision-router'
|
|
9
18
|
export const CURRENT_VERSION = String(packageJson.version ?? '')
|
|
10
19
|
export const DEFAULT_NPM_REGISTRY = 'https://registry.npmjs.org'
|
|
@@ -149,7 +158,7 @@ async function fetchLatestReleaseVersion({ fetchImpl, releaseApi, signal, timeou
|
|
|
149
158
|
* read-only metadata request against npmjs instead of showing a false failure.
|
|
150
159
|
*/
|
|
151
160
|
export async function checkPackageUpdate({
|
|
152
|
-
fetchImpl =
|
|
161
|
+
fetchImpl = moduleFetch,
|
|
153
162
|
currentVersion = CURRENT_VERSION,
|
|
154
163
|
registry = registryBaseFromEnv(),
|
|
155
164
|
fallbackRegistry = DEFAULT_NPM_REGISTRY,
|
|
@@ -247,7 +256,7 @@ export async function checkPackageUpdate({
|
|
|
247
256
|
* settings card reuses that result, and the manual button can force a refresh.
|
|
248
257
|
*/
|
|
249
258
|
export function createCachedUpdateChecker({
|
|
250
|
-
fetchImpl =
|
|
259
|
+
fetchImpl = moduleFetch,
|
|
251
260
|
currentVersion = CURRENT_VERSION,
|
|
252
261
|
registry = registryBaseFromEnv(),
|
|
253
262
|
fallbackRegistry = DEFAULT_NPM_REGISTRY,
|