dsh-vision-router 1.7.5 → 1.7.6

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.
@@ -1,7 +1,84 @@
1
1
  const wrappedContexts = new WeakMap()
2
+ const wrappedLlmServices = new WeakMap()
3
+ const preparedAdapterCompat = new WeakMap()
2
4
 
3
5
  export const DEFAULT_ADAPTER_RECONCILE_MAX_PASSES = 32
4
6
 
7
+ /**
8
+ * DSH 0.1.1 dispatches every model call through adapter.prepareCall(). Older
9
+ * Vision Router adapters are intentionally duck-typed objects and therefore do
10
+ * not inherit LlmAdapter's default implementation. Normalize only adapters
11
+ * registered through Vision Router's wrapped context so host/foreign adapters
12
+ * keep their native identity and behavior.
13
+ */
14
+ export function ensureAdapterPrepareCall(adapter) {
15
+ if (!adapter || (typeof adapter !== 'object' && typeof adapter !== 'function')) return adapter
16
+ if (typeof adapter.prepareCall === 'function') return adapter
17
+
18
+ const cached = preparedAdapterCompat.get(adapter)
19
+ if (cached) return cached
20
+
21
+ const prepareCall = async (provider, model, signal) => {
22
+ const fallbackModel = { provider, id: model, name: model }
23
+ const resolved =
24
+ typeof adapter.resolveModel === 'function'
25
+ ? await adapter.resolveModel.call(adapter, provider, model, signal)
26
+ : fallbackModel
27
+ return {
28
+ model: resolved && typeof resolved === 'object' ? resolved : fallbackModel,
29
+ stream(options) {
30
+ return adapter.stream.call(adapter, options)
31
+ },
32
+ }
33
+ }
34
+
35
+ // Preserve the exact adapter object whenever possible. Some runtime paths
36
+ // retain registration.adapter and compare/reuse it later, so mutation is less
37
+ // surprising than substituting a wrapper. Frozen/sealed adapters fall back to
38
+ // a proxy that exposes only the missing contract method.
39
+ try {
40
+ Object.defineProperty(adapter, 'prepareCall', {
41
+ configurable: true,
42
+ writable: true,
43
+ value: prepareCall,
44
+ })
45
+ preparedAdapterCompat.set(adapter, adapter)
46
+ return adapter
47
+ } catch {
48
+ const wrapped = new Proxy(adapter, {
49
+ get(target, property) {
50
+ if (property === 'prepareCall') return prepareCall
51
+ const value = Reflect.get(target, property, target)
52
+ return typeof value === 'function' ? value.bind(target) : value
53
+ },
54
+ })
55
+ preparedAdapterCompat.set(adapter, wrapped)
56
+ return wrapped
57
+ }
58
+ }
59
+
60
+ function wrapLlmService(llm) {
61
+ if (!llm || (typeof llm !== 'object' && typeof llm !== 'function')) return llm
62
+ const cached = wrappedLlmServices.get(llm)
63
+ if (cached) return cached
64
+
65
+ const wrapped = new Proxy(llm, {
66
+ get(target, property) {
67
+ if (property === 'registerAdapter') {
68
+ const registerAdapter = Reflect.get(target, property, target)
69
+ if (typeof registerAdapter !== 'function') return registerAdapter
70
+ return (providers, adapter, ...rest) =>
71
+ registerAdapter.call(target, providers, ensureAdapterPrepareCall(adapter), ...rest)
72
+ }
73
+ const value = Reflect.get(target, property, target)
74
+ return typeof value === 'function' ? value.bind(target) : value
75
+ },
76
+ })
77
+
78
+ wrappedLlmServices.set(llm, wrapped)
79
+ return wrapped
80
+ }
81
+
5
82
  /**
6
83
  * Turn a synchronous reconciliation pass into a bounded fixed-point runner.
7
84
  *
@@ -76,6 +153,10 @@ export function createCoalescingRunner(run, options = {}) {
76
153
  * registerAdapter() returns. Only Vision Router listeners registered through
77
154
  * this wrapped context are coalesced; host and other plugin listeners keep
78
155
  * their native event semantics.
156
+ *
157
+ * The same boundary also normalizes Vision Router-owned adapter registrations
158
+ * to the DSH 0.1.1 prepareCall contract. This stays scoped to the wrapped
159
+ * context instead of monkey-patching the Host LLM service process-wide.
79
160
  */
