/**
 * AskUserBridge — bridges train-lang's host builtin call to the ccweb
 * frontend.
 *
 * Flow:
 *   1. .tr code calls `__ccweb_ask_user({ fields: [...] })`
 *   2. train evaluates this as a builtin → call our bridge.requestInput()
 *   3. bridge pushes a "track_ask_user" event (via onPush callback)
 *      to the WebSocket layer, which broadcasts to the frontend
 *   4. frontend renders a form, user submits → POST /api/.../tracks/input
 *   5. route handler calls bridge.submitInput(runId, requestId, data)
 *   6. bridge resolves the pending Promise → train continues
 *
 * The bridge maintains one pending request per runId. Concurrent
 * ask_user calls within one track would queue (only the most recent
 * pending request is active). For T1 this is fine; multi-prompt would
 * need a queue (T2+).
 *
 * Cancellation: AbortSignal aborts the pending request immediately,
 * rejecting the Promise with a TrainException-shaped error.
 */
export type Value = unknown;
export interface AskUserFieldSpec {
    key: string;
    label: string;
    type: 'text' | 'enum' | 'number' | 'bool';
    variants?: string[];
    placeholder?: string;
    required?: boolean;
}
export interface AskUserRequest {
    runId: string;
    requestId: string;
    fields: AskUserFieldSpec[];
}
export interface AskUserPushEvent extends AskUserRequest {
    kind: 'track_ask_user';
}
export type AskUserPushFn = (event: AskUserPushEvent) => void;
export interface AskUserBridge {
    /** Called from the builtin when train evaluates __ccweb_ask_user(...). */
    requestInput(runId: string, spec: AskUserFieldSpec[], signal?: AbortSignal): Promise<Record<string, Value>>;
    /** Called from the route handler when the user submits the form. */
    submitInput(runId: string, requestId: string, data: Record<string, Value>): {
        ok: boolean;
        message?: string;
    };
    /** Reject all pending requests for a runId (e.g. on track cancel). */
    cancelAllForRun(runId: string, reason?: string): void;
    /** For diagnostics + tests. */
    getPending(runId: string): AskUserRequest | null;
}
export declare function createAskUserBridge(onPush: AskUserPushFn): AskUserBridge;
//# sourceMappingURL=ask-user-bridge.d.ts.map