[Improvement] Code Editor Tasks - #70
Conversation
- 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
There was a problem hiding this comment.
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
EditFileTaskwith 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.
marksibrahim
left a comment
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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: Trueruns 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_contentorrequired_fragment, but_content_matches()currently allows both (it will silently ignorerequired_fragmentifexpected_contentis 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 makeexpected_contentmatches 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 noconfig/agent/gemma-4.yamlin 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
[Improvement] Todo layout
All failing test are within |
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.
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
f1559af to
77147e3
Compare
Changes
edit_script_add_header_commenttaskcreate_notes_file_in_code_editortasksitemap.xmlregister_resolver()error