/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import type { Config, GitService, Logger } from '@aetherai/aether-core'; import type { Content, PartListUnion } from '@google/genai'; import type { MutableRefObject, ReactNode } from 'react'; import type { LoadedSettings } from '../../config/settings.js'; import type { SessionStatsState } from '../contexts/SessionContext.js'; import type { UseHistoryManagerReturn } from '../hooks/useHistoryManager.js'; import type { ExtensionUpdateAction, ExtensionUpdateStatus } from '../state/extensions.js'; import type { ConfirmationRequest, HistoryItem, HistoryItemBtw, HistoryItemWithoutId } from '../types.js'; export interface CommandContext { /** * Execution mode for the current invocation. * * - interactive: React/Ink UI mode * - non_interactive: non-interactive CLI mode (text/json) * - acp: ACP/Zed integration mode */ executionMode?: 'interactive' | 'non_interactive' | 'acp'; invocation?: { /** The raw, untrimmed input string from the user. */ raw: string; /** The primary name of the command that was matched. */ name: string; /** The arguments string that follows the command name. */ args: string; }; services: { config: Config | null; settings: LoadedSettings; git: GitService | undefined; logger: Logger | null; }; ui: { /** Adds a new item to the history display. */ addItem: UseHistoryManagerReturn['addItem']; /** Clears all history items and the console screen. */ clear: () => void; /** * Sets the transient debug message displayed in the application footer in debug mode. */ setDebugMessage: (message: string) => void; /** The currently pending history item, if any. */ pendingItem: HistoryItemWithoutId | null; /** * Sets a pending item in the history, which is useful for indicating * that a long-running operation is in progress. * * @param item The history item to display as pending, or `null` to clear. */ setPendingItem: (item: HistoryItemWithoutId | null) => void; /** The current btw side-question item rendered in the fixed bottom area. */ btwItem: HistoryItemBtw | null; /** Sets the btw item independently of the main pendingItem. */ setBtwItem: (item: HistoryItemBtw | null) => void; /** Cancels a pending btw (aborts the in-flight API call and clears the btw area). */ cancelBtw: () => void; /** Ref to the btw AbortController, set by btwCommand so cancelBtw can abort it. */ btwAbortControllerRef: MutableRefObject; /** * Loads a new set of history items, replacing the current history. * * @param history The array of history items to load. */ loadHistory: UseHistoryManagerReturn['loadHistory']; toggleVimEnabled: () => Promise; setGeminiMdFileCount: (count: number) => void; reloadCommands: () => void; extensionsUpdateState: Map; dispatchExtensionStateUpdate: (action: ExtensionUpdateAction) => void; addConfirmUpdateExtensionRequest: (value: ConfirmationRequest) => void; }; session: { stats: SessionStatsState; /** A transient list of shell commands the user has approved for this session. */ sessionShellAllowlist: Set; /** Reset session metrics and prompt counters for a fresh session. */ startNewSession?: (sessionId: string) => void; }; overwriteConfirmed?: boolean; /** Abort signal for cancelling long-running slash command operations via ESC. */ abortSignal?: AbortSignal; } /** * The return type for a command action that results in scheduling a tool call. */ export interface ToolActionReturn { type: 'tool'; toolName: string; toolArgs: Record; } /** The return type for a command action that results in the app quitting. */ export interface QuitActionReturn { type: 'quit'; messages: HistoryItem[]; } /** * The return type for a command action that results in a simple message * being displayed to the user. */ export interface MessageActionReturn { type: 'message'; messageType: 'info' | 'error'; content: string; } /** * The return type for a command action that streams multiple messages. * Used for long-running operations that need to send progress updates. */ export interface StreamMessagesActionReturn { type: 'stream_messages'; messages: AsyncGenerator<{ messageType: 'info' | 'error'; content: string; }, void, unknown>; } /** * The return type for a command action that needs to open a dialog. */ export interface OpenDialogActionReturn { type: 'dialog'; dialog: 'help' | 'arena_start' | 'arena_select' | 'arena_stop' | 'arena_status' | 'auth' | 'theme' | 'editor' | 'settings' | 'model' | 'fast-model' | 'subagent_create' | 'subagent_list' | 'trust' | 'permissions' | 'approval-mode' | 'resume' | 'extensions_manage' | 'hooks' | 'mcp'; } /** * The return type for a command action that results in replacing * the entire conversation history. */ export interface LoadHistoryActionReturn { type: 'load_history'; history: HistoryItemWithoutId[]; clientHistory: Content[]; } /** * The return type for a command action that should immediately submit * content as a prompt to the Gemini model. */ export interface SubmitPromptActionReturn { type: 'submit_prompt'; content: PartListUnion; } /** * The return type for a command action that needs to pause and request * confirmation for a set of shell commands before proceeding. */ export interface ConfirmShellCommandsActionReturn { type: 'confirm_shell_commands'; /** The list of shell commands that require user confirmation. */ commandsToConfirm: string[]; /** The original invocation context to be re-run after confirmation. */ originalInvocation: { raw: string; }; } export interface ConfirmActionReturn { type: 'confirm_action'; /** The React node to display as the confirmation prompt. */ prompt: ReactNode; /** The original invocation context to be re-run after confirmation. */ originalInvocation: { raw: string; }; } export type SlashCommandActionReturn = ToolActionReturn | MessageActionReturn | StreamMessagesActionReturn | QuitActionReturn | OpenDialogActionReturn | LoadHistoryActionReturn | SubmitPromptActionReturn | ConfirmShellCommandsActionReturn | ConfirmActionReturn; export declare enum CommandKind { BUILT_IN = "built-in", FILE = "file", MCP_PROMPT = "mcp-prompt", SKILL = "skill" } export interface CommandCompletionItem { value: string; label?: string; description?: string; } export interface SlashCommand { name: string; altNames?: string[]; description: string; hidden?: boolean; kind: CommandKind; extensionName?: string; action?: (context: CommandContext, args: string) => undefined | SlashCommandActionReturn | Promise; completion?: (context: CommandContext, partialArg: string) => Promise | null>; subCommands?: SlashCommand[]; }