dsh-vision-router 2.1.7 → 2.2.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 +8 -14
- package/README.zh.md +8 -14
- package/docs/architecture/compat-inventory.md +1 -1
- package/docs/architecture/dsh-compatibility-matrix.md +4 -1
- package/docs/architecture/dsh-support-window.md +1 -2
- package/docs/releases/v2.2.0.md +25 -0
- package/docs/remote-settings.md +2 -0
- package/entry.js +2 -0
- package/index.js +355 -64
- package/lib/artifact-boundary.js +11 -0
- package/lib/artifact-io.js +60 -7
- package/lib/catalog-corrections.js +5 -0
- package/lib/client.js +22 -17
- package/lib/core-primitives.js +115 -5
- package/lib/degraded-local-evidence.js +39 -0
- package/lib/dsh-contract-compat.js +202 -0
- package/lib/dsh-support-window.js +1 -1
- package/lib/image-offload-compat.js +38 -0
- package/lib/local-vision-stabilizer.js +15 -6
- package/lib/official-deepseek-catalog.js +120 -0
- package/lib/ollama-cold-start.js +3 -15
- package/lib/remote-settings-bridge.js +19 -1
- package/lib/replay-delegation.js +41 -21
- package/lib/runtime-composition.js +15 -2
- package/lib/runtime-i18n-boundary.js +4 -13
- package/lib/runtime-i18n.js +2 -2
- package/lib/session-surface-compat.js +40 -0
- package/lib/session-turn-resolver.js +57 -0
- package/lib/session-vision-index.js +206 -93
- package/lib/session-vision-mode-boundary.js +83 -6
- package/lib/session-vision-runtime.js +8 -2
- package/lib/session-vision-state.js +0 -13
- package/lib/tesseract-exec-compat.js +16 -2
- package/lib/twin-image-capability-fallback.js +2 -11
- package/lib/vision-artifact-store.js +16 -3
- package/lib/vision-attachment-handle-runtime.js +9 -21
- package/lib/vision-backend-runtime-policy.js +7 -6
- package/lib/vision-breaker-shadow-health.js +15 -5
- package/lib/vision-evidence-guidance.js +39 -0
- package/lib/vision-resilience.js +73 -1
- package/package.json +11 -6
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveArtifactTarget,
|
|
3
3
|
writeArtifactFile,
|
|
4
|
+
writePersistentArtifactFile,
|
|
4
5
|
} from './artifact-io.js'
|
|
5
6
|
import {
|
|
6
7
|
retainArtifactRun,
|
|
@@ -46,6 +47,17 @@ export function createVisionArtifactStore({ workspace, artifactsDir, deps = {} }
|
|
|
46
47
|
)
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
const publishPersistent = (relativePath, data, options = {}) => {
|
|
51
|
+
const current = location()
|
|
52
|
+
return writePersistentArtifactFile(
|
|
53
|
+
current.workspace,
|
|
54
|
+
current.artifactsDir,
|
|
55
|
+
relativePath,
|
|
56
|
+
data,
|
|
57
|
+
callDeps(deps, options),
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
49
61
|
return Object.freeze({
|
|
50
62
|
resolve(relativePath, options = {}) {
|
|
51
63
|
const current = location()
|
|
@@ -58,10 +70,11 @@ export function createVisionArtifactStore({ workspace, artifactsDir, deps = {} }
|
|
|
58
70
|
},
|
|
59
71
|
|
|
60
72
|
publish,
|
|
73
|
+
publishPersistent,
|
|
61
74
|
|
|
62
|
-
// Temporary
|
|
63
|
-
//
|
|
64
|
-
//
|
|
75
|
+
// Temporary placement remains authority/lifetime driven by the ambient
|
|
76
|
+
// random managed artifactRunId. publishPersistent is the narrow handoff
|
|
77
|
+
// exception and uses one stable reserved run that retention still owns.
|
|
65
78
|
publishTemporary(relativePath, data, options = {}) {
|
|
66
79
|
return publish(relativePath, data, options)
|
|
67
80
|
},
|
|
@@ -29,13 +29,11 @@ function attachmentIdOf(ref) {
|
|
|
29
29
|
return id === '' ? undefined : id
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function
|
|
32
|
+
function sessionMessages(session) {
|
|
33
33
|
try {
|
|
34
|
-
if (session
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
return Array.isArray(session?.events) ? session.events : []
|
|
34
|
+
if (!session || typeof session.deriveMessages !== 'function') return []
|
|
35
|
+
const messages = session.deriveMessages()
|
|
36
|
+
return Array.isArray(messages) ? messages : []
|
|
39
37
|
} catch {
|
|
40
38
|
return []
|
|
41
39
|
}
|
|
@@ -55,18 +53,9 @@ function collectImageRefsFromMessages(messages, out) {
|
|
|
55
53
|
for (const message of messages) collectImageRefsFromBlocks(message?.content, out)
|
|
56
54
|
}
|
|
57
55
|
|
|
58
|
-
function authorizedRefs(
|
|
56
|
+
function authorizedRefs(agent) {
|
|
59
57
|
const refs = []
|
|
60
|
-
|
|
61
|
-
const events = sessionEvents(session)
|
|
62
|
-
if (typeof core?.collectEventAttachmentRefs === 'function') {
|
|
63
|
-
try {
|
|
64
|
-
const durable = core.collectEventAttachmentRefs(events)
|
|
65
|
-
if (Array.isArray(durable)) refs.push(...durable)
|
|
66
|
-
} catch {
|
|
67
|
-
// The resolver remains fail-closed; pending refs below may still suffice.
|
|
68
|
-
}
|
|
69
|
-
}
|
|
58
|
+
collectImageRefsFromMessages(sessionMessages(agent?.session), refs)
|
|
70
59
|
collectImageRefsFromMessages(agent?.inbox?.nextTurn, refs)
|
|
71
60
|
collectImageRefsFromMessages(agent?.inbox?.nextStep, refs)
|
|
72
61
|
|
|
@@ -99,12 +88,12 @@ function isCanonicalSha256Id(value) {
|
|
|
99
88
|
* only when exactly one image authorized by the current Session has that
|
|
100
89
|
* prefix. Zero or multiple matches fail closed.
|
|
101
90
|
*/
|
|
102
|
-
export function resolveProjectedAttachmentHandle(handle, {
|
|
91
|
+
export function resolveProjectedAttachmentHandle(handle, { sessionVisionIndex, agent } = {}) {
|
|
103
92
|
const token = typeof handle === 'string' ? handle.trim() : ''
|
|
104
93
|
if (!isProjectedAttachmentHandle(token)) return { kind: 'not-projected', value: handle }
|
|
105
94
|
|
|
106
95
|
const session = agent?.session
|
|
107
|
-
const refs = authorizedRefs(
|
|
96
|
+
const refs = authorizedRefs(agent)
|
|
108
97
|
const wanted = token.toLowerCase()
|
|
109
98
|
const matches = refs.filter((ref) => {
|
|
110
99
|
const id = attachmentIdOf(ref)
|
|
@@ -124,7 +113,7 @@ export function resolveProjectedAttachmentHandle(handle, { core, sessionVisionIn
|
|
|
124
113
|
try {
|
|
125
114
|
sessionVisionIndex?.recordAttachments?.(session, [candidate])
|
|
126
115
|
} catch {
|
|
127
|
-
//
|
|
116
|
+
// Authorization is still fail-closed if the bounded cache cannot be warmed.
|
|
128
117
|
}
|
|
129
118
|
if (!sessionVisionIndex || typeof sessionVisionIndex.lookupAttachment !== 'function') {
|
|
130
119
|
return { kind: 'unknown', handle: token }
|
|
@@ -201,7 +190,6 @@ export function wrapVisionAttachmentHandleDefinition(def, options = {}) {
|
|
|
201
190
|
...def,
|
|
202
191
|
execute(args, exec) {
|
|
203
192
|
const nextArgs = canonicalizeArgs(args, {
|
|
204
|
-
core: options.core,
|
|
205
193
|
sessionVisionIndex: options.sessionVisionIndex,
|
|
206
194
|
agent: exec?.agent,
|
|
207
195
|
toolName: def.name,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
2
|
+
import { blocksHaveRetainedImage, isOffloadedImageBlock, offloadedImagePlaceholder } from './image-offload-compat.js'
|
|
2
3
|
|
|
3
4
|
const visionBackendScope = new AsyncLocalStorage()
|
|
4
5
|
const wrappedContexts = new WeakMap()
|
|
@@ -127,12 +128,8 @@ async function resolveCredential(ctx, plan) {
|
|
|
127
128
|
return undefined
|
|
128
129
|
}
|
|
129
130
|
|
|
130
|
-
function contentHasImage(
|
|
131
|
-
return (messages ?? []).some((message) =>
|
|
132
|
-
if (!Array.isArray(message?.content)) return false
|
|
133
|
-
if (typeof core?.blocksHaveImage === 'function') return core.blocksHaveImage(message.content)
|
|
134
|
-
return message.content.some((block) => block?.type === 'image')
|
|
135
|
-
})
|
|
131
|
+
function contentHasImage(_core, messages) {
|
|
132
|
+
return (messages ?? []).some((message) => blocksHaveRetainedImage(message?.content))
|
|
136
133
|
}
|
|
137
134
|
|
|
138
135
|
async function toOpenAIMessages(ctx, messages) {
|
|
@@ -151,6 +148,10 @@ async function toOpenAIMessages(ctx, messages) {
|
|
|
151
148
|
continue
|
|
152
149
|
}
|
|
153
150
|
if (block?.type === 'image' && block.attachment) {
|
|
151
|
+
if (isOffloadedImageBlock(block)) {
|
|
152
|
+
converted.push({ type: 'text', text: offloadedImagePlaceholder(block) })
|
|
153
|
+
continue
|
|
154
|
+
}
|
|
154
155
|
const stored = await attachments.readImage(block.attachment)
|
|
155
156
|
const mediaType = block.attachment.mediaType || stored?.mediaType || 'image/png'
|
|
156
157
|
const data = Buffer.from(stored.data).toString('base64')
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto'
|
|
2
|
+
import { createSessionTurnResolver } from './session-turn-resolver.js'
|
|
2
3
|
|
|
3
|
-
function
|
|
4
|
+
function legacyTurnNumberOf(session) {
|
|
4
5
|
try {
|
|
5
6
|
const events = session?.events
|
|
6
7
|
if (!Array.isArray(events)) return 0
|
|
@@ -19,8 +20,15 @@ function sessionIdOf(session) {
|
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export function visionBreakerScopeOf(session) {
|
|
23
|
-
|
|
23
|
+
export function visionBreakerScopeOf(session, turnOf) {
|
|
24
|
+
let turn
|
|
25
|
+
try {
|
|
26
|
+
if (typeof turnOf === 'function') turn = turnOf(session)
|
|
27
|
+
} catch {
|
|
28
|
+
turn = undefined
|
|
29
|
+
}
|
|
30
|
+
if (!Number.isInteger(turn) || turn < 0) turn = legacyTurnNumberOf(session)
|
|
31
|
+
return `${sessionIdOf(session)}:${turn}`
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
function credentialFingerprintOf(value) {
|
|
@@ -76,7 +84,9 @@ function healthFromGate(gate) {
|
|
|
76
84
|
* giving shadow code mutation authority. `capture()` is called only while
|
|
77
85
|
* core.apply() constructs the breaker; `healthForCandidate()` uses peek().
|
|
78
86
|
*/
|
|
79
|
-
export function createVisionBreakerShadowHealth(ctx) {
|
|
87
|
+
export function createVisionBreakerShadowHealth(ctx, options = {}) {
|
|
88
|
+
const sessionTurnResolver = options.sessionTurnResolver ?? createSessionTurnResolver(ctx)
|
|
89
|
+
const turnOf = sessionTurnResolver.turnOf
|
|
80
90
|
let breaker
|
|
81
91
|
return {
|
|
82
92
|
capture(value) {
|
|
@@ -88,7 +98,7 @@ export function createVisionBreakerShadowHealth(ctx) {
|
|
|
88
98
|
const key = typeof candidate?.key === 'string' ? candidate.key : undefined
|
|
89
99
|
if (!key) return undefined
|
|
90
100
|
const fingerprint = await visionBreakerFingerprintForCandidate(ctx, candidate)
|
|
91
|
-
const scope = visionBreakerScopeOf(context.session)
|
|
101
|
+
const scope = visionBreakerScopeOf(context.session, turnOf)
|
|
92
102
|
return healthFromGate(breaker.peek(key, fingerprint, scope))
|
|
93
103
|
},
|
|
94
104
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const VISION_SUCCESS_GUIDANCE =
|
|
2
|
+
'Vision Router trusted execution metadata: the preceding vision_describe call SUCCEEDED. ' +
|
|
3
|
+
'This metadata is not image content. If that successful evidence resolves the visual fact needed for the current task, stop making additional vision calls for that fact and continue the remaining user task from this evidence. ' +
|
|
4
|
+
'If no non-visual work remains, answer now in exactly the format the user requested; when the user asks for only one value or short phrase, do not add Markdown, explanation, or a restatement. ' +
|
|
5
|
+
'Call another vision tool only for a specific unresolved visual fact. For verbatim or exact-text tasks such as identifiers, amounts, times, version strings, or code, preserve every visible symbol, prefix, suffix, and punctuation from the most faithful evidence already collected; a later semantic summary must not overwrite a more exact transcription. Focused OCR or localization is still appropriate when character identity remains uncertain.'
|
|
6
|
+
|
|
7
|
+
function isVisionFailureEnvelope(value) {
|
|
8
|
+
const text = value.trim()
|
|
9
|
+
if (!text.startsWith('{')) return false
|
|
10
|
+
try {
|
|
11
|
+
const parsed = JSON.parse(text)
|
|
12
|
+
return (
|
|
13
|
+
parsed !== null &&
|
|
14
|
+
typeof parsed === 'object' &&
|
|
15
|
+
parsed.ok === false &&
|
|
16
|
+
typeof parsed.code === 'string' &&
|
|
17
|
+
/^VISION_[A-Z0-9_]+$/u.test(parsed.code)
|
|
18
|
+
)
|
|
19
|
+
} catch {
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function visionDescribeSuccessContext(exec, result) {
|
|
25
|
+
if (
|
|
26
|
+
exec?.name !== 'vision_describe' ||
|
|
27
|
+
!exec?.agent ||
|
|
28
|
+
result?.isError !== false ||
|
|
29
|
+
typeof result.value !== 'string' ||
|
|
30
|
+
result.value.trim().length === 0 ||
|
|
31
|
+
isVisionFailureEnvelope(result.value)
|
|
32
|
+
) return undefined
|
|
33
|
+
return {
|
|
34
|
+
role: 'user',
|
|
35
|
+
id: `vision-router-evidence-success-${String(exec.callId)}`,
|
|
36
|
+
content: [{ type: 'text', text: VISION_SUCCESS_GUIDANCE }],
|
|
37
|
+
source: { kind: 'plugin', plugin: 'dsh-vision-router' },
|
|
38
|
+
}
|
|
39
|
+
}
|
package/lib/vision-resilience.js
CHANGED
|
@@ -376,12 +376,14 @@ export function createVisionTurnMemory({
|
|
|
376
376
|
maxScopes = 64,
|
|
377
377
|
maxSessions = maxScopes,
|
|
378
378
|
maxAttemptsPerScope = 64,
|
|
379
|
+
maxEvidencePerScope = 32,
|
|
379
380
|
} = {}) {
|
|
380
381
|
const scopes = new Map() // scope -> { failedKinds:Set, attempted: [], allFailed:false }
|
|
381
382
|
const lastScopeBySession = new Map() // bounded LRU sessionId -> scope
|
|
382
383
|
const scopeLimit = Math.max(1, Math.floor(Number(maxScopes) || 64))
|
|
383
384
|
const sessionLimit = Math.max(1, Math.floor(Number(maxSessions) || scopeLimit))
|
|
384
385
|
const attemptLimit = Math.max(1, Math.floor(Number(maxAttemptsPerScope) || 64))
|
|
386
|
+
const evidenceLimit = Math.max(1, Math.floor(Number(maxEvidencePerScope) || 32))
|
|
385
387
|
|
|
386
388
|
const dropScope = (scope) => {
|
|
387
389
|
scopes.delete(scope)
|
|
@@ -410,7 +412,14 @@ export function createVisionTurnMemory({
|
|
|
410
412
|
const entry = (scope) => {
|
|
411
413
|
let hit = scopes.get(scope)
|
|
412
414
|
if (hit === undefined) {
|
|
413
|
-
hit = {
|
|
415
|
+
hit = {
|
|
416
|
+
failedKinds: new Set(),
|
|
417
|
+
attempted: [],
|
|
418
|
+
allFailed: false,
|
|
419
|
+
localOcr: new Map(),
|
|
420
|
+
derivedArtifacts: new Map(),
|
|
421
|
+
degradedRefinements: new Map(),
|
|
422
|
+
}
|
|
414
423
|
scopes.set(scope, hit)
|
|
415
424
|
pruneScopes()
|
|
416
425
|
} else {
|
|
@@ -453,6 +462,69 @@ export function createVisionTurnMemory({
|
|
|
453
462
|
return hit === undefined ? [] : [...hit.attempted]
|
|
454
463
|
},
|
|
455
464
|
|
|
465
|
+
resolveSource(scope, sourceKey) {
|
|
466
|
+
const key = typeof sourceKey === 'string' ? sourceKey : ''
|
|
467
|
+
const hit = scopes.get(scope)
|
|
468
|
+
if (hit === undefined || key === '') return key
|
|
469
|
+
for (const [artifactToken, rootSource] of hit.derivedArtifacts) {
|
|
470
|
+
if (key === artifactToken || key.includes(artifactToken)) return rootSource
|
|
471
|
+
}
|
|
472
|
+
return key
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
recordLocalOcr(scope, sourceKey, evidence = {}) {
|
|
476
|
+
const hit = entry(scope)
|
|
477
|
+
const key = this.resolveSource(scope, sourceKey)
|
|
478
|
+
if (key === '') return
|
|
479
|
+
hit.localOcr.delete(key)
|
|
480
|
+
hit.localOcr.set(key, Object.freeze({ uncertain: evidence.uncertain === true }))
|
|
481
|
+
while (hit.localOcr.size > evidenceLimit) hit.localOcr.delete(hit.localOcr.keys().next().value)
|
|
482
|
+
},
|
|
483
|
+
|
|
484
|
+
hasLocalOcr(scope, sourceKey) {
|
|
485
|
+
const hit = scopes.get(scope)
|
|
486
|
+
if (hit === undefined) return false
|
|
487
|
+
return hit.localOcr.has(this.resolveSource(scope, sourceKey))
|
|
488
|
+
},
|
|
489
|
+
|
|
490
|
+
degradedEvidenceTokens(scope) {
|
|
491
|
+
const hit = scopes.get(scope)
|
|
492
|
+
if (hit === undefined || !hit.allFailed || hit.localOcr.size === 0) return []
|
|
493
|
+
const tokens = [...hit.localOcr.keys()]
|
|
494
|
+
for (const [artifactToken, rootSource] of hit.derivedArtifacts) {
|
|
495
|
+
if (hit.localOcr.has(rootSource)) tokens.push(artifactToken)
|
|
496
|
+
}
|
|
497
|
+
return tokens
|
|
498
|
+
},
|
|
499
|
+
|
|
500
|
+
recordDerivedArtifact(scope, sourceKey, artifactToken) {
|
|
501
|
+
const token = typeof artifactToken === 'string' ? artifactToken : ''
|
|
502
|
+
if (token === '') return
|
|
503
|
+
const hit = entry(scope)
|
|
504
|
+
const rootSource = this.resolveSource(scope, sourceKey)
|
|
505
|
+
if (rootSource === '') return
|
|
506
|
+
hit.derivedArtifacts.delete(token)
|
|
507
|
+
hit.derivedArtifacts.set(token, rootSource)
|
|
508
|
+
while (hit.derivedArtifacts.size > evidenceLimit) hit.derivedArtifacts.delete(hit.derivedArtifacts.keys().next().value)
|
|
509
|
+
},
|
|
510
|
+
|
|
511
|
+
degradedRefinementCount(scope, sourceKey) {
|
|
512
|
+
const hit = scopes.get(scope)
|
|
513
|
+
if (hit === undefined) return 0
|
|
514
|
+
return hit.degradedRefinements.get(this.resolveSource(scope, sourceKey)) ?? 0
|
|
515
|
+
},
|
|
516
|
+
|
|
517
|
+
recordDegradedRefinement(scope, sourceKey) {
|
|
518
|
+
const hit = entry(scope)
|
|
519
|
+
const key = this.resolveSource(scope, sourceKey)
|
|
520
|
+
if (key === '') return 0
|
|
521
|
+
const count = (hit.degradedRefinements.get(key) ?? 0) + 1
|
|
522
|
+
hit.degradedRefinements.delete(key)
|
|
523
|
+
hit.degradedRefinements.set(key, count)
|
|
524
|
+
while (hit.degradedRefinements.size > evidenceLimit) hit.degradedRefinements.delete(hit.degradedRefinements.keys().next().value)
|
|
525
|
+
return count
|
|
526
|
+
},
|
|
527
|
+
|
|
456
528
|
stats() {
|
|
457
529
|
return { scopes: scopes.size, sessions: lastScopeBySession.size }
|
|
458
530
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vision-router",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
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": {
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"undici": "^7.29.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@deepseek-ai/dsh-anonymous-user-id": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.3-alpha.2 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2",
|
|
58
|
-
"@deepseek-ai/dsh-llm-deepseek": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.3-alpha.2 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2",
|
|
57
|
+
"@deepseek-ai/dsh-anonymous-user-id": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.3-alpha.2 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
|
|
58
|
+
"@deepseek-ai/dsh-llm-deepseek": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.3-alpha.2 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
|
|
59
59
|
"sharp": ">=0.35.3 <1"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"sharp": "^0.35.4"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
|
-
"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/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/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/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/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/bundle-defaults.test.js tests/file-logger.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/structured-bootstrap.test.js tests/structured-bootstrap-gate.test.js tests/vision-model-guidance-contract.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/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/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/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/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/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 && node --test tests/vision-backend-runtime-policy.test.js",
|
|
74
|
-
"test:core": "node --test tests/core.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",
|
|
73
|
+
"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/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/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/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/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/structured-bootstrap.test.js tests/structured-bootstrap-gate.test.js tests/vision-model-guidance-contract.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/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/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/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/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/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 && node --test tests/vision-backend-runtime-policy.test.js",
|
|
74
|
+
"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",
|
|
75
75
|
"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",
|
|
76
76
|
"test:session": "node --test tests/session-vision-state.test.js tests/session-vision-state-integration.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",
|
|
77
77
|
"test:resources": "node --test tests/artifact-path-security.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/qa-turn-budget-cancellation.test.js tests/qa-cancellation-publication.test.js",
|
|
@@ -81,7 +81,12 @@
|
|
|
81
81
|
"test:grounding": "node --test tests/grounding-coordinate-frame.test.js tests/grounding-coordinate-runtime.test.js tests/vision-capability-grounding-proof-contract.test.js",
|
|
82
82
|
"test:stress": "node scripts/image-resource-stress.mjs && node --test tests/large-image-resource-integration.test.js tests/resource-retention-lifecycle.test.js",
|
|
83
83
|
"test:adversarial-fuzz": "node scripts/security-adversarial-fuzz.mjs",
|
|
84
|
-
"test:property-fuzz": "node --test tests/security-property-fuzz.test.js"
|
|
84
|
+
"test:property-fuzz": "node --test tests/security-property-fuzz.test.js",
|
|
85
|
+
"test:quality": "node --test tests/vision-quality-round2-baseline.test.js",
|
|
86
|
+
"quality:round2:render": "node quality/vision-round2/render-fixtures.mjs",
|
|
87
|
+
"quality:round2:template": "node quality/vision-round2/make-run-template.mjs",
|
|
88
|
+
"quality:round2:run": "node quality/vision-round2/run-host-api.mjs",
|
|
89
|
+
"quality:round2:report": "node quality/vision-round2/report-results.mjs"
|
|
85
90
|
},
|
|
86
91
|
"pnpm": {
|
|
87
92
|
"onlyBuiltDependencies": ["sharp"]
|