dsh-vision-router 2.2.3 → 2.2.4

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.
@@ -0,0 +1,22 @@
1
+ # v2.2.4
2
+
3
+ DSH Vision Router 2.2.4 is a Desktop and Session-recovery hotfix for the DSH 0.1.7 line.
4
+
5
+ ## Highlights
6
+
7
+ - Fixes the official DSH `0.1.7-rc.2` Desktop startup failure where Vision Router could remain at `Loading plugins…` / `pending (waiting for service: settingsScope)`. The 0.1.7 Settings compatibility prelude now travels through DSH's structured `webserver/index-inject` boot table used by Electron/static carriers, while the served-Web `tapIndex()` path remains as a compatibility fallback and is deduplicated.
8
+ - Adds an exact `0.1.7-rc.2` Desktop Host bootstrap regression on `windows-latest`, so the Electron/Desktop injection carrier is validated directly instead of inferred from `dsh web` browser coverage.
9
+ - Fixes a Session event-feed recovery edge case where one transient activation-time SessionQuery read failure could permanently suppress future backfill attempts. Failed snapshots are now retried, concurrent reads remain coalesced, and a successful snapshot remains one-shot cached.
10
+ - Keeps the public minimum supported DSH Host at `0.1.0-rc.8`; no settings migration is required.
11
+
12
+ ## Validation
13
+
14
+ - Exact DSH source: `0.1.7-rc.2` at `477b4f420553e8a52c2fbccc464d7561b239c443`.
15
+ - Exact Windows Desktop Host bootstrap passes with one Vision Router structured compatibility injection.
16
+ - Real `dsh web` + Chromium passes bundle recompose, Desktop structured bootstrap, cold Vision toggle, mixed attachment lifecycle, and Settings mount/save/reload/readback.
17
+ - Node 22/24, architecture/data-boundary/adversarial/fuzz, dependency review, and HOL plugin security gates pass.
18
+ - Session regression covers fail → retry → success → cached behavior; the full local suite passed `1488/1489` tests with one intentional skip, plus `8/8` Host image-delivery tests.
19
+
20
+ ## Upgrade
21
+
22
+ Users on DSH `0.1.7-rc.2` Desktop should upgrade to 2.2.4. This release contains the Desktop boot fix that is not present in 2.2.3. No settings migration is required.
@@ -366,17 +366,17 @@ export function createSessionVisionIndex({
366
366
  result = await readSessionLog(session)
367
367
  } catch (error) {
368
368
  warnRepairReadFailure(session, surfaceNodes(session)?.[0] ?? 0, error)
369
- return
369
+ return false
370
370
  }
371
371
  if (result?.supported === true) {
372
372
  if (!Array.isArray(result.events)) {
373
373
  warnRepairReadFailure(session, surfaceNodes(session)?.[0] ?? 0, new Error('Session log reader returned no event log'))
374
- return
374
+ return false
375
375
  }
376
376
  events = result.events
377
377
  } else if (result?.supported !== false) {
378
378
  warnRepairReadFailure(session, surfaceNodes(session)?.[0] ?? 0, new Error('Session log reader returned an invalid capability result'))
379
- return
379
+ return false
380
380
  }
381
381
  }
382
382
 
@@ -385,15 +385,16 @@ export function createSessionVisionIndex({
385
385
  // snapshot, then return to the O(new events) feed path. Older partial Hosts
386
386
  // without SessionQuery retain the Session-local compatibility snapshot.
387
387
  if (events === undefined) events = legacySessionEvents(session)
388
- if (!Array.isArray(events)) return
388
+ if (!Array.isArray(events)) return true
389
389
 
390
390
  const nodes = surfaceNodes(session)
391
- if (!nodes || nodes.length === 0) return
391
+ if (!nodes || nodes.length === 0) return true
392
392
  for (const seq of nodes) {
393
393
  const event = events[seq]
394
394
  if (!event || typeof event !== 'object' || (event.seq !== undefined && event.seq !== seq)) continue
395
395
  recordSessionEvent(session, event)
396
396
  }
397
+ return true
397
398
  }
398
399
 
399
400
  const ensureSurfaceEventFeedBackfill = async (session) => {
@@ -403,7 +404,15 @@ export function createSessionVisionIndex({
403
404
  task = backfillSurfaceEventFeed(session)
404
405
  surfaceFeedBackfills.set(session, task)
405
406
  }
406
- await task
407
+ try {
408
+ const complete = await task
409
+ if (complete === false && surfaceFeedBackfills.get(session) === task) {
410
+ surfaceFeedBackfills.delete(session)
411
+ }
412
+ } catch (error) {
413
+ if (surfaceFeedBackfills.get(session) === task) surfaceFeedBackfills.delete(session)
414
+ throw error
415
+ }
407
416
  }
408
417
 
409
418
  const consumePendingRepairEvents = (pendingBySession, session) => {
@@ -2,6 +2,7 @@ import { htmlHasScriptMarker } from './html-script-marker.js'
2
2
  import { LOCAL_SETTINGS_PATH } from './dsh-settings-017-compat.js'
3
3
 
4
4
  const SETTINGS_017_MARK = 'data-vision-router-settings-017-compat'
5
+ const SETTINGS_017_STRUCTURED_MARK = `/* ${SETTINGS_017_MARK}:structured */`
5
6
 
6
7
  export const SETTINGS_017_CLIENT_PRELUDE = String.raw`(function(){
7
8
  'use strict';
@@ -311,7 +312,9 @@ export const SETTINGS_017_CLIENT_PRELUDE = String.raw`(function(){
311
312
  })();`
312
313
 
313
314
  export function injectSettings017ClientPrelude(html) {
314
- if (typeof html !== 'string' || htmlHasScriptMarker(html, SETTINGS_017_MARK)) return html
315
+ if (typeof html !== 'string'
316
+ || htmlHasScriptMarker(html, SETTINGS_017_MARK)
317
+ || html.includes(SETTINGS_017_STRUCTURED_MARK)) return html
315
318
  const safe = SETTINGS_017_CLIENT_PRELUDE.replace(/<\/script/gi, '<\\/script')
316
319
  const script = `<script ${SETTINGS_017_MARK}>${safe}</script>`
317
320
  const closeHead = html.indexOf('</head>')
@@ -321,8 +324,27 @@ export function injectSettings017ClientPrelude(html) {
321
324
  export function installSettings017ClientCompatibility(ctx) {
322
325
  if (!ctx || typeof ctx.inject !== 'function') return
323
326
  // ConfigEditor is the generation fence: old supported Hosts keep their native
324
- // settingsScope activation contract and never see this client shim.
327
+ // settingsScope activation contract and never see this client shim. DSH 0.1.7
328
+ // Desktop serves dsh-app:// from static assets and receives Host bootstrap
329
+ // state only through the structured index-injection table; raw tapIndex()
330
+ // transforms are HTTP-only and would leave the Desktop client parked on the
331
+ // retired settingsScope dependency.
325
332
  ctx.inject(['configEditor', 'webServer'], (webCtx) => {
333
+ if (typeof webCtx.on === 'function') {
334
+ webCtx.on('webserver/index-inject', (table) => {
335
+ if (!Array.isArray(table)) return
336
+ table.push({
337
+ kind: 'script',
338
+ placement: 'head',
339
+ text: `${SETTINGS_017_STRUCTURED_MARK}\n${SETTINGS_017_CLIENT_PRELUDE}`,
340
+ })
341
+ })
342
+ }
343
+
344
+ // Keep the served-HTML carrier too. On 0.1.7 the structured row renders
345
+ // first and the marker makes this a no-op; on a transitional Host that
346
+ // has ConfigEditor but never emits index-inject, tapIndex remains the
347
+ // compatibility fallback instead of silently losing the prelude.
326
348
  webCtx.effect(
327
349
  () => webCtx.webServer.tapIndex(injectSettings017ClientPrelude),
328
350
  'vision-router: DSH 0.1.7 settings client compatibility',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-vision-router",
3
- "version": "2.2.3",
3
+ "version": "2.2.4",
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": {