import type { IncomingMessage, ServerResponse } from 'node:http';
/**
 * The browser bridge (#1237): the one endpoint an extension running in the user's own Claude
 * session posts to, so a question a cloud agent is parked on becomes visible in the dashboard.
 *
 * **Why this route carries its own token, unlike every other one.** The #1051 guard in
 * `startDashboard` only exists on a non-loopback bind, and what protects a loopback daemon is
 * the same-origin check on `/_rpc`: a page on another origin is refused outright. This
 * route is the first that is *meant* to be reached from another origin, so neither of those
 * protects it, and it demands `Authorization: Bearer <daemonToken>` unconditionally instead.
 *
 * **No CORS headers, on purpose.** An extension's service worker holding `host_permissions`
 * fetches without a preflight, so the bridge does not need `Access-Control-Allow-Origin` and
 * must not have it: a wildcard here would let any page the user visits post to their daemon.
 * The cost is that the extension has to post from its background worker rather than from the
 * content script, which is a line in the extension and a much better trade.
 *
 * **What it accepts is deliberately tiny.** One shape, fully validated, with no path, command,
 * prompt or free text anywhere in it. The worst a stolen token buys is a bogus question card in
 * someone's dashboard, which is the point: this is attached to a daemon that spawns processes.
 */
export declare const BRIDGE_PREFIX = "/_bridge";
/**
 * The extension version this daemon speaks (#1519). The extension states its own version on
 * every call, in this header, and a daemon expecting another refuses outright: a version-skewed
 * extension does not fail loudly, it half-works — missed messages, silently ignored fields —
 * which reads as a framework bug and burns a debugging session. The extension's manifest must
 * carry the same number; a test keeps the two in lockstep.
 */
export declare const EXPECTED_EXTENSION_VERSION = "0.8.1";
/** The header the extension states its version in. Lowercase, as node presents all headers. */
export declare const EXTENSION_VERSION_HEADER = "x-tf-extension-version";
/** A question a cloud session is parked on, as reported by the bridge. */
export interface BridgeQuestion {
    /** The cloud session that asked, which joins back to an agent through `AgentMeta.sessionId`. */
    sessionId: string;
    title: string;
    options: {
        label: string;
        detail?: string;
    }[];
    recommended?: string;
    /** When the daemon accepted it. Set here, never by the caller. */
    receivedAt: string;
}
/**
 * One thing a cloud session did, as scraped from its page (#1237).
 *
 * `seq` is the message's position in the transcript, assigned by the extension, and it is what
 * makes this idempotent: the page is re-read on every DOM change, so the same message arrives
 * many times and the daemon keeps one copy per position rather than a growing pile of repeats.
 */
export interface BridgeEvent {
    sessionId: string;
    seq: number;
    role: 'agent' | 'user';
    text: string;
    receivedAt: string;
}
/** What the page half of the bridge reports about itself, for diagnosis. */
export interface BridgeHello {
    version: string;
    sessionId?: string | undefined;
    note: string;
    at: string;
}
/** A cloud session the extension should be watching. */
export interface BridgeSession {
    id: string;
    url: string;
}
/** What the daemon wires behind the bridge. Absent when the feature is off, which 404s it. */
export interface BridgeHandlers {
    /** The shared secret every bridge call must present. */
    token: string;
    /**
     * The extension version to insist on (#1519). When set, every route past the token demands a
     * matching {@link EXTENSION_VERSION_HEADER} and answers 426 otherwise — no degraded mode,
     * ping included, so the only path forward from a stale extension is updating it.
     */
    expectedExtensionVersion?: string;
    /** What version the caller claimed and whether it was turned away, for the dashboard. */
    extensionVersion?: (got: string, blocked: boolean) => void;
    record: (question: BridgeQuestion) => void;
    /** Record what the session said, keyed by its position in the transcript. */
    recordEvent?: (event: BridgeEvent) => void;
    /** Note that something reached the bridge, including when it was refused. */
    contact?: (route: string, status: number) => void;
    /** What the injected page script reports about itself. */
    hello?: (hello: BridgeHello) => void;
    /**
     * The cloud sessions worth watching, newest first. The extension cannot know an agent started:
     * it only sees pages the user is already on, so without this the bridge works only when
     * somebody happens to be looking at claude.ai. This is how a tab gets opened for them.
     */
    sessions?: () => Promise<BridgeSession[]>;
    /** The answer queued in the dashboard for that session, waiting to be delivered (#1237). */
    answer?: (sessionId: string) => {
        id: string;
        label: string;
    } | undefined;
    /** The extension's word on what a delivery attempt did. */
    answered?: (sessionId: string, id: string, ok: boolean, note?: string) => void;
    now?: () => Date;
}
/** Route a `/_bridge/*` request. A daemon with the bridge off 404s every route. */
export declare function handleBridgeRequest(req: IncomingMessage, res: ServerResponse, pathname: string, handlers: BridgeHandlers | undefined): Promise<void>;
//# sourceMappingURL=bridge-endpoints.d.ts.map