/**
 * CLI Interactive Prompt Detector
 *
 * Claude Code CLI (and likely other Ink-TUI CLI tools) renders interactive
 * select menus through ANSI escape sequences on the PTY. These do NOT show
 * up as stream-json lines, so the ChatOverlay (which only consumes JSON via
 * adapter.parseLineBlocks) is blind to them. The user is then stuck in the
 * terminal panel without knowing it from the chat-only view.
 *
 * This module is a passive PTY-output sniffer that watches for known menu
 * fingerprints (currently only Claude's `--continue` resume menu) and emits
 * `cli_prompt_detected` / `cli_prompt_dismissed` lifecycle events. The
 * ChatOverlay then renders interactive choice buttons whose labels mirror
 * the menu options — the click handler hits a backend API that writes the
 * chosen digit straight to the PTY.
 *
 * Why digits parsed from the menu, not hard-coded 1/2/3:
 *  CLAUDE.md 历史教训 #10 — wrapping external CLIs is bypass, not root-cause.
 *  If Claude CLI ever reorders the menu, hard-coded `1 = Resume summary` would
 *  silently mis-select. Instead we parse "<digit>. <label>" lines out of the
 *  ANSI-stripped buffer and bind buttons to the digit-label pairs we actually
 *  saw. If parsing fails (CLI changed format wholesale), we emit nothing —
 *  the user falls back to the terminal panel, which is the pre-feature state.
 *
 * State machine: per-project ring buffer of recent (ANSI-stripped) PTY output;
 * on every feed() we re-evaluate "any fingerprint visible + options parsable?"
 * and emit only on transitions (debounced — no per-chunk spam).
 */
import { EventEmitter } from 'events';
/** Public event union (mirrors approval-manager style). */
export type CliPromptEvent = {
    type: 'cli_prompt_detected';
    projectId: string;
    kind: CliPromptKind;
    /** Best-effort human label for the menu (en/zh-agnostic). */
    label: string;
    /** Parsed digit-label pairs the user can choose between. */
    options: CliPromptOption[];
    detectedAt: number;
} | {
    type: 'cli_prompt_dismissed';
    projectId: string;
    kind: CliPromptKind;
};
export type CliPromptKind = 'claude_resume_session';
export interface CliPromptOption {
    /** The digit shown next to the option in the menu (typically 1-based). */
    digit: number;
    /** Human label after the digit, e.g. "Resume from summary". */
    label: string;
    /** Highlighted by ❯ or marked "(recommended)" — UI default-focus hint. */
    recommended: boolean;
}
/**
 * Parse menu options out of the ANSI-stripped buffer.
 *
 * Matches lines shaped like:
 *   "  1. Resume from summary (recommended)"
 *   "  ❯ 2. Resume full session as-is"
 *
 * Returns options keyed by parsed digit, latest occurrence wins (Ink redraws
 * the same menu repeatedly as the user navigates with ↑/↓; the *latest* slice
 * of buffer reflects the current state including which option is highlighted).
 */
export declare function parseOptions(buffer: string): CliPromptOption[];
interface ActiveState {
    kind: CliPromptKind;
    label: string;
    detectedAt: number;
    options: CliPromptOption[];
}
declare class CliPromptDetector extends EventEmitter {
    private readonly states;
    /**
     * Feed a chunk of raw PTY output. Synchronous, side-effect: may emit
     * 'cli_prompt_detected' or 'cli_prompt_dismissed' on state transitions.
     */
    feed(projectId: string, raw: string): void;
    /** Drop all state for a project (call on terminal exit / project delete). */
    reset(projectId: string): void;
    /**
     * Snapshot of the currently active prompt for a project, if any. Used by
     * the REST endpoint that lets the frontend re-sync after WS reconnect /
     * page refresh — without it, a client that misses the transition emit
     * would never know the CLI is still waiting for input.
     */
    getActive(projectId: string): ActiveState | null;
    private matchFingerprint;
}
export declare const cliPromptDetector: CliPromptDetector;
export {};
//# sourceMappingURL=cli-prompt-detector.d.ts.map