import { deriveSlackConnectorSlug, ensureChannel, type ChannelKind, type EvePackageContract } from "#setup/scaffold/index.js"; import { detectPackageManager } from "#setup/package-manager.js"; import { runPackageManagerInstall } from "#setup/primitives/pm/run.js"; import { runVercel } from "#setup/primitives/run-vercel.js"; import { detectDeployment, type ProjectResolution } from "../project-resolution.js"; import { type Asker } from "../ask.js"; import type { Prompter } from "../prompter.js"; import { provisionSlackbot, reconcileSlackUid } from "../slackbot.js"; import { type SetupState } from "../state.js"; import { type SetupBox } from "../step.js"; /** Injected for tests; defaults to the real scaffold, Connect, and Vercel effects. */ export interface AddChannelsDeps { ensureChannel: typeof ensureChannel; deriveSlackConnectorSlug: typeof deriveSlackConnectorSlug; provisionSlackbot: typeof provisionSlackbot; reconcileSlackUid: typeof reconcileSlackUid; detectPackageManager: typeof detectPackageManager; runPackageManagerInstall: typeof runPackageManagerInstall; runVercel: typeof runVercel; detectDeployment: typeof detectDeployment; } export interface AddChannelsOptions { /** Resolves the slackbot question; the composed stack decides how. */ asker: Asker; /** * Logs through `prompter.log` in `perform`, and owns the interactive * `vercel link` fallback. The slackbot question itself now travels the asker, * not this prompter. */ prompter: Prompter; /** * Headless mode: gates the interactive `vercel link` fallback inside `perform` * and refuses Slack up front. Fixed at composition time (the same place the * asker base is chosen), since `gather` cannot read the mode off the asker. */ headless?: boolean; /** * eve package metadata for the scaffolded web `package.json`. When omitted, * every package value comes from the build-stamped defaults. */ evePackage?: EvePackageContract; /** Skip the "Create slackbot?" prompt and use this answer. */ presetCreateSlackbot?: boolean; /** Overwrite existing channel files (`eve channels add --force`). */ force?: boolean; /** * Override for the web scaffold's Vercel services config. Defaults to * `hasVercelProject(state)`; `eve channels add` pins it to true so an * unlinked directory still gets the config, matching the dissolved engine. */ configureVercelServices?: boolean; /** * Opt-in fallback when Slack is chosen interactively but `state.project` is * unresolved: run the interactive bare `vercel link` before provisioning the * slackbot. Only the `eve channels add` composition sets this; onboarding * resolves the project up front via the link box and keeps the hard gate. */ ensureLinkedProject?: "interactive-vercel-link"; /** * What a failed slackbot provision (create or attach) does to the run. The * default, "abort", fails the whole box — right for `eve channels add slack`, * where Slack is the point. Onboarding passes "warn-and-continue": the agent * still scaffolds, deploys, and chats without Slack (recorded as nothing, so * a later `eve channels add slack` starts clean). */ slackbotFailure?: "abort" | "warn-and-continue"; deps?: AddChannelsDeps; } /** * What the user (or the preset) decided before `perform` runs effects. * `createSlackbot` is only consulted when Slack is in the channel selection. */ export interface AddChannelsInput { headless: boolean; createSlackbot: boolean | undefined; } /** Slackbot facts resolved by a successful Connect provision. */ export interface AddChannelsSlackbotFacts { connectorUid: string; /** Deep link that opens a DM compose with the bot ("chat with your agent"). */ chatUrl?: string; workspaceName?: string; } /** * What `perform` actually did. `channelsAdded` lists the channels recorded this * run (web before slack); a skipped Web scaffold (Next.js detected) records * nothing, deliberately. `slackbot` is present only after a fresh, fully * attached provision; every failure mode either throws or (under * `slackbotFailure: "warn-and-continue"`) skips Slack entirely, so a failed * Slack setup records nothing (atomicity). */ export interface AddChannelsPayload { channelsAdded: ChannelKind[]; webScaffolded: boolean; slackScaffolded: boolean; /** * Whether the post-scaffold dependency install succeeded. False both when no * channels were recorded (nothing ran) and when the install failed; only a * success lets `apply` mark the deploy-time install as already done. */ dependenciesInstalled: boolean; project: ProjectResolution; slackbot?: AddChannelsSlackbotFacts; } /** * THE CHANNEL SCAFFOLD BOX. Scaffolds the channels chosen up front by the * select-channels box (`state.channelSelection`): writes the Web Chat files, * provisions the Slackbot through Vercel Connect, writes the Slack channel * definition, reconciles a Connect-assigned connector UID, and installs the * dependencies the scaffold added to `package.json` so a running `eve dev` * can load the new channel modules right away. The only prompt * (the slackbot question) travels the asker in `gather`; `perform` is promptless * and reads `state.project` directly, resolved earlier by the link box or the * in-project seed. */ export declare function addChannels(options: AddChannelsOptions): SetupBox;