/** Which target to attribute when the endpoint lists several pages. */ export type ChromeCdpPagePreference = "pinned" | "active"; export interface ChromeCdpProbeArgs { /** Launch-time CDP port, if the launch capture caught it. */ cdpPort?: number; /** The launched profile dir; the probe re-reads DevToolsActivePort at observe time. */ profileDir?: string; /** The URL this lane opened; attributes the page when no target id is pinned yet. */ targetUrl: string; /** The pinned page target id from the launch-time geometry capture. */ targetId?: string; /** * "pinned" (default): the launch-time target, for launch geometry and emulation attribution. * "active": the tab the participant is driving NOW — Chrome's /json lists page * targets most-recently-focused first. The state observer must follow the participant: a * verification link that opens in a NEW tab left a pinned observer reading the old tab forever, * so the observed URL never changed again and stopWhen/task criteria went blind (a live run's * funnel read reach-dashboard 0/2 under a screenshot OF the dashboard). Final geometry follows * this target too: a closed launch tab is unavailable, and a background tab may report stale * layout dimensions or zero outer bounds after navigation. */ prefer?: ChromeCdpPagePreference; /** * "state": url/title/text/scrollY. "geometry": outer window + CSS viewport. "port": resolution * only. "emulate": apply mobile emulation (#221) to the selected page and exit (the overrides that * are session-scoped, UA / touch / DPR, lapse when the socket closes). "hold": the same over a browser-level * socket, then stay attached until killed (how a lane keeps them for its whole life) and attach * to every page target Chrome opens later, sending it the same overrides and a reload the moment * it exists, never pausing it (#623). "fidelity": read * back what the page reports about itself (UA, DPR, viewport, touch), the proof for the bundle. */ mode: "state" | "geometry" | "port" | "emulate" | "hold" | "fidelity"; /** For "emulate": what to apply. */ emulation?: ChromeMobileEmulationRequest; } /** Mobile emulation request (#221): the CDP Emulation domain applied to one page target. */ export interface ChromeMobileEmulationRequest { width: number; height: number; deviceScaleFactor: number; touch: boolean; userAgent: string; platform?: string; } /** What the page reports after emulation: the proof, never copied from the request. */ export interface ChromeFidelityRead { userAgent: string; devicePixelRatio: number; innerWidth: number; innerHeight: number; maxTouchPoints: number; coarsePointer: boolean; } /** The probe's stdout, before the caller narrows it. */ export interface ChromeCdpProbeResult { unavailable?: string; cdpPort?: number; url?: string; title?: string; text?: string; scrollY?: number; targetId?: string; browserWindow?: { x: number; y: number; width: number; height: number; }; viewport?: { width: number; height: number; deviceScaleFactor: number; }; /** "emulate": the CDP methods that returned without error, in order. */ applied?: string[]; /** "fidelity": the read-back. */ fidelity?: ChromeFidelityRead; } /** * The probe itself. Kept as one string so the shipped command is exactly what the tests execute * (tests/chrome-cdp-probe.test.ts runs it under the real python3 against a real headless Chrome). * * WebSocket is hand-rolled because python's stdlib has no client: one masked text frame out, frames * in until the reply with id 1 arrives, 1.5 s budget, and NO Origin header (Chrome refuses * cross-origin DevTools sockets unless --remote-allow-origins is set; a header-less client is a * local one). urllib is opened WITHOUT proxy handlers so a sandbox-wide http_proxy cannot redirect * a loopback read. */ export declare const CHROME_CDP_PROBE_PY: string; /** The exact shell command a sandbox runs for one probe. */ export declare function chromeCdpProbeCommand(args: ChromeCdpProbeArgs): string; /** * Narrow one probe's stdout. A parse failure is reported as unavailable with the reason, never as * an empty success: the difference between "nothing to observe" and "could not observe" is the * whole point of #514. */ export declare function parseChromeCdpProbeOutput(stdout: string | undefined): ChromeCdpProbeResult;