Spaces:
Sleeping
Sleeping
Xining Li
Deploy snapshot: causal-gate + flash-offer tasks (textbook/ omitted, binary PDF rejected by HF's plain-git push policy)
6ec7f56 Download harness/agents/scripted.py from xiningli/webtask-arena: direct link, hf CLI and curl.
- Browser
- Download file 4.43 kB
-
https://huggingface.co/spaces/xiningli/webtask-arena/resolve/main/harness/agents/scripted.py
- Command line
-
hf download hf://spaces/xiningli/webtask-arena/harness/agents/scripted.py
-
curl -L -o scripted.py https://huggingface.co/spaces/xiningli/webtask-arena/resolve/main/harness/agents/scripted.py
4.43 kB
| """Scripted oracle agent — the harness's own reference implementation. | |
| It parses the natural-language instruction (never the oracle API) and emits | |
| ordinary computer-use actions, but it locates click targets via the DOM | |
| (`browser.center`) instead of pixels. Its purpose is to validate the full | |
| pipeline — env → screenshot loop → action executor → server state → verify — | |
| not to be a fair baseline. Model adapters must not receive the browser handle. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from typing import Iterator | |
| from ..browser import Browser | |
| from .base import Observation | |
| # must match server/seeding.py TIMEZONES order (oracle knowledge, documented) | |
| TIMEZONES = [ | |
| "UTC", "America/Vancouver", "America/New_York", "Europe/Paris", | |
| "Europe/Berlin", "Asia/Tokyo", "Asia/Singapore", "Australia/Sydney", | |
| ] | |
| class ScriptedAgent: | |
| def __init__(self, browser: Browser, task_id: str): | |
| self.browser = browser | |
| self.task_id = task_id | |
| self._plan: Iterator[dict] | None = None | |
| def begin(self, instruction: str) -> None: | |
| plans = { | |
| "email-triage": self._email_plan, | |
| "settings-panel": self._settings_plan, | |
| "checkout-form": self._checkout_plan, | |
| } | |
| if self.task_id not in plans: | |
| raise ValueError(f"scripted agent has no plan for '{self.task_id}'") | |
| self._plan = plans[self.task_id](instruction) | |
| def step(self, obs: Observation) -> dict: | |
| assert self._plan is not None, "begin() not called" | |
| try: | |
| return next(self._plan) | |
| except StopIteration: | |
| return {"action": "done"} | |
| # ------------------------------------------------------------------ plans | |
| def _click(self, selector: str, has_text: str | None = None) -> dict: | |
| x, y = self.browser.center(selector, has_text) | |
| return {"action": "left_click", "coordinate": [round(x), round(y)]} | |
| def _email_plan(self, instruction: str) -> Iterator[dict]: | |
| m = re.search(r"archive every email from (.+?) and star the email " | |
| r"with the subject “(.+?)”", instruction) | |
| assert m, f"could not parse instruction: {instruction!r}" | |
| sender, subject = m.group(1), m.group(2) | |
| while self.browser.exists("tr.email-row", has_text=sender): | |
| row = f"tr.email-row:has(td.sender:text-is('{sender}'))" | |
| x, y = self.browser.center(f"{row} .archive-btn") | |
| yield {"action": "left_click", "coordinate": [round(x), round(y)]} | |
| yield {"action": "wait", "duration": 0.3} | |
| star_row = f"tr.email-row:has-text('{subject}')" | |
| yield self._click(f"{star_row} .star-btn") | |
| def _settings_plan(self, instruction: str) -> Iterator[dict]: | |
| m = re.search(r"set the timezone to (\S+?),", instruction) | |
| assert m, f"could not parse instruction: {instruction!r}" | |
| target_tz = m.group(1) | |
| yield self._click("#nav button", has_text="Appearance") | |
| yield self._click("input[data-field='dark_mode']") | |
| yield self._click("#nav button", has_text="General") | |
| # focus the timezone <select>, then arrow down from UTC (index 0) | |
| yield self._click("select[data-field='timezone']") | |
| for _ in range(TIMEZONES.index(target_tz)): | |
| yield {"action": "key", "text": "Down"} | |
| yield {"action": "key", "text": "Return"} # close the dropdown | |
| yield self._click("#save") | |
| yield {"action": "wait", "duration": 0.3} | |
| def _checkout_plan(self, instruction: str) -> Iterator[dict]: | |
| m = re.search(r"checkout for (.+?) \(email: (.+?)\)\. " | |
| r"Ship to (.+?), (.+?), ZIP (\d{5})", instruction) | |
| assert m, f"could not parse instruction: {instruction!r}" | |
| name, email, street, city, zip_code = m.groups() | |
| for field, value in (("#name", name), ("#email", email)): | |
| yield self._click(field) | |
| yield {"action": "type", "text": value} | |
| yield self._click("#next1") | |
| yield {"action": "wait", "duration": 0.3} | |
| for field, value in (("#street", street), ("#city", city), ("#zip", zip_code)): | |
| yield self._click(field) | |
| yield {"action": "type", "text": value} | |
| yield self._click("#next2") | |
| yield {"action": "wait", "duration": 0.3} | |
| yield self._click("#submit") | |
| yield {"action": "wait", "duration": 0.3} | |