/**
 * What a Discord message should do (#680). Pure: it takes the text plus a snapshot of the
 * project's state and returns an action, so every routing rule is unit-testable without a
 * gateway, a daemon, or a run. The side effects live in `bot.ts`.
 */
/** One option of a parked choice gate, as the run emitted it. */
export interface GateOption {
    id: string;
    label: string;
}
/** A gate a run is parked on, waiting for an answer. */
export interface Gate {
    id: string;
    title: string;
    options: GateOption[];
    /** A multi-select gate takes a list of picks rather than one. */
    multi?: boolean;
}
/** The live run of a project, if it has one. */
export interface RunSnapshot {
    projectId: string;
    runId: string;
    /** Present when the run is parked on a choice gate. */
    gate?: Gate;
}
/** Where a message goes when no run is live. */
export interface ProjectTarget {
    id: string;
    name: string;
}
/** The state a routing decision is made against. */
export interface RouteContext {
    /** The project's live run, if any. */
    live?: RunSnapshot | undefined;
    /** The project a new run would start in. */
    target: ProjectTarget;
}
/** What the bot should do about a message. */
export type BotAction = {
    kind: 'choice';
    projectId: string;
    runId: string;
    gateId: string;
    pick: string | string[];
    reply: string;
} | {
    kind: 'message';
    projectId: string;
    runId: string;
    text: string;
    reply: string;
} | {
    kind: 'start';
    projectId: string;
    text: string;
    reply: string;
} | {
    kind: 'stop';
    projectId: string;
    runId: string;
    reply: string;
}
/** Nothing to do but say something (help, status, an unusable message). */
 | {
    kind: 'reply';
    reply: string;
};
/** The help text, also sent when a message cannot be understood as an answer to a gate. */
export declare const HELP: string;
/** Render a parked gate as a numbered question, so it can be answered by number in chat. */
export declare function renderGate(gate: Gate): string;
/**
 * Resolve an answer to a gate. Accepts option numbers (`2`, or `1,3` for a multi-select) and an
 * exact option label or id, case-insensitively. `undefined` when the text is not an answer —
 * the caller then treats it as an ordinary message rather than guessing, because picking the
 * wrong option on someone's behalf is worse than asking again.
 */
export declare function resolvePick(gate: Gate, text: string): string | string[] | undefined;
/** Decide what a message means. See the module comment. */
export declare function decideAction(text: string, ctx: RouteContext): BotAction;
//# sourceMappingURL=routing.d.ts.map