Wait for Browser screencast frames

Replace the WebSocket viewer frame pump's idle poll with read_screencast_frame so live screencast delivery follows the producer cadence instead of a 50 ms sleep cycle. Keep idle-page timeouts inside the stream loop to avoid screencast restart flashes, and update the Browser regression test to pin the blocking read path and timeout handling.

Alessandro committed Jul 3, 2026 at 01:25 UTC 686e039d1b779ecf864d9654bfe175c53d7d3096
2 files changed +11 -5
plugins/_browser/api/ws_browser.py
+7 -4
@@ -11,7 +11,7 @@ from helpers.ws_manager import WsResult
11 from plugins._browser.helpers.runtime import get_runtime, list_runtime_sessions
12
13
14 -FRAME_IDLE_POLL_SECONDS = 0.05
14 +FRAME_READ_TIMEOUT_SECONDS = 0.5
15 FRAME_RETRY_DELAY_SECONDS = 0.5
16 FRAME_STATE_REFRESH_SECONDS = 0.75
17 SNAPSHOT_STATE_POLL_SECONDS = 0.75
@@ -445,11 +445,14 @@ class WsBrowser(WsHandler):
445 last_state_refresh = now
446
447 try:
448 - frame = await runtime.call("pop_screencast_frame", stream_id)
448 + frame = await runtime.call(
449 + "read_screencast_frame",
450 + stream_id,
451 + timeout=FRAME_READ_TIMEOUT_SECONDS,
452 + )
453 except KeyError:
454 break
451 - if frame is None:
452 - await asyncio.sleep(FRAME_IDLE_POLL_SECONDS)
455 + except TimeoutError:
456 continue
457
458 frame["context_id"] = context_id
tests/test_browser_agent_regressions.py
+4 -1
@@ -1162,7 +1162,10 @@ def test_browser_viewer_defaults_to_live_screencast_with_snapshot_fallback():
1162 assert "initial_viewport = self._viewport_from_data(data)" in ws_browser
1163 assert '"set_viewport"' in ws_browser
1164 assert "start_screencast" in ws_browser
1165 - assert "pop_screencast_frame" in ws_browser
1165 + assert "read_screencast_frame" in ws_browser
1166 + assert "FRAME_READ_TIMEOUT_SECONDS" in ws_browser
1167 + assert "FRAME_IDLE_POLL_SECONDS" not in ws_browser
1168 + assert "except TimeoutError:" in ws_browser
1169 assert "stop_screencast" in ws_browser
1170 assert "viewer_transport == VIEWER_TRANSPORT_SCREENCAST" in ws_browser
1171 assert '"viewer_transport": viewer_transport' in ws_browser