/** * One question, two places it can be answered, and exactly one answer. * * The terminal and the phone are both live at once. Whichever comes back first * decides, and the other has to be taken down — a dialog left on screen after * the phone answered would ask again, and a Telegram message left with three * live buttons invites a tap that can no longer do anything. * * Kept apart from the agent loop and from the Telegram client because the part * that goes wrong is the ordering, and the ordering can be tested with two * promises and no network. */ export interface RaceParticipant { /** Resolves when this side is answered. Must never reject: a rejection here * would take down a run over a failure to *ask*, which is not the same thing * as a denial and must not be treated as one. */ answer: Promise; /** Take this side down because the other one won. Must be safe to call when * this side never started, and must not itself answer anything. */ withdraw: (winner: string) => void | Promise; } /** * Settle a question from whichever side answers first. * * A side that resolves `null` has declined to decide — it failed to send, or it * was cancelled — and is not treated as a winner. When both come back null, * nobody answered, and the caller decides what that means. It must not mean * approval. */ export declare function raceApproval(terminal: RaceParticipant, remote: RaceParticipant | null, describe: (answer: T) => string): Promise<{ answer: T | null; from: 'terminal' | 'remote' | 'nobody'; }>;