Introduce `Page.onResponse`
ZI
17h ago+199+199+012345678901234567890123456789-25-25-01234567890123456789
Add dedicated Page.onResponse() event listener, matching Playwright's Page.on("response") (docs).
PR Stack
Architecture
There are two broad stroke changes:
- Drilling a "response subscription" all the way from the SDK client
Pagethrough -> RPC ->StagehandRuntime-> UnderstudyPage->NetworkManager-> CDP. - Using the existing
class Responseas the callback return type! We hold references to these objects in a newResponseHandlerTablethat gets looked up whenever the SDK client asks for it.
flowchart TB
subgraph CLIENT["SDK client"]
PAGE["Page<br/>+onResponse()<br/>+on_response()"]
SDKRESP["Response<br/>body() · text() · json()"]
RPC["RPCClient"]
RPC -.->|"page.event"| PAGE
PAGE -->|"listener(response)"| SDKRESP
SDKRESP -->|"response.body(responseId)"| RPC
end
subgraph SW["Extension worker"]
RUNTIME["StagehandRuntime<br/>±pageOn()"]
HANDLES["+ResponseHandleTable"]
RUNTIME -->|"register(response)"| HANDLES
HANDLES -.->|"responseId"| RUNTIME
RUNTIME -->|"resolve(responseId)"| HANDLES
HANDLES -->|"stored Response → body()"| LIVE
subgraph UNDERSTUDY["Understudy"]
UPAGE["Page<br/>+subscribeResponse()"]
NETWORK["NetworkManager<br/>+subscribeResponse()"]
LIVE["Response<br/>body() · finished() · loadBody()"]
CDP["CdpConnection / CDPSession"]
UPAGE -->|"subscribeResponse(listener)"| NETWORK
NETWORK -->|"new Response()"| LIVE
CDP -->|"Network.responseReceived"| NETWORK
LIVE -->|"Network.getResponseBody"| CDP
end
RUNTIME -->|"subscribeResponse(listener)"| UPAGE
end
subgraph BROWSER["Chrome browser targets"]
TARGETS["Page / child frames"]
end
RPC -->|"JSON-RPC over CDP"| SW
CDP <-->|"CDP"| TARGETS
classDef edited fill:#dcfce7,stroke:#16a34a,color:#14532d,stroke-width:2px;
classDef existing fill:#f4f4f5,stroke:#a1a1aa,color:#27272a;
class PAGE,RUNTIME,HANDLES,UPAGE,NETWORK edited;
class SDKRESP,RPC,LIVE,CDP,TARGETS existing;