/** * Business logic (e.g. git-move-code-workflow.ts) depends only on this * interface — never on Ink/React or on the `prompts` package directly — so the * same workflow code runs unchanged under traditional Commander dispatch * (PlainCliInteractionService) and inside the interactive shell * (InkInteractionService). */ export type TChoice = { title: string; value: TValue; description?: string; /** multiSelect only: pre-check this choice (e.g. a currently-enabled region). Ignored by select. */ selected?: boolean; }; export type TNotifyLevel = "info" | "success" | "warn" | "error" | "muted" | "step"; export type TNotification = { level: TNotifyLevel; message: string; /** Present when level is "step": renders as "Step {current}/{total} {message}". */ current?: number; total?: number; }; export type TSelectOptions = { message: string; choices: TChoice[]; allowCustomValue?: boolean; customValueTitle?: (value: string) => string; validateCustomValue?: (value: string) => true | string; }; export type TMultiSelectOptions = { message: string; choices: TChoice[]; hint?: string; }; export type TInputOptions = { message: string; initial?: string; validate?: (value: string) => true | string; /** Mask typed characters (passwords/tokens) — never echo the raw value to the terminal. */ mask?: boolean; }; export type TConfirmOptions = { message: string; initial?: boolean; }; export type TProgressReport = { current?: number; total?: number; label?: string; }; export type TProgressOptions = { label: string; }; export interface IInteractionService { select(options: TSelectOptions): Promise; multiSelect(options: TMultiSelectOptions): Promise; input(options: TInputOptions): Promise; confirm(options: TConfirmOptions): Promise; progress( options: TProgressOptions, task: (report: (update: TProgressReport) => void) => Promise, ): Promise; notify(notification: TNotification): void; } /** Thrown by an IInteractionService implementation when its AbortSignal fires mid-request. */ export class InteractionCancelledError extends Error { constructor(message = "Cancelled") { super(message); this.name = "InteractionCancelledError"; } } /** * Threaded through business-logic call chains (git move-code, cf target * switching, etc.) instead of importing `searchableSelectChoice`/`prompts`/ * `console.log` directly, so the exact same code runs unchanged under * traditional Commander dispatch (PlainCliInteractionService) and inside the * interactive shell (InkInteractionService). */ export type TInteractionContext = { interaction: IInteractionService; signal: AbortSignal; };