/**
 * Prompt Gate — InputDetector
 *
 * Monitors terminal output from Claude Code sessions to detect interactive
 * prompts (permission requests, clarifying questions, plan approvals).
 * Phase 1: detection and logging only. No auto-approve, no relay.
 *
 * Hooks into SessionManager.monitorTick() via a dedicated capture loop,
 * NOT WebSocketManager (which only runs when dashboard clients connect).
 */
import { EventEmitter } from 'node:events';
export type PromptType = 'permission' | 'question' | 'plan' | 'selection' | 'confirmation';
export interface DetectedPrompt {
    type: PromptType;
    raw: string;
    summary: string;
    options?: PromptOption[];
    sessionName: string;
    detectedAt: number;
    id: string;
    /**
     * Optional deterministic response directive for system prompts whose safe
     * answer is known from the framework UI itself (e.g. Claude Code's optional
     * survey, Gemini CLI's loop-detection modal).
     * When set, the consumer should send `autoDismissKey` to the session and
     * SKIP the relay/classify pipeline entirely.
     */
    autoDismissKey?: string;
    /**
     * Safety disposition for deterministic auto-dismisses. `safe-default`
     * answers a framework-owned non-risky prompt with its known default.
     * `safe-reject` explicitly refuses an execution prompt; it must never
     * approve code execution and must be logged by the consumer.
     */
    autoDismissDisposition?: 'safe-default' | 'safe-reject';
    /** Command text rejected by an execution-approval safe-reject prompt. */
    autoDismissCommand?: string;
}
export interface PromptOption {
    key: string;
    label: string;
}
export interface InputDetectorConfig {
    /** Lines from buffer tail to examine (default: 50) */
    detectionWindowLines: number;
    /** Enable/disable detection */
    enabled: boolean;
    /** LLM provider for intelligent prompt detection (falls back to regex-only if not set) */
    intelligence?: import('../core/types.js').IntelligenceProvider;
}
/**
 * Strip ANSI escape sequences and control characters from terminal output.
 * Uses a comprehensive regex covering CSI, OSC, and other escape sequences.
 * Post-strip: remove control chars < 0x20 except \n and \t.
 */
export declare function stripAnsi(text: string): string;
export declare class InputDetector extends EventEmitter {
    private config;
    private lastOutput;
    private lastContentFingerprint;
    private stableCount;
    private emittedPrompts;
    private autoDismissedPrompts;
    /** Post-emission cooldown: session → timestamp of last emission */
    private lastEmissionTime;
    private static readonly COOLDOWN_MS;
    /** Rejected prompt cooling: fingerprint → expiry timestamp */
    private rejectedFingerprints;
    private static readonly REJECTED_COOLING_MS;
    /** Track pending LLM detection calls to prevent overlap */
    private pendingLlmDetection;
    /**
     * NO_PROMPT classification cache: session → bounded set of recent context
     * fingerprints already classified by the LLM as not a blocking prompt.
     *
     * Without this, an idle session showing the same terminal output across every
     * monitor tick re-asks the LLM "is this stuck?" every 5 seconds forever,
     * because the existing rate limit (lastLlmRelay) is only updated on a
     * successful emit. The cache short-circuits that loop: once we've classified
     * a given context as NO_PROMPT, we don't re-classify the identical context.
     * Cache is cleared in onInputSent() and cleanup().
     */
    private noPromptCache;
    private static readonly NO_PROMPT_CACHE_MAX;
    /**
     * Per-session cache generation counter. Incremented whenever the cache is
     * cleared for a session (onInputSent, cleanup). An in-flight llmDetect call
     * captures the generation at start; if it changes before the call's
     * recordNoPrompt write, the write is dropped — we don't want a stale
     * pre-input verdict to repopulate the cache after a clear.
     */
    private cacheGeneration;
    constructor(config: InputDetectorConfig);
    /**
     * Called every monitor tick with captured terminal output.
     * Returns a DetectedPrompt if a new prompt is found, null otherwise.
     */
    onCapture(sessionName: string, rawOutput: string): DetectedPrompt | null;
    /**
     * Emit a detected prompt if it passes dedup/cooldown checks.
     */
    private emitIfNew;
    /**
     * LLM-based prompt detection. Asks Haiku to analyze terminal output
     * and determine if the session is waiting for user input.
     * Fires asynchronously — emits 'prompt' event if detected.
     */
    /** Per-session LLM detection rate limit: max 1 LLM relay per session per 5 minutes */
    private llmRelayTimestamps;
    private static readonly LLM_RELAY_COOLDOWN_MS;
    private llmDetect;
    /**
     * Called when input is sent to a session — clears dedup cache
     * since the prompt has been answered.
     *
     * Also clears the per-session 5-minute LLM relay cooldown so that
     * a follow-up prompt (e.g. the next question in a multi-question form)
     * isn't silently blocked. Rate-limiting on the LLM call is still
     * provided by stableCount + post-emission cooldown.
     */
    onInputSent(sessionName: string): void;
    /**
     * Called after a deterministic auto-dismiss key is successfully sent.
     * Unlike normal prompt dedup, this memory survives onInputSent(): some
     * terminal panes keep the dismissed prompt text visible until new output
     * arrives, and re-clearing normal dedup would otherwise re-fire every tick.
     */
    onAutoDismissSent(prompt: DetectedPrompt): void;
    /**
     * Mark a prompt as rejected (user cancelled). Prevents re-fire for 60s.
     */
    onPromptRejected(sessionName: string, promptRaw: string, type: PromptType): void;
    /**
     * Clean up stale state for a session that has ended.
     */
    cleanup(sessionName: string): void;
    /**
     * Record a NO_PROMPT classification for the given session and context
     * fingerprint, evicting the oldest entry if the per-session cache exceeds
     * NO_PROMPT_CACHE_MAX. FIFO is sufficient — these are pure memoizations of
     * an LLM verdict on a specific terminal-output snapshot.
     *
     * Drops the write if the cache generation has advanced since llmDetect
     * started — that means onInputSent or cleanup fired during the LLM call,
     * and our verdict was computed against output the session has now moved
     * past. Without this guard, the post-input cache could get repopulated
     * with a stale pre-input verdict.
     */
    private recordNoPrompt;
    /**
     * Prune expired entries from rejectedFingerprints.
     */
    pruneRejected(): void;
    private fingerprint;
}
//# sourceMappingURL=PromptGate.d.ts.map