/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { Box, Text } from 'ink'; import { useMemo } from 'react'; import { LoadingIndicator } from './LoadingIndicator.js'; import { ContextSummaryDisplay } from './ContextSummaryDisplay.js'; import { AutoAcceptIndicator } from './AutoAcceptIndicator.js'; import { ShellModeIndicator } from './ShellModeIndicator.js'; import { DetailedMessagesDisplay } from './DetailedMessagesDisplay.js'; import { InputPrompt, calculatePromptWidths } from './InputPrompt.js'; import { Footer, type FooterProps } from './Footer.js'; import { ShowMoreLines } from './ShowMoreLines.js'; import { OverflowProvider } from '../contexts/OverflowContext.js'; import { theme } from '../semantic-colors.js'; import { isNarrowWidth } from '../utils/isNarrowWidth.js'; import { useUIState } from '../contexts/UIStateContext.js'; import { useUIActions } from '../contexts/UIActionsContext.js'; import { useVimMode } from '../contexts/VimModeContext.js'; import { useConfig } from '../contexts/ConfigContext.js'; import { useSettings } from '../contexts/SettingsContext.js'; import { ApprovalMode } from '@google/gemini-cli-core'; import { StreamingState } from '../types.js'; import { ConfigInitDisplay } from '../components/ConfigInitDisplay.js'; const MAX_DISPLAYED_QUEUED_MESSAGES = 3; export const Composer = () => { const config = useConfig(); const settings = useSettings(); const uiState = useUIState(); const uiActions = useUIActions(); const { vimEnabled, vimMode } = useVimMode(); const terminalWidth = process.stdout.columns; const isNarrow = isNarrowWidth(terminalWidth); const debugConsoleMaxHeight = Math.floor(Math.max(terminalWidth * 0.2, 5)); const { contextFileNames, showAutoAcceptIndicator } = uiState; // Use the container width of InputPrompt for width of DetailedMessagesDisplay const { containerWidth } = useMemo( () => calculatePromptWidths(uiState.terminalWidth), [uiState.terminalWidth], ); // Build footer props from context values const footerProps: Omit = { model: config.getModel(), targetDir: config.getTargetDir(), debugMode: config.getDebugMode(), branchName: uiState.branchName, debugMessage: uiState.debugMessage, corgiMode: uiState.corgiMode, errorCount: uiState.errorCount, showErrorDetails: uiState.showErrorDetails, showMemoryUsage: config.getDebugMode() || settings.merged.ui?.showMemoryUsage || false, promptTokenCount: uiState.sessionStats.lastPromptTokenCount, nightly: uiState.nightly, isTrustedFolder: uiState.isTrustedFolder, hideCWD: settings.merged.ui?.footer?.hideCWD || false, hideSandboxStatus: settings.merged.ui?.footer?.hideSandboxStatus || false, hideModelInfo: settings.merged.ui?.footer?.hideModelInfo || false, }; return ( {!uiState.shellFocused && ( )} {!uiState.isConfigInitialized && } {uiState.messageQueue.length > 0 && ( {uiState.messageQueue .slice(0, MAX_DISPLAYED_QUEUED_MESSAGES) .map((message, index) => { const preview = message.replace(/\s+/g, ' '); return ( {preview} ); })} {uiState.messageQueue.length > MAX_DISPLAYED_QUEUED_MESSAGES && ( ... (+ {uiState.messageQueue.length - MAX_DISPLAYED_QUEUED_MESSAGES}{' '} more) )} )} {process.env['GEMINI_SYSTEM_MD'] && ( |⌐■_■| )} {uiState.ctrlCPressedOnce ? ( Press Ctrl+C again to exit. ) : uiState.ctrlDPressedOnce ? ( Press Ctrl+D again to exit. ) : uiState.showEscapePrompt ? ( Press Esc again to clear. ) : ( !settings.merged.ui?.hideContextSummary && ( ) )} {showAutoAcceptIndicator !== ApprovalMode.DEFAULT && !uiState.shellModeActive && ( )} {uiState.shellModeActive && } {uiState.showErrorDetails && ( )} {uiState.isInputActive && ( )} {!settings.merged.ui?.hideFooter && (