Skip to content

fix(cli): restore V3 network capture through a CDP sidecar - #2849

Draft
shrey150 wants to merge 6 commits into
agent/browse-v4-4-runtimefrom
agent/browse-v4-network-sidecar
Draft

fix(cli): restore V3 network capture through a CDP sidecar#2849
shrey150 wants to merge 6 commits into
agent/browse-v4-4-runtimefrom
agent/browse-v4-network-sidecar

Conversation

@shrey150

@shrey150 shrey150 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Stack

  1. chore(cli): import Browse V3 baseline #2833 — exact Browse V3 baseline import
  2. refactor(cli): migrate Browse runtime to Stagehand V4 #2834 — Stagehand V4 runtime cutover and CLI-owned cursor
  3. fix(cli): restore V3 network capture through a CDP sidecar #2849 — CLI-private CDP sidecar; restores V3 network capture
  4. refactor(cli): remove coordinate XPath return flag #2835 — remove --return-xpath; complete supported V3 parity
  5. test(evals): exercise the workspace V4 CLI #2838 — eval, packaging, and release wiring
  6. fix(cli): persist context names in Browserbase #2839 — managed Context names (fast-follow)
  7. refactor(cli): consume shared Functions core #2701 — shared Functions core consumer (fast-follow)

Why

Browse V3 reads raw CDP Network events from the page frame session. Stagehand V4 does not expose that session. Adding a public page.on("network") API would commit the framework, protocol, generated SDKs, and extension to a new event schema before that API has been designed.

This PR restores CLI parity without expanding Stagehand public API surface.

Architecture

  • Lazily opens one CLI-private browser-level CDP WebSocket using the endpoint already held by the initialized Stagehand client.
  • Attaches a flattened CDP session to the active V4 page target.
  • Presents the V3 writer with the same on / off / send session shape it used before.
  • On browse network off, removes listeners, sends Network.disable, and detaches the page target.
  • Keeps the browser-level sidecar WebSocket alive across off/on cycles. Browserbase treats closing an auxiliary browser WebSocket during a live session as a disconnect.
  • Closes the sidecar only during browse close.
  • Never logs or returns the signed browser WebSocket endpoint.

The request correlation and request/response JSON writer are inherited from the V3 CLI. No protocol schema, extension, SDK, or generated-client changes are included.

Versioning is intentionally deferred to the consolidated Browse minor changeset in #2838.

User-visible behavior

The command surface and files remain the V3 shape:

browse network on
browse network path
browse network clear
browse network off

Each request directory still contains request.json and, when available, response.json, including POST bodies, response bodies, failures, redirects, and cache hits with the existing V3 semantics.

Verification

  • pnpm --filter browse test: 27 test files, 382 tests passed against the built CLI.
  • pnpm --filter browse lint: formatting, ESLint, and TypeScript passed.
  • Added focused tests for browser-WebSocket reuse, target attach/detach, CDP event routing, off/on lifecycle, the request-write race, response-body capture, and V3-shaped files.
  • The actual built V3 CLI and actual built V4 CLI produced zero normalized command or artifact differences across GET, POST, cache, binary body, redirect, failure, clear, and permissions cases.
  • The actual built V4 CLI completed two sidecar on/off cycles in one real Browserbase session and remained usable afterward.

Built CLI E2E matrix

The local differential invoked each built CLI as a subprocess against the same HTTP fixture:

browse open <fixture>/page
browse network on
browse eval <GET + cached GET + POST + redirect + binary + aborted request>
browse network path
browse network off
browse network clear
browse stop
Flow Actual V3 CLI Actual V4 CLI on this PR Result
network on/path/off/path/clear return shape enabled/path states present Same Command diffs: []
Page evaluation result GET, cached GETs, POST, redirect, binary, and expected failure completed Same Exact result match
Captured artifacts 8 requests / 7 responses 8 requests / 7 responses Same counts
Normalized request/response JSON 8 records 8 records 0 structural differences
POST Request body and 201 response body captured Same Match
Cache Two capture records while the origin was hit once per browser Same Match
Redirect /redirect request-only plus /final request/response Same existing V3 behavior Match
Aborted request Status 0 failure response Same Match
Binary response Existing base64-preview representation Same Match
Permissions Directories 0700; request/response files 0600 Same Match
Clear 0 entries remained 0 entries remained Match

Normalization was deliberately limited to values that cannot match across independent browser runs: CDP request ID, timestamp, duration, HTTP Date, and fixture origin/port. Header names/casing, directory counters, methods, paths, bodies, statuses, MIME types, status text, error shape, and file modes were compared as emitted.

The Browserbase matrix also invoked the actual built CLI:

Remote flow Observed result
First network on → navigate → off GET 200 and full Example Domain response body captured
Clear, then second network on → navigate → off GET 200 and body captured again
Sidecar lifecycle Browserbase session identity stayed stable across both cycles
Navigation after network off A new open --wait networkidle completed
Daemon after both cycles browserConnected: true, initialized: true, mode remote
Cleanup browse stop completed; no remote or local test artifacts retained

Review guide

  1. network-cdp-sidecar.ts: the isolated transport and lifecycle.
  2. network-capture.ts: the narrow adapter from V4 pageId to the preserved V3 writer.
  3. session-manager.ts: endpoint access and close ordering.
  4. Focused tests, then the differential E2E evidence.

The built-CLI local differential and real Browserbase lifecycle matrix are attached above. This remains draft for code review, not for missing runtime proof.


Summary by cubic

Restores V3 network capture in the Browse V4 CLI via a CLI-owned CDP sidecar. Previously browse network on failed because the V4 runtime no longer exposes the page frame session; now it works without expanding the public Stagehand API.

Details

  • Opens a single browser-level CDP WebSocket using the endpoint already held by the Stagehand client.
  • Attaches a flattened CDP session to the active page target and feeds the existing V3 network writer unchanged.
  • Keeps the sidecar open across off/on cycles; Browserbase treats an auxiliary WebSocket close as a browser disconnect.
  • Closes the sidecar only during browse close.
  • Adds tests for sidecar reuse, attach/detach, event routing, and V3-shaped request/response files.

Written for commit 86ea880. Summary will update on new commits.

Review in cubic

@changeset-bot

changeset-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 86ea880

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

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