/** * BrowserDriver — GuiDriver over playwright-core via CDP. * * Connection is lazy. A caller-provided endpoint is strict; otherwise we try the * environment hint, the conventional local endpoint, then the managed Chrome — * adopt-or-launch on a persistent profile (see acquire.ts for the ladder and why each * rung exists). This keeps explicit eval/debug sessions deterministic while making * normal use recover from stale ephemeral ports, frozen leftovers and browser restarts. */ import { GuiDriver } from "../driver.ts"; import { type ActResult, type Snapshot, type Strategy, type TargetInfo, type VerbSpec } from "../types.ts"; export declare class BrowserDriver extends GuiDriver { readonly platform = "browser"; readonly strategies: Strategy[]; private browser; private context; private active; /** Stable per-session tab ids (element refs are re-minted; target ids are not). */ private tabIds; private nextTabId; /** Set only when the managed path acquired the browser: attached browsers have no run * dir, so there is nowhere (and no mandate) to publish action points for them. */ private managedProfileDir; /** Center of the element the last locate() resolved, captured BEFORE the action runs — * the action point for ref-grounded verbs (a navigating click destroys the element). */ private lastPoint; /** One CDP session per page for window-state upkeep (ensureComposited). */ private cdpSessions; /** A fact the NEXT result must carry (e.g. "the browser had been closed, a new one is up"). * Held on the driver rather than thrown, so both actions and observations can deliver it. */ private pendingNote; /** Whether this context already carries the keep-clicks-in-one-tab init script. */ private keepInTabInstalled; /** The profile belongs to the USER (browser takeover) — see {@link isAttachedProfile}. */ private attached; /** CDP windowId of the window the agent opened for itself; null until it has one. * While set, it is the boundary of everything this driver may see or touch. */ private ownWindowId; /** Which window each page lives in — one CDP round trip per page, then cached. */ private windowIds; /** Explicit constructor values and /eval retargets are strict. Environment values * are hints because shell state commonly outlives an ephemeral browser port. */ private explicit; private readonly fallbackCdpUrl; constructor(cdpUrl?: string, fallbackCdpUrl?: string); private cdpUrl; /** Hand over (and clear) the pending fact, so it is delivered exactly once. Read by * `perform` here and by the base class's observation path. */ protected takePendingNote(): string | null; /** Point the driver at a different browser (used by /eval to hand it a prepared * environment). Drops any current connection; the next call reconnects. */ retarget(cdpUrl: string): Promise; /** The driver-neutral form: an eval harness publishes PI_GUI_CDP_URL. */ retargetEnv(params: Record): Promise; private endpoints; private ensure; private page; /** * Open the agent's OWN window and remember it — the whole of attached mode rests on this. * * `Target.createTarget{newWindow}` is the only way to get a separate window without * `context.newPage()`, which activates the application (measured: it steals the keyboard * even when the window is off-screen). The new window is then parked off-screen, exactly * like the managed browser's — but this time only OUR window moves; the user's stay put. */ private openOwnWindow; /** Is this page inside the agent's own window? Always true when not attached. */ private ownsPage; /** * The pages this driver may see and act on: every open page normally, and ONLY the ones in * the agent's own window when attached. Every enumeration goes through here — a stray * `context.pages()` in attached mode is how the agent ends up typing into the user's tab. */ private ownPages; private tabId; extraVerbs(strategy: Strategy): VerbSpec[]; promptFragment(strategy: Strategy): string; protected snapshot(): Promise; readText(): Promise; screenshot(): Promise; /** URL of the active tab — the scoring harness needs where the agent ended up. */ currentUrl(): Promise; listTargets(): Promise; focusTarget(id: string): Promise; perform(kind: string, a: Record): Promise; /** * Un-minimize the managed window before acting. A minimized window stops COMPOSITING: * wheel input hangs its full CDP timeout and the observer's screencast freezes — so a * user who minimizes the revealed window would silently brick the session. Restoring is * two CDP calls (~ms); in offscreen mode the window then goes back to the parking spot, * because minimizing meant "I don't want to see this" and popping it back up would be * worse than the freeze. Managed browsers only — an attached browser is the user's own * window, and moving it is not ours to do. */ private ensureComposited; private dispatch; close(): Promise; private locate; private locateInner; /** Append `{ts, kind, x?, y?, url}` to the run dir's actions.jsonl so an observing host * can composite a pointer onto its live preview. Fire-and-forget by contract: swallow * every error and never await — publication must not fail or slow a turn. */ private publishAction; private missing; }