Fix UI-TARS scroll parsing (scroll actions were silently dropped) - #63
Merged
marksibrahim merged 1 commit intoJul 29, 2026
Merged
Conversation
uitars_parser never translated scroll actions to BrowserGym scroll(dx, dy):
the two branches had mutually-exclusive conditions — the gate
startswith("scroll(direction=d") requires no quote after '=' while the regex
required direction='...' with a quote. UI-TARS emits the quoted form
(e.g. scroll(direction='down', point='(612,455)'), verified in real traces),
so scroll was never translated and the raw string leaked to BrowserGym as an
invalid call — every UI-TARS-family model effectively could not scroll. Only
click/type are exercised by most evals, so it went unnoticed.
Replace the two dead branches with a single tolerant parse: extract the
direction and first two integers, then emit an axis-aligned delta
(down/right positive, up/left negative). Also handles left/right, which the
old code omitted. Add tests/test_uitars_parser.py covering all four
directions plus click/type regressions.
Contributor
|
Great catch Jiayu! This looks great |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
uitars_parser(insrc/open_apps/agent/utils.py) never translatedscrollactions into BrowserGym
scroll(dx, dy)calls. The raw model string was passedthrough unchanged, and since it isn't a valid BrowserGym action signature, the
scroll silently failed. Every UI-TARS-family model (UI-TARS, and any model
routed through this parser) effectively could not scroll.
Click and type are translated correctly, so any eval dominated by click/type
never surfaced this — it only bites tasks that require scrolling.
How to reproduce
UI-TARS-1.5 emits scroll actions in this exact form (verified across real run
trajectories — 59 scroll steps sampled, e.g.
scroll(direction='down', point='(612,455)'),scroll(direction='down', point='(1022, 666)'),scroll(direction='up', point='(1920,536)')):Before this PR this prints:
The string reaches BrowserGym as-is;
scrollexpects positionalscroll(dx, dy),not
direction=/point=kwargs, so the action fails / no-ops. Click and type inthe same trajectory translate fine, which is why this stayed hidden.
Root cause
The two scroll branches had mutually exclusive conditions, so neither body
ever executed:
startswith("scroll(direction=d")gate requires the character right after=to bed(i.e.scroll(direction=down…, no quote).direction='…'(i.e. with a quote).No string can satisfy both at once, so the branch is dead code (same for the
upbranch).What we changed
Replaced the two dead branches with a single tolerant parse that:
scroll(...)action,direction(down/up/left/right) and the first twointegers regardless of quoting/whitespace, and
down/rightpositive,up/leftnegative (a "scroll down" no longer also moves horizontally).This also adds
left/right, which the old code never handled.Before / after (what the model emits -> parsed action)
scroll(direction='down', point='(612,455)')scroll(direction='down', point='(612,455)')(invalid)scroll(0, 455)scroll(direction='up', point='(1920,536)')scroll(direction='up', point='(1920,536)')(invalid)scroll(0, -536)scroll(direction='right', point='(300,400)')scroll(300, 0)scroll(direction='left', point='(300,400)')scroll(-300, 0)Click/type are unchanged:
click(point='(100,200)')mouse_click(x=100, y=200)type(content='hello\n')keyboard_type(text='hello\n')Tests
Adds
tests/test_uitars_parser.py— 6 tests covering all four scrolldirections, whitespace tolerance in the point, and click/type regressions.
All pass.
Notes
click-translation behavior.
heuristic (the point marks where to scroll, while BrowserGym
scrolltakes adelta), but it scrolls the correct direction by a bounded amount instead of
failing outright. Happy to switch to a fixed step size if maintainers prefer.