fix(ci): unbreak main — ruff format, test_refs, test_model_catalog (#7084)

* fix(ci): apply ruff format to browser tool files

Refs #7083

* fix(ci): unbreak test_refs (img regression) and test_model_catalog

test_refs:
- Add `img` back to CONTENT_ROLES so named images get refs again. The
  recent `cc6ec97a feat: multiple modes browser snapshot tool` refactor
  renamed NAMED_CONTENT_ROLES → CONTENT_ROLES and accidentally dropped
  `img`, breaking `test_named_content_roles_get_refs`.
- Drop the `navigation` assertion from `test_skips_structural_roles`.
  That same refactor intentionally added landmark roles (navigation,
  main, listitem) to CONTENT_ROLES so AI agents can ref them by name,
  and the test was not updated to reflect that.

test_model_catalog:
- Add 5 openrouter models that were added to model_catalog.json by
  #7081 (UI/UX improvements) but not reflected in the test.

Refs #7083

* fix(ci): wait for event propagation in subagent report test on Windows

`test_worker_report_emits_subagent_report_event` waited only for
`worker.is_active` to flip to False, then immediately asserted on the
collected events. On Windows the event loop scheduling differs enough
that the SUBAGENT_REPORT subscriber callback can run a few ticks after
the worker is marked inactive, so the assertion fires against an empty
list. Wait for both conditions.

Refs #7083
This commit is contained in:
Hundao
2026-04-18 19:09:15 +08:00
committed by GitHub
parent 49317ac5f5
commit 90aadf247a
6 changed files with 17 additions and 14 deletions
+5 -2
View File
@@ -274,9 +274,12 @@ class TestReportToParent:
worker = colony.get_worker(worker_ids[0])
assert worker is not None
# Wait for the worker's background task to finish
# Wait for the worker to finish AND for the SUBAGENT_REPORT event
# to propagate. On Windows the event loop scheduling differs from
# POSIX, so a worker can be marked inactive a few ticks before the
# subscriber callback runs. Waiting on both avoids that race.
deadline = asyncio.get_event_loop().time() + 5.0
while worker.is_active and asyncio.get_event_loop().time() < deadline:
while (worker.is_active or len(reports) == 0) and asyncio.get_event_loop().time() < deadline:
await asyncio.sleep(0.05)
assert not worker.is_active, "Worker did not finish within timeout"
+5
View File
@@ -150,6 +150,11 @@ def test_openrouter_catalog_tracks_current_frontier_set():
"anthropic/claude-opus-4.6",
"google/gemini-3.1-pro-preview-customtools",
"deepseek/deepseek-v3.2",
"qwen/qwen3.6-plus",
"z-ai/glm-5v-turbo",
"x-ai/grok-4.20",
"xiaomi/mimo-v2-pro",
"stepfun/step-3.5-flash",
]
assert openrouter_models[0]["max_tokens"] == 128000
assert openrouter_models[0]["max_context_tokens"] == 922000
+1
View File
@@ -50,6 +50,7 @@ CONTENT_ROLES: frozenset[str] = frozenset(
"columnheader",
"gridcell",
"heading",
"img",
"listitem",
"main",
"navigation",
+1 -2
View File
@@ -187,8 +187,7 @@ def _resize_and_annotate(
)
except Exception:
logger.warning(
"Screenshot resize/annotate FAILED — returning original image. "
"css_width=%s, dpr=%s.",
"Screenshot resize/annotate FAILED — returning original image. css_width=%s, dpr=%s.",
css_width,
dpr,
exc_info=True,
+2 -8
View File
@@ -546,10 +546,7 @@ def register_interaction_tools(mcp: FastMCP) -> None:
if x > 1.5 or y > 1.5 or x < -0.1 or y < -0.1:
result = {
"ok": False,
"error": (
f"Coords ({x}, {y}) look like pixels. This tool expects "
"fractions 0..1 of the viewport."
),
"error": (f"Coords ({x}, {y}) look like pixels. This tool expects fractions 0..1 of the viewport."),
}
log_tool_call("browser_hover_coordinate", params, result=result)
return result
@@ -627,10 +624,7 @@ def register_interaction_tools(mcp: FastMCP) -> None:
if x > 1.5 or y > 1.5 or x < -0.1 or y < -0.1:
result = {
"ok": False,
"error": (
f"Coords ({x}, {y}) look like pixels. This tool expects "
"fractions 0..1 of the viewport."
),
"error": (f"Coords ({x}, {y}) look like pixels. This tool expects fractions 0..1 of the viewport."),
}
log_tool_call("browser_press_at", params, result=result)
return result
+3 -2
View File
@@ -45,8 +45,9 @@ class TestAnnotateSnapshot:
def test_skips_structural_roles(self):
annotated, ref_map = annotate_snapshot(SAMPLE_SNAPSHOT)
roles_in_map = {entry.role for entry in ref_map.values()}
# navigation, main, list, listitem, paragraph are structural — no refs
assert "navigation" not in roles_in_map
# main (unnamed), list, listitem (unnamed), paragraph are structural — no refs.
# Note: navigation is a landmark role and now gets a ref when named, so it
# is not asserted absent here.
assert "main" not in roles_in_map
assert "list" not in roles_in_map
assert "listitem" not in roles_in_map