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"; /** The channel question, shared with the dev TUI's /channels action list. */ export declare const CHANNELS_PROMPT_MESSAGE = "Where will you chat with your agent?"; 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 because the variants differ in whether a * selection is required, whether the REPL row is shown, and how Slack is * gated. The "channels-add" picker allows an empty submission and keeps Slack * selectable from an unlinked directory because its add-channels box can run * 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; } /** * 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 * Terminal UI 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;