80
161
  export function contextWithCoalescedAdapterUpdates(ctx) {
81
162
  if (!ctx || (typeof ctx !== 'object' && typeof ctx !== 'function')) return ctx
@@ -84,6 +165,9 @@ export function contextWithCoalescedAdapterUpdates(ctx) {
84
165
 
85
166
  const wrapped = new Proxy(ctx, {
86
167
  get(target, property) {
168
+ if (property === 'llm') {
169
+ return wrapLlmService(Reflect.get(target, property, target))
170
+ }
87
171
  if (property === 'on') {
88
172
  const on = Reflect.get(target, property, target)
89
173
  if (typeof on !== 'function') return on
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-vision-router",
3
- "version": "1.7.5",
3
+ "version": "1.7.6",
4
4
  "description": "Eyes for text-only DeepSeek Harness agents: built-in free vision chain (no key) + pixel-level vision tools (Q&A, grounding, crop, pixel diff, colors, OCR, SVG trace, cutout, screenshots). One-command install, no Python, image turns work like ordinary tool-calling turns.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -69,7 +69,7 @@
69
69
  "sharp": "^0.35.3"
70
70
  },
71
71
  "scripts": {
72
- "test": "node --test tests/core.test.js tests/capability-advisory.test.js tests/vision-execution-policy.test.js tests/vision-backend-diagnostics.test.js tests/vision-backend-smoke-test.test.js tests/live-model-discovery.test.js tests/live-model-credential-resolution.test.js tests/vision-model-registry.test.js tests/live-model-client-stability.test.js tests/provider-directory-fallback.test.js tests/settings-section-order.test.js tests/attachment-admission-policy.test.js tests/vision-resilience.test.js tests/client.test.js tests/client-presentation-boundary.test.js tests/remote-settings-bridge.test.js tests/remote-settings-risk-confirmation.test.js tests/local-remote-settings-permission.test.js tests/rc6-real-settings-persistence.test.js tests/artifact-path-security.test.js tests/http-compat.test.js tests/catalog-corrections.test.js tests/update-check.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/session-repair-v2.test.js tests/bundle-defaults.test.js tests/file-logger.test.js tests/replay-delegation.test.js tests/adversarial-hardening.test.js tests/wrapper-directory.test.js tests/logging-ui.test.js tests/manifest-dependencies.test.js tests/structured-bootstrap.test.js tests/structured-bootstrap-gate.test.js tests/local-ollama.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/repetition-guard.test.js tests/guide-scroll-gate.test.js tests/settings-scroll-jank-regression.test.js tests/android-attachment-compat.test.js tests/free-cloud-first.test.js tests/rc6-rc7-compat.test.js tests/native-image-coexistence.test.js tests/pi-ai-bridge-wire-compat.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/vision-budget-activation.test.js tests/runtime-boundary-fixes.test.js tests/tesseract-node24-boot.test.js tests/session-vision-state.test.js tests/session-vision-state-integration.test.js tests/image-resource-governor.test.js tests/pixel-diff-stream.test.js tests/large-image-resource-integration.test.js tests/structured-guard-idempotency.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"
72
+ "test": "node --test tests/adapter-prepare-call-compat.test.js tests/core.test.js tests/capability-advisory.test.js tests/vision-execution-policy.test.js tests/vision-backend-diagnostics.test.js tests/vision-backend-smoke-test.test.js tests/live-model-discovery.test.js tests/live-model-credential-resolution.test.js tests/vision-model-registry.test.js tests/live-model-client-stability.test.js tests/provider-directory-fallback.test.js tests/settings-section-order.test.js tests/attachment-admission-policy.test.js tests/vision-resilience.test.js tests/client.test.js tests/client-presentation-boundary.test.js tests/remote-settings-bridge.test.js tests/remote-settings-risk-confirmation.test.js tests/local-remote-settings-permission.test.js tests/rc6-real-settings-persistence.test.js tests/artifact-path-security.test.js tests/http-compat.test.js tests/catalog-corrections.test.js tests/update-check.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/session-repair-v2.test.js tests/bundle-defaults.test.js tests/file-logger.test.js tests/replay-delegation.test.js tests/adversarial-hardening.test.js tests/wrapper-directory.test.js tests/logging-ui.test.js tests/manifest-dependencies.test.js tests/structured-bootstrap.test.js tests/structured-bootstrap-gate.test.js tests/local-ollama.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/repetition-guard.test.js tests/guide-scroll-gate.test.js tests/settings-scroll-jank-regression.test.js tests/android-attachment-compat.test.js tests/free-cloud-first.test.js tests/rc6-rc7-compat.test.js tests/native-image-coexistence.test.js tests/pi-ai-bridge-wire-compat.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/vision-budget-activation.test.js tests/runtime-boundary-fixes.test.js tests/tesseract-node24-boot.test.js tests/session-vision-state.test.js tests/session-vision-state-integration.test.js tests/image-resource-governor.test.js tests/pixel-diff-stream.test.js tests/large-image-resource-integration.test.js tests/structured-guard-idempotency.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"
73
73
  },
74
74
  "pnpm": {
75
75
  "onlyBuiltDependencies": ["sharp"]