import type { DipclawConfig } from "../config/types.js";
/**
 * Build the environment for the spawned Chrome.
 *
 * Timezone is forced here via the `TZ` env var rather than a CDP
 * `Emulation.setTimezoneOverride`: V8/ICU honor `TZ` in every renderer, so
 * `Date.prototype.getTimezoneOffset`, the `Date` string methods, and
 * `Intl…resolvedOptions().timeZone` ALL agree — engine-level and undetectable.
 * The CDP route is also a non-starter under extension-relay: Playwright's
 * `newCDPSession` trips `Target.attachToBrowserTarget`, which the relay can't
 * forward through `chrome.debugger`.
 */
export declare function buildChromeSpawnEnv(config: DipclawConfig): NodeJS.ProcessEnv;
/**
 * Live handle for a spawned Chrome process.
 *
 * Why a handle and not loose helpers: the spawn registers a `process.once("exit")`
 * cleanup that must be deregistered exactly once — either when Chrome dies on
 * its own or when we deliberately close it. Bundling spawn + exit-handler +
 * graceful kill in one object means callers can't accidentally leak either.
 */
export interface ChromeProcessHandle {
    readonly pid: number | undefined;
    /** CDP WebSocket endpoint, ready for `chromium.connectOverCDP(endpoint)`. */
    readonly cdpEndpoint: string;
    /** Absolute path to the Chrome binary that was spawned. */
    readonly chromePath: string;
    /** Absolute path to the unpacked Chrome extension loaded for this profile. */
    readonly extensionPath: string | null;
    /** CDP debugging port. Null in extension-relay mode. */
    readonly port: number | null;
    /**
     * Subscribe to Chrome exiting (clean or unclean). The listener fires
     * exactly once per spawn. Use this for "Chrome died" cleanup on the
     * caller side (Playwright handle, watchdog state, etc.).
     */
    onExit(listener: () => void): void;
    /**
     * Graceful close: SIGTERM, then SIGKILL after 5s if Chrome hangs.
     * Resolves once the process has actually exited. Safe to call after
     * the process has already exited (resolves immediately).
     */
    close(): Promise<void>;
}
export interface ChromeSpawnOptions {
    userDataDir: string;
    config: DipclawConfig;
    relay?: {
        extensionWebSocketUrl: string;
        token: string;
        protocolVersion: number;
    };
    /**
     * Invoked synchronously as soon as Chrome is spawned with the assigned
     * pid. Use this to record the pid for orphan detection BEFORE awaiting
     * CDP — if Node crashes or the CDP wait times out during the startup
     * window, the next launch needs a pid file on disk to clean up the
     * Chrome we just started.
     */
    onPid?: (pid: number) => void;
}
/**
 * Locate Chrome, pick a free debugging port, spawn it with our flags, and
 * wait until the CDP endpoint is reachable. Throws if Chrome can't be
 * found or the CDP port doesn't come up in time.
 *
 * The handle is constructed (and its process.once("exit") cleanup is
 * registered) IMMEDIATELY after spawn — before awaiting CDP — so a Node
 * crash during the startup window still sends SIGTERM to Chrome on the
 * way out. On CDP timeout we call `handle.close()` (which awaits the
 * actual process exit) instead of a fire-and-forget SIGKILL, so the
 * caller's workspace lock release doesn't race a still-exiting profile.
 */
export declare function spawnChrome(opts: ChromeSpawnOptions): Promise<ChromeProcessHandle>;
export declare function buildChromeArgsForTest(userDataDir: string, port: number | null, config: DipclawConfig, extensionPath: string | null): string[];
export declare function prepareBundledChromeExtensionForLaunch(userDataDir: string, config: DipclawConfig, relay?: {
    extensionWebSocketUrl: string;
    token: string;
    protocolVersion: number;
}): string | null;
