Skip to content

feat(panel): responsive full-stretch viewport, live nav, fidelity + anti-detection (v0.6.1)#15

Merged
mabry1985 merged 1 commit into
mainfrom
feat/responsive-viewport
Jul 1, 2026
Merged

feat(panel): responsive full-stretch viewport, live nav, fidelity + anti-detection (v0.6.1)#15
mabry1985 merged 1 commit into
mainfrom
feat/responsive-viewport

Conversation

@mabry1985

Copy link
Copy Markdown
Contributor

Four fixes for actually using the interactive panel in a docked/resized console.

1. Full-stretch, responsive viewport

The canvas painted frames at Chrome's fixed viewport (1280×577 landscape) and CSS only shrank-to-fit — so a tall/wide dock showed a small landscape box in dead space. Now a debounced ResizeObserver reports the dock size and the server resizes Chrome's layout viewport to match (× device-pixel-ratio, ≤2) via Emulation.setDeviceMetricsOverride, re-arming the screencast at the new size. The page reflows to fill; the canvas fills the stage. Validated live: dock 900×1200 → frames arrive at 900×1200.

2. The agent's navigation is now visible (the big one)

A cross-process navigation swaps Chrome's render widget and silently kills the screencast — so you saw the first page load but nothing as the agent moved around or into sub-pages. Root-caused with a CDP event trace: data:/SPA navigations emit frameStoppedLoading / navigatedWithinDocument, not loadEventFired. The stream now re-arms on the full set of nav-complete signals (debounced). Validated: 4 sequential navigations each paint a fresh frame (was: only the first).

3. Higher fidelity

JPEG quality 60 → 80 (configurable via stream_quality) plus hi-dpi rendering (deviceScaleFactor up to 2×).

4. Anti-detection (stealth)

New knobs to help past bot walls (Google, Reddit, Cloudflare): stealth drops the navigator.webdriver automation flag and, when headless, swaps the "HeadlessChrome" UA for a real desktop one; plus user_agent / browser_args overrides. Most reliable paired with headed: true + a logged-in profile. No setting defeats detection entirely — documented as such. Launch flags moved to a shared runtime.launch_flags and now also apply when a session is started from the panel (Start button / URL bar), not just the agent's browser_open.

Notes

  • One shared write-lock on the CDP socket now that both the reader (acks + re-arm) and the request task (input + resize) write to it.
  • New config: stream_quality, stealth, user_agent, browser_args (all in Settings ▸ Plugins).
  • 45 host-free tests pass, ruff clean. New tests: viewport_metrics clamping, launch_flags/stealth, resize + nav wiring in the page, /nav applies launch flags.

🤖 Generated with Claude Code

… anti-detection (v0.6.1)

Four fixes for using the interactive panel in a real dock:

- Full-stretch, responsive viewport. A debounced ResizeObserver reports the dock's
  size; the server resizes Chrome's layout viewport to match (× DPR up to 2) via
  Emulation.setDeviceMetricsOverride and re-arms the screencast at that size — the
  page reflows to fill instead of a fixed landscape box in dead space. Canvas fills
  the stage. Validated live: dock 900x1200 → frames at 900x1200.

- The agent's navigation is now visible. A cross-process nav tears down Chrome's
  screencast, so you saw the first page but nothing as the agent moved around. Re-arm
  on every nav-complete signal (loadEventFired / frameStoppedLoading / frameNavigated
  / navigatedWithinDocument, debounced). Root-caused via CDP event trace: data:/SPA
  navs emit frameStoppedLoading, NOT loadEventFired. Validated: every page paints.

- Higher fidelity. JPEG quality 60 → 80 (configurable via stream_quality) + hi-dpi
  rendering.

- Anti-detection (stealth). New stealth / user_agent / browser_args config to help
  past bot walls (Google, Reddit, Cloudflare): stealth drops navigator.webdriver and,
  headless, swaps the HeadlessChrome UA for a real one. Launch flags (headed / profile
  / stealth / …) moved to a shared runtime.launch_flags and now also apply when a
  session is started from the panel, not just the agent's browser_open.

One shared write-lock on the CDP socket (reader acks/re-arm + request input/resize).
45 host-free tests pass; ruff clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@protoquinn

protoquinn Bot commented Jul 1, 2026

Copy link
Copy Markdown

👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow.

@mabry1985 mabry1985 merged commit bc12f73 into main Jul 1, 2026
1 check passed

@protoquinn protoquinn Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

QA Audit — PR #15 | feat(panel): responsive full-stretch viewport, live nav, fidelity + anti-detection (v0.6.1)

VERDICT: WARN


CI Status

  • test: success ✅

Diff Review

  • browser_panel.py: clean — launch_flags wired into panel /nav, stream_quality passthrough, CSS full-stretch + overflow:hidden, ResizeObserver (180ms debounce) → sendResize() on connect and resize. All good patterns.
  • browser_stream.py (visible): viewport_metrics() clamps defensively (CSS ≤2048, scale ∈[1,2], frame ≤2560). _NAV_DONE frozenset covers all four CDP nav-complete signals. CDPStream.__init__ gains quality/lock/last_arm fields. Docstring is thorough.

Observations

  • GAP: 340 of 560 diff lines truncated — the lock serialization, nav re-arm logic, resize CDP command (Emulation.setDeviceMetricsOverride), and dispatch() changes are not visible. These are the core of the PR's claims.
  • GAP: runtime.py is a new module not visible in the truncated diff — launch_flags() is imported by both browser_panel.py and presumably tools.py. Cannot review stealth/UA/flag logic.
  • GAP: clawpatch structural review unavailable (HTTP 502 — checkout cache error). No cross-file analysis performed.
  • LOW: viewport_metrics floors scale at 1.0 (max(1.0, …)) — sub-1-DPR displays get upscaled. Intentional, minor bandwidth trade-off.
  • LOW: sendResize() guards >10px — panel collapse yields no resize, screencast keeps running at last size. Acceptable.
  • LOW: _NAV_DONE docstring mentions only frameNavigated/loadEventFired, but the frozenset also includes frameStoppedLoading/navigatedWithinDocument. Code is correct; docstring is slightly incomplete.

— Quinn, QA Engineer

@protoquinn

protoquinn Bot commented Jul 1, 2026

Copy link
Copy Markdown

Submitted COMMENT review on #15.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant