import { type IncomingMessage, type ServerResponse } from 'node:http';
/**
 * The dashboard's route to an agent's browser preview (#813).
 *
 * The bridge itself lives in the agent (#802) on a port the OS picks per agent. The dashboard is a
 * different origin, on the daemon's port, so it cannot post to that bridge directly: a JSON POST
 * would need a CORS preflight, and answering it would mean letting browser origins reach the
 * bridge — giving up exactly the containment #802 paid for by keeping Chrome's debug port
 * unreachable from the web.
 *
 * So the daemon proxies. The pane talks same-origin to the daemon, the daemon talks to loopback,
 * and the agent's port is never named by the client: it comes from the agent's own meta. A caller
 * cannot point this at an arbitrary port, which is what keeps it from being an open relay into
 * anything else listening on loopback.
 */
/** Where a proxied request is headed, once the URL has been understood. */
export interface BrowserRoute {
    projectId: string;
    agentId: string;
    /** `stream` renders in an `<img>`; `input` carries a click or a key back. */
    leg: 'stream' | 'input';
}
/** The prefix the dashboard client posts to. */
export declare const BROWSER_PROXY_PREFIX = "/browser";
/**
 * Parse `/browser/<projectId>/<agentId>/stream|input`, or undefined for anything else — an
 * unrecognized shape must fall through to the bundle rather than be guessed at. Ids are taken
 * verbatim and only ever used to look an agent up, never as a path.
 */
export declare function parseBrowserRoute(url: string | undefined): BrowserRoute | undefined;
/** How the proxy finds the agent's bridge. Injectable so a test needs no registry and no run. */
export type BrowserPortLookup = (projectId: string, agentId: string) => Promise<number | undefined>;
/**
 * Proxy one request to the agent's bridge. Returns false when the URL is not a browser route, so
 * the dashboard server can carry on to the client bundle.
 *
 * Streams both ways rather than buffering: `/stream` is an endless `multipart/x-mixed-replace`
 * body, so anything that waits for it to finish never answers.
 */
export declare function handleBrowserProxy(req: IncomingMessage, res: ServerResponse, lookup?: BrowserPortLookup): Promise<boolean>;
//# sourceMappingURL=browser-proxy.d.ts.map