feat(#175): network response + dump commands for API flow capture#464
feat(#175): network response + dump commands for API flow capture#464giulio-leone wants to merge 4 commits intovercel-labs:mainfrom
Conversation
|
@g97iulio1609 is attempting to deploy a commit to the Vercel Labs Team on Vercel. A member of the Team first needs to authorize it. |
6b1453c to
3869b3e
Compare
Add networkdump command with host/type filters, header redaction, idempotent tracking, WeakMap response matching, and monotonic IDs. Refs: vercel-labs#175
72f46f1 to
0c38cfb
Compare
There was a problem hiding this comment.
Pull request overview
Adds network inspection and export capabilities to the agent-browser CLI/protocol so users can capture API flows (requests + responses) during a browsing session, including new “network response” and “network dump” commands and enhanced request filtering/redaction.
Changes:
- Extend request tracking to include monotonically increasing request IDs plus response status/headers, with multi-page listener attachment.
- Add new protocol/types for
networkdumpand extendrequestscommand options (host,type,redact). - Update CLI parsing to support
network responseandnetwork dump, plus newnetwork requestsfilters.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types.ts | Adds new command type (NetworkDumpCommand) and extends RequestsCommand options. |
| src/protocol.ts | Adds Zod schema for networkdump and extends requests schema with new filters. |
| src/browser.ts | Implements request IDs, response metadata capture, multi-page tracking, filtering, and redaction in getRequests. |
| src/actions.ts | Wires the new networkdump action into dispatch and implements file export handler. |
| cli/src/commands.rs | Adds CLI subcommands network response and network dump and extends network requests flags. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| getRequests(options?: { | ||
| filter?: string; | ||
| host?: string; | ||
| type?: string; | ||
| redact?: boolean; | ||
| }): TrackedRequest[] { |
There was a problem hiding this comment.
getRequests was changed to accept an options object, but there are still call sites passing a plain string (e.g. the requests action handler). Without an overload/backwards-compat shim this will fail TypeScript compilation. Either keep a string overload (delegating to { filter }) or update all callers to the new { filter, host, type, redact } shape.
There was a problem hiding this comment.
Fixed in the latest commit. See the push for details.
| page.on('response', (response) => { | ||
| const reqId = requestMap.get(response.request()); | ||
| if (reqId !== undefined) { | ||
| const tracked = this.trackedRequests.find((r) => r.id === reqId); | ||
| if (tracked) { | ||
| tracked.statusCode = response.status(); | ||
| tracked.responseHeaders = response.headers(); | ||
| } |
There was a problem hiding this comment.
In the response listener, updating the tracked entry uses this.trackedRequests.find(...), which makes response processing O(n) per response and can become noticeably slow on pages with lots of requests. Consider storing a direct reference (e.g., WeakMap<Request, TrackedRequest> or Map<number, TrackedRequest>) so the update is O(1).
There was a problem hiding this comment.
Fixed in the latest commit. See the push for details.
| case 'networkdump': | ||
| return await handleNetworkDump(command, browser); |
There was a problem hiding this comment.
New networkdump action will be categorized as unknown by the action policy system unless it’s added to ACTION_CATEGORIES (likely under 'network'). With a default-deny policy (or confirmation rules), this command may be unexpectedly blocked or treated differently than other network actions.
There was a problem hiding this comment.
Fixed in the latest commit. See the push for details.
| Some("response") => { | ||
| let url = rest.get(1).ok_or_else(|| ParseError::MissingArguments { | ||
| context: "network response".to_string(), | ||
| usage: "network response <url> [--timeout <ms>]", | ||
| })?; | ||
| let timeout_idx = rest.iter().position(|&s| s == "--timeout"); | ||
| let timeout = timeout_idx.and_then(|i| rest.get(i + 1).and_then(|s| s.parse::<u64>().ok())); | ||
| let mut cmd = json!({ "id": id, "action": "responsebody", "url": url }); | ||
| if let Some(t) = timeout { | ||
| cmd["timeout"] = json!(t); | ||
| } | ||
| Ok(cmd) |
There was a problem hiding this comment.
network response is wired to the existing responsebody action, which currently returns { url, status, body } but not response headers. This doesn’t match the PR description/CLI docs that say headers are returned; either include headers in the responsebody response or adjust the command description/output expectations accordingly.
There was a problem hiding this comment.
Fixed in the latest commit. See the push for details.
- Use Map<number, TrackedRequest> for O(1) response matching instead of find() - Add networkdump and responsebody to ACTION_CATEGORIES under network - Include response headers in responsebody action output
Fixes TS2345: command.filter (string) is not assignable to the options object parameter. Spread all RequestsCommand filter fields properly.
Closes #175
New Commands
network response <url> [--timeout <ms>]Wait for and capture a response matching a URL pattern. Returns status code, headers, and parsed body.
network dump --out <path> [--filter <url>] [--host <domain>] [--type <types>] [--redact]Export all tracked requests as structured JSON.
Enhanced
network requestsFilters--host <domain>— Filter by hostname (substring match)--type xhr,fetch— Filter by resource type (comma-separated)--redact— Mask sensitive headers (Authorization, Cookie, Set-Cookie, X-Api-Key, X-Auth-Token)--filter <url>— Existing URL substring filter (unchanged)Implementation Details
TrackedRequestwith auto-increment IDs, status codes, response headersWeakMap-based response matching (Playwright Request identity, not URL)isTrackingRequests)setupPageTrackingExample Usage