/** Where a "show the human this" call actually landed. */
export type ShowOutcome = {
    via: 'profile';
    profile: string;
    tabId?: string;
} | {
    via: 'os';
    command: string;
} | {
    via: 'none';
    reason: string;
};
export interface ShowOptions {
    /**
     * Force the OS default handler, ignoring `browser.viewer`. This is the
     * The programmatic escape hatch, for a caller that must use the user's own
     * browser regardless of configuration. There is deliberately no CLI flag for
     * it: `agents config set browser.viewer os` is the user-facing control.
     */
    osBrowser?: boolean;
    /** Explicit profile override, ahead of `browser.viewer`. */
    profile?: string;
    /** Injected opener so the OS branch is testable without spawning anything. */
    spawnOpen?: (cmd: string, args: string[]) => boolean;
}
/**
 * Launch a detached opener and report whether it actually started.
 *
 * Detection without blocking, which is the whole trick here. A bare detached
 * `spawn` cannot tell success from "xdg-open is not installed" — it does not
 * throw for a missing binary, it emits `error` asynchronously — so the failure
 * branches of every caller were dead. But `spawnSync` is not the answer either:
 * it waits for the child's whole lifetime, and `devices lease` opens a console
 * and then immediately prompts for a pasted key, so a blocking open would stall
 * that prompt behind the browser.
 *
 * Racing `spawn` against `error` gives both: Node emits `spawn` as soon as the
 * child is successfully created (measured: 1ms, and it does NOT wait for exit),
 * and `error` for ENOENT. We unref on success so the opener outlives us.
 */
export declare function trySpawn(cmd: string, args: string[]): Promise<boolean>;
/**
 * Decide the viewer for this call. Exported for its own test — this is the one
 * place the policy lives.
 *
 * Every fall back to the OS handler prints one stderr line naming why. A silent
 * downgrade here is what made the original bug invisible for so long: the user
 * had configured a profile and had no way to see that it was being ignored.
 */
export declare function resolveViewer(opts?: ShowOptions): Promise<'os' | {
    profile: string;
}>;
/** Show a URL to the human at this machine. Never throws. */
export declare function showUrl(url: string, opts?: ShowOptions): Promise<ShowOutcome>;
/**
 * Show a local file. Browser-renderable kinds go through {@link showUrl}; every
 * other kind goes to the OS default APP, which for a screenshot or a recording
 * is the right viewer.
 */
export declare function showFile(filePath: string, opts?: ShowOptions): Promise<ShowOutcome>;
