Repository navigation
Conversation
…fe danger zone) Closes #97
# Conflicts: # CHANGELOG.md
Birfy
left a comment
There was a problem hiding this comment.
Self-review (Birfy; cannot approve own PR).
Ready-to-merge-from-my-side for the opt-in wire path of #97: S1A_JEV_IMAGES defaults off; only the direct TypeSafe backend is accepted (proxy / custom URL are config errors, not silent text-only); assets + TypeSafe-Danger-Zone-Images are per-request; resize/reject follows the documented side and byte limits; provenance sent_image is present only when an image was sent; desktop --pixel-target accepts jev only with images on. Offline tests with fake / MockTransport cover the important reject paths. Main was merged in (8ec00f9); CI green.
What's left before fully closing #97 / leaving draft:
- Issue item 5 — live text-only vs screenshot
--model jevon WebVoyager Allrecipes task 0 underdocs/results/— still needs a TypeSafe key. Same blocker as noted in the PR body. - #113 (
--box-target) is stacked on this branch; merging this first unblocks that stack.
From my side the experimental opt-in path is fine to merge if a maintainer accepts shipping without the live comparison row; otherwise stay draft until that run lands. No quality claim in the docs — keep it that way.
Required human contributor answers
Per the repo owner's (Danyang, @Birfy) standing instruction, these are filled from the issue (#97) instead of waiting for separate human answers.
What outcome are you trying to achieve?
Answer:
--model jev(hosted TypeSafe Jev, the backend the README benchmarks most) can read the page or window screenshot, so it can be compared with and without one, and users without a GPU get a screenshot-reading option ([Feat] Let hosted Jev read screenshots (TypeSafe image input, opt-in) on the browser and desktop pixel-target paths #97).What is the highest-leverage variable for that outcome?
Answer: Whether the direct TypeSafe request carries the current screenshot in the documented
assetsformat with the danger-zone header, within TypeSafe's image limits.How will this work move that variable rather than create busywork?
Answer: It flips
JevModel.supports_imagesbehind one opt-in setting, so the existing browser screenshot capture and desktop--pixel-targetpath work unchanged; nothing changes when the setting is unset.Who is the customer or user, and what do they actually need?
Answer: People running the browser or desktop agents on hosted Jev who need visual grounding (canvases, controls without accessibility entries) without running an in-process vision model.
After answering the four questions: is a PR needed at all to achieve this outcome?
Human decision and rationale (or explicit source reference): Yes; the request body is built in
s1a/decision_models/jev.py, scoped by #97 items 1 to 4.For a bug fix: link actual observed failure evidence.
Evidence: Not a bug fix: a new opt-in input path (#97).
Why
TypeSafe turned on image input for hosted Jev with Jev 1.14 (Images docs);
jev-1.13.0, our pinned default, accepts it too. Here thejevpath is text-only:JevModelnever setssupports_images, so the browser front never captures a screenshot for it and the desktop--pixel-targetpath refuses it. Closes #97 (the live comparison, item 5, is still outstanding; see Demo / evidence).How
Start with
s1a/decision_models/jev.py, thens1a/decision_models/wire.pyandtests/test_decision_models_jev_images.py.S1A_JEV_IMAGES=1(read bywire.jev_images_from_env) is accepted only on the direct TypeSafe backend; with the OpenRouter proxy or a customTYPESAFE_API_URLit is a config error, since the proxy is not known to forwardassets. An unreadable value is a config error too. The TypeSafe client is then built withimages=True, andJevModel.supports_imagesfollows it.assets: {<fresh "screenshot-<uuid4>">: {type: image, format, data_base64}}, the reference goes once intostate.screenshot(a text state becomes{text, screenshot}), and that request alone carriesTypeSafe-Danger-Zone-Images: true(per-requestheaders=onJevDecisionsClient.decide). No screenshot means the plain text body; more than one isMODEL_CALL_FAILED.sent_image(width,height,bytes,format,resized) throughDecision.provenance;input_tokensalready comes fromusage.--pixel-targetaccepts--model jevwhenS1A_JEV_IMAGESis on (the env already sends exactly one current capture per step).What
S1A_JEV_IMAGES(off by default), documented as experimental (TypeSafe danger zone) indocs/configuration.md,docs/decision-models.mdanddocs/capabilities.md, with no quality claim.JevDecisionsClient(images=...)anddecide(body, *, headers=None);ScriptedTransportgainsimagesand recordsheaders.PROVENANCE_KEYSgainssent_image(present only when an image was sent).Verification
uv run ruff format --check . && uv run ruff check . && uv run ty check: all cleanuv run pytest -qandscripts/smoke.sh: 1273 passed, 130 skipped; smoke OKCHANGELOG.mdand the docs say what the code does nowNew offline tests (fake transport and
httpx.MockTransport): assets and header only when on; every asset referenced once, fresh per request; text state wrapped; oversize 3136x1960 resized to 1568x980; 279 px and too-thin images rejected; GIF, mismatched bytes and garbage rejected; proxy and custom-URL backends refuse the setting; desktop--pixel-targetaccepted forjevonly with images on.Demo / evidence
--model jevon the WebVoyager Allrecipes task, committed underdocs/results/) is not done. Keeping this draft until that run lands or a maintainer accepts merging the opt-in path first.main06db629; hosted TypeSafe, no System1-Omni involved.