import { type ChannelKind } from "#setup/scaffold/index.js";
import type { DisabledChannelReasons } from "#setup/cli/index.js";
import type { Asker } from "../ask.js";
import { type SetupState } from "../state.js";
import type { SetupBox } from "../step.js";
export interface SelectChannelsOptions {
    /** Resolves the channels question; the composed stack decides how. */
    asker: Asker;
    /**
     * Resolve to these channels without asking. Stays a factory option (not a
     * `withAnswers` rung) so it keeps short-circuiting the picker exactly as the
     * dual-face box did, while still passing the Slack/Vercel gate and
     * `validateSelection` like a picked selection.
     */
    presetChannels?: ChannelKind[];
    /**
     * Picker shape, chosen explicitly by every composition because the variants
     * differ in how Slack is gated. The "onboarding" picker requires a selection
     * and carries the locked CLI REPL row; Slack stays selectable because the
     * deployment decision comes later in the interview — the provisioning box
     * reads the selection and resolves to Vercel when Slack needs it. The
     * "in-project" picker (`eve setup` inside an existing project) is the same
     * shape but gates Slack on the detected on-disk project link, the only
     * deployment fact that composition has. The "channels-add" picker drops the
     * REPL row, allows an empty submission (the command's "No channels added."
     * path), and keeps Slack selectable from an unlinked directory, because that
     * composition's add-channels box runs an interactive `vercel link` on demand.
     */
    variant: "onboarding" | "in-project" | "channels-add";
    /**
     * Reasons for channel kinds that cannot be added to this project (existing
     * registrations); matching rows render disabled with the reason.
     */
    disabledChannelReasons?: DisabledChannelReasons;
    /**
     * Rejects a selection before any later box runs effects. Runs on both the
     * asked and the preset path, so a flag-driven selection is validated exactly
     * like a picked one. A throw aborts the run.
     */
    validateSelection?(channels: readonly ChannelKind[]): Promise<void> | void;
}
/**
 * THE CHANNELS BOX: interview-phase channel picker. Choosing channels is human
 * input, so it runs before any filesystem work; the channels box scaffolds the
 * chosen channels afterward from `state.channelSelection`. During onboarding
 * the deployment decision has not been made yet, so Slack is never gated here:
 * picking it is what makes the later provisioning box resolve to Vercel. Only
 * the in-project variant gates Slack, on the detected on-disk link.
 *
 * The onboarding picker is required and always carries a locked, pre-selected
 * CLI REPL row, so an empty selection is impossible: every agent can at least be
 * chatted with locally in the terminal. Web and Slack stack on top of it.
 */
export declare function selectChannels(options: SelectChannelsOptions): SetupBox<SetupState, ChannelKind[], ChannelKind[]>;
