Skip to content

[Improvement] Code Editor Tasks - #70

Open
aaronsmulktis wants to merge 28 commits into
facebookresearch:aaronsmulktis/coord-rescalefrom
aaronsmulktis:aaronsmulktis/editor-tasks
Open

[Improvement] Code Editor Tasks#70
aaronsmulktis wants to merge 28 commits into
facebookresearch:aaronsmulktis/coord-rescalefrom
aaronsmulktis:aaronsmulktis/editor-tasks

Conversation

@aaronsmulktis

@aaronsmulktis aaronsmulktis commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Changes

  1. add agent Gemma 4 31B
  2. add edit_script_add_header_comment task
  3. add create_notes_file_in_code_editor task
  4. fix sitemap.xml
  5. fix register_resolver() error
  6. fix editor save method
  7. add unit tests

- theme design vars
- set default layout
- set default theme
- use design vars in todo app
- update README
- add theme & layout to appserver
- retain appearance for legacy usage
- add theme & layout to registry and session
- 44 tests passing
@aaronsmulktis
aaronsmulktis requested review from marksibrahim and a lite review from Copilot August 8, 2026 00:36
@aaronsmulktis aaronsmulktis self-assigned this Aug 8, 2026
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Aug 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class “Code Editor” task support by introducing EditFileTask, along with configuration, documentation, and tests to validate reward logic when editing or creating files in the Code Editor app.

Changes:

  • Introduces EditFileTask with custom completion logic that inspects the Code Editor file tree directly.
  • Adds unit tests and task config entries for editing an existing file and creating a new file.
  • Updates docs and a small launcher logging robustness tweak; cleans up a sitemap merge artifact.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/test_codeeditor_tasks.py Adds unit tests covering EditFileTask reward logic and task instantiation via load_task.
src/open_apps/tasks/tasks.py Implements EditFileTask and related helpers for matching file content and detecting changes vs initial state.
src/open_apps/tasks/init.py Re-exports EditFileTask and maps it to the codeeditor app for task filtering.
src/open_apps/launcher.py Removes local ${now:...} resolver registration and hardens W&B action logging against missing obs/agent_info.
site/sitemap.xml Resolves merge-conflict artifacts and normalizes sitemap entries.
scripts/conduct_slurm.sh Updates header comment describing cluster/network assumptions.
docs/tasks.md Documents EditFileTask usage with YAML examples.
config/tasks/original_tasks.yaml Adds two Code Editor tasks using EditFileTask.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/open_apps/tasks/tasks.py
Comment thread scripts/conduct_slurm.sh
Comment thread config/tasks/original_tasks.yaml
Comment thread docs/tasks.md

@marksibrahim marksibrahim left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for adding the coding editor tasks. These seem reasonable overall. I want to hold off on merging until 1) unit-test pass (currently failing in this branch) 2) I run the task locally on my end. Would you mind looking into 1) for now?

@aaronsmulktis
aaronsmulktis changed the base branch from main to aaronsmulktis/coord-rescale August 17, 2026 22:17
@aaronsmulktis
aaronsmulktis requested a lite review from Copilot August 17, 2026 22:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (7)

scripts/conduct_slurm.sh:7

  • Spelling/grammar in this comment: “This assume” → “This assumes”, and “Gemme” → “Gemma”.
# target model on :8000), and launches the worker pool pointed at it. This assume
# the eval job is running on the same internal network as Gemme.

config/browsergym_env_args/screenshot.yaml:20

  • Typo in comment: “neets” → “needs”.
  base_url: null # this neets to be the localhost url, will be set automatically in launch_experiment.py

config/browsergym_env_args/screenshot.yaml:16

  • The inline comment is misleading: headless: True runs without showing a browser window, so it does not “keep the browser open” in a visible sense.
headless: True # keep the browser open

src/open_apps/tasks/tasks.py:732

  • Docstring says to provide exactly one of expected_content or required_fragment, but _content_matches() currently allows both (it will silently ignore required_fragment if expected_content is set). This makes misconfigurations easy to miss; consider enforcing mutual exclusivity.
    def _content_matches(self, content: str) -> bool:
        if self.expected_content is not None:
            return self._normalize(content) == self._normalize(self.expected_content)
        if self.required_fragment is not None:
            return self._normalize(self.required_fragment) in self._normalize(content)

src/open_apps/tasks/tasks.py:712

  • _normalize() uses .strip(), which removes leading whitespace from the first line and can change the meaning of indentation-sensitive files; the comment above says it only strips trailing whitespace per line. This can make expected_content matches pass/fail incorrectly when the file begins with spaces.
        return "\n".join(line.rstrip() for line in lines).strip()

config/browsergym_env_args/screenshot.yaml:14

  • Typo in comment: “envrionments” → “environments”.

This issue also appears in the following locations of the same file:

  • line 16
  • line 20
task_seed: 42 # not relevant for us we have only deterministic envrionments

docs/tasks.md:100

  • The example command references agent=gemma-4, but there is no config/agent/gemma-4.yaml in this repo. Use an existing agent config name so the command is runnable as written.
uv run launch_agent.py agent=gemma-4 task_name=edit_script_add_header_comment

@aaronsmulktis

Copy link
Copy Markdown
Contributor Author

Thank you for adding the coding editor tasks. These seem reasonable overall. I want to hold off on merging until 1) unit-test pass (currently failing in this branch) 2) I run the task locally on my end. Would you mind looking into 1) for now?

All failing test are within tests/test_longer_horizon.py which I never touched, after pulling in the latest upstream main I see no changes. Should I debug these longer horizon tests? I will likely require spending some time running those evals and understanding what the tests need to do.

These are on the public tip, not just in history. The earlier cleanup commits
scrubbed config/mode/slurm_cluster.yaml and docs/agents.md but missed these two
files, so the account, QOS, partition and a node hostname have been readable in
a checkout of main this whole time.

scripts/conduct_slurm.sh
  --account, --qos and --partition now use the same *_replace_me placeholders
  as config/mode/slurm_cluster.yaml. SBATCH directives are parsed before the
  shell runs, so they cannot be env-substituted -- the header now says they are
  placeholders and points at submit-time flags, which override the directives.
  sbatch rejects the job until one or the other names a real allocation, which
  is the right failure for a public repo.

config/agent/gemma-4-computer-use.yaml
  Example hostname in a comment.

This does not touch history -- f584c60 and the commits after it still carry
these strings on the public remote. Whether to rewrite that is a separate
decision; force-pushing alone would not remove the objects from GitHub anyway.
@aaronsmulktis aaronsmulktis changed the title Code Editor Tasks [Improvement] Code Editor Tasks Aug 20, 2026
aaronsmulktis and others added 13 commits August 20, 2026 19:58
fast_app()/FastHTML() load htmx, Pico and three helper scripts from
cdn.jsdelivr.net by default. The eval nodes have no outbound network, so none
of it arrives there, and nothing anywhere reports that:

  * htmx missing makes every hx-* attribute inert. /todo alone carries 15
    hx-put attributes. A checkbox still toggles on click -- that is native
    browser behaviour, not htmx -- so the screenshot shows the interaction
    landing while no PUT is sent, /todo_all never changes, and the task scores
    zero. The trajectory reads as a model that clicked the right element.
  * Pico missing renders every page unstyled, which changes the observation a
    screenshot-scored agent is graded on.

Vendors htmx 2.0.4 (0BSD) and Pico 2.1.1 (MIT) under apps/assets/vendor, served
by the static route that already serves jquery and fontawesome the same way.
Versions are pinned in the filename: the default pulled pico@latest, so a run's
styling depended on the day it ran.

Every FastHTML construction site now passes default_hdrs=False and takes
headers from open_apps.frontend.local_hdrs(). That also removes a duplicate
htmx 1.9.10 from unpkg in messenger, which was racing the 2.0.4 FastHTML
injected, and two picolink references in codeeditor whose hdrs are rebuilt in
set_environment.

Out of scope here, and still listed in the test allowlist: Tailwind, daisyUI,
Font Awesome, highlight.js, phosphor-icons and Leaflet. Those change appearance
rather than behaviour; Leaflet needs the map app rethought.

tests/test_no_egress.py ratchets this. The load-bearing case is
test_interactive_routes_load_htmx_locally: a page with hx-* attributes must
load htmx from local assets. Verified it has teeth by reverting todo_app to
fast_app() -- three tests fail with the fix in the message. Full suite: 704
passed.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…is/scrub-cluster-values

[Chore] Replace configs with placeholders
…is/vendor-frontend-assets

Serve `htmx` and `Pico` locally instead of from a CDN
Vision models disagree about what an (x, y) in their output means, and
getting it wrong is silent: the click lands somewhere plausible and the
episode scores 0 without an error. Gemma clicking off-target under
screenshot-only is this failure.

Add action_parsers/coords.py::rescale_xy as the single conversion point
and route every parser through ActionParser.rescale:

- ActionParser gains a coord_scale field. None = raw viewport pixels,
  N = a normalized [0, N) grid.
- qwen3vl's hardcoded _COORD_SPACE = 1000 becomes coord_scale = 1000,
  so it is now overridable rather than baked in. Behavior unchanged.
- uitars was discarding its viewport argument and passing raw pixels
  straight through, so no normalized-grid model could use that grammar.
  It now threads a rescale hook into flexible_parser/uitars_parser,
  applied to click, right_single, and the scroll magnitude (which
  UI-TARS reads off a point, so it shares the coordinate space).
  coord_scale defaults to None, keeping the UI-TARS path byte-identical
  -- pinned by a regression test.
- Plumb AgentArgs.coord_scale -> VLLMAgent -> get_action_parser, so a
  family's default can be overridden per model in yaml. Passing None
  means "keep the family default", not "raw pixels".

rescale_xy applies one scalar against each viewport axis independently,
which is what a square normalized grid means; it cannot express a model
predicting in its own non-square resized image space. Noted in the
docstring.

Also log a warning on the (1920, 1080) viewport fallback in vLLM_prompt.
It is only reachable with use_screenshot off, but under a non-1080p
preset it would silently miscale every rescaled coordinate.

Gemma's actual convention is unmeasured -- the Gemma lineage bins
locations to 0-1024, but that is inference from the family, not data. A
wrong scale fails exactly like no scale, so README documents a
calibration recipe using set_of_marks_coordinates.json as the oracle
rather than shipping a guessed default.
1. edit script task
1. create notes file task
1. documentation
1. tests
The local 'now' resolver registration was dead code: launcher.py never
imported datetime, so the lambda would NameError if it ran, yet runs work
because Hydra registers its own 'now' resolver that shadows this one.
Remove it to silence the register_resolver() deprecation warning.
1. add SOM
1. use axtree
1. use html
1. remove prompt_txt
1. add wait to custom_actions
1. improve prompt (w/bids, not coords)
1. screenshot config
1. agent config test
1. editor save test
1. add wait to custom_actions
1. improve prompt (w/bids, not coords)
1. screenshot config
Two gaps in the coord_scale plumbing, both of which made a normalized
coordinate space silently not apply.

1. A model prompted directly in browsergym syntax emits
   mouse_click(x=, y=) rather than UI-TARS's click(point=), so it matched
   none of the remaps in uitars_parser and skipped rescaling entirely.
   This is the common case -- config/agent/default.yaml has always
   prompted for mouse_click(x=612, y=455). Rewrite those in place via
   _BG_MOUSE_XY_RE, preserving trailing kwargs so button='right'
   survives, and covering dblclick/move/down/up alongside click.

2. UITarsActionParser.parse always passed a rescale hook, even with
   coord_scale=None, so "no conversion" still round-tripped through
   int(round(float(x))). That rounded float coordinates and rewrote
   already-valid calls. Pass no hook at all when there is nothing to
   convert, so the default path leaves coordinates exactly as written.

The regression guard for (2) is what caught it: mouse_click(x=500.5)
was coming back as x=500 on the default UI-TARS path.
Adds config/agent/gemma-4-31B-coords.yaml as a sibling to the existing
bid-based gemma-4-31B-computer-use.yaml rather than converting it, so
the working set-of-marks config stays intact and the two can be A/B'd.

Rather than reverse-engineering Gemma's native coordinate convention,
this declares a 1000x1000 grid in the prompt and sets coord_scale: 1000
to match -- the same trick Qwen3.6-VL-computer-use.yaml uses. If the
model honors the declared space the conversion is correct by
construction, which is a much shorter path than measuring what a
checkpoint happens to emit. If it does not honor it, the README
calibration recipe applies and coord_scale=1024 (the Gemma/PaliGemma
<loc> binning) is the first alternative to try; it is overridable at
launch, no config edit needed.

Coherence tests pin the three things that must agree -- the grid named
in the prompt, coord_scale, and the pixels that actually come out of the
parser -- because drift between them is invisible at runtime: the click
just lands somewhere plausible and the episode scores 0.

scroll deltas stay in pixels and the prompt says so explicitly; a model
on a normalized grid would otherwise have no way to know the units.
The header presented coordinate mode as a viable path pending
calibration. Cluster runs since then settled it: inverting the executed
action through the conversion reproduces the model's stated coordinates
exactly, at two different scales, so the pipeline was never the problem
and no coord_scale value fixes it. Gemma's spatial estimate is simply
wrong.

Rewritten as a negative result -- what was tried, what the numbers were,
and why bids (and, better, the accessibility tree) are the supported
route -- so nobody re-runs the experiment in three months. Also warns
against the coord_scale=1024 override, which contradicts the 1000x1000
grid the prompt declares, and notes that omitting the screenshot env
preset leaves max_steps at 10.
1. record last-action errors
1. send last_action_error to W&B
1. add slow mode in toml
@aaronsmulktis
aaronsmulktis force-pushed the aaronsmulktis/editor-tasks branch from f1559af to 77147e3 Compare August 24, 2026 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants