import * as readline from 'readline';
import { InstallFlow, InstallFlowOptions } from './InstallFlow';
import { InstallStateStore } from './InstallStateStore';
/**
 * Pluggable answer provider. Tests inject `CannedAnswerProvider`; production
 * uses `ReadlineAnswerProvider` (wraps node:readline). No tty assumptions.
 */
export interface AnswerProvider {
    /** Ask the user a multi-choice question; return the chosen index (0-based). */
    choice(question: string, options: string[], defaultIndex?: number): Promise<number>;
    /** Ask a free-form question; return the trimmed string (or '' if user just pressed Enter and no default supplied). */
    text(question: string, defaultValue?: string): Promise<string>;
    /** Ask yes/no. */
    yesNo(question: string, defaultYes?: boolean): Promise<boolean>;
}
/**
 * Production answer provider — uses node:readline. Renders the question and
 * available defaults (bracketed) so the operator can press Enter to accept.
 */
export declare class ReadlineAnswerProvider implements AnswerProvider {
    private rl;
    private ownsInterface;
    constructor(rl?: readline.Interface);
    close(): void;
    private ask;
    choice(question: string, options: string[], defaultIndex?: number): Promise<number>;
    text(question: string, defaultValue?: string): Promise<string>;
    yesNo(question: string, defaultYes?: boolean): Promise<boolean>;
}
/**
 * Test seam — feeds canned answers from a FIFO queue. Each call shifts one off.
 * When the queue is exhausted, throws WIZARD_TEST_OUT_OF_ANSWERS so tests can't
 * silently fall through to a default and mask bugs.
 */
export declare class CannedAnswerProvider implements AnswerProvider {
    private queue;
    constructor(answers: Array<number | string | boolean>);
    private next;
    choice(_question: string, _options: string[], _defaultIndex?: number): Promise<number>;
    text(_question: string, _defaultValue?: string): Promise<string>;
    yesNo(_question: string, _defaultYes?: boolean): Promise<boolean>;
    remaining(): number;
}
export type WizardResult = {
    ok: true;
    options: InstallFlowOptions;
    preExistingAction?: 'reinstall' | 'repair';
    warnings?: string[];
} | {
    ok: false;
    reason: 'user_aborted' | 'invalid_input';
    detail?: string;
};
/**
 * Interactive install wizard. Walks the operator through profile, host,
 * model order, Telegram bits (autonomous only), doctor toggle, and a final
 * confirm preview. Returns a WizardResult that the caller passes into
 * `new InstallFlow().run(options)`.
 *
 * Re-entry safe: if `<root>/.openlife/install-manifest.json` exists, the
 * wizard asks the operator whether to reinstall, repair, or abort BEFORE
 * touching any other question — so an accidental rerun doesn't clobber
 * a working install silently.
 */
export declare class InstallWizard {
    private root;
    private answers;
    constructor(root?: string, answers?: AnswerProvider);
    run(): Promise<WizardResult>;
}
export interface HeadlessInstallWizardOptions {
    mode?: string;
    resume?: boolean;
    host?: string;
    skipDoctor?: boolean;
    modelOrder?: string[];
    telegramToken?: string;
    telegramChatId?: string;
    defaultAgentName?: string;
    additionalAgentName?: string;
}
export declare class HeadlessInstallWizard {
    private root;
    private flow;
    private state;
    constructor(root?: string, flow?: InstallFlow, state?: InstallStateStore);
    run(options: HeadlessInstallWizardOptions): string[];
    private resolveMode;
}
