/** * @license * Copyright 2026 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import type React from 'react'; import { Box, Text } from 'ink'; import { theme } from '../semantic-colors.js'; import { shortenPath, tildeifyPath, getDisplayString, } from '@google/gemini-cli-core'; import { ConsoleSummaryDisplay } from './ConsoleSummaryDisplay.js'; import process from 'node:process'; import { ThemedGradient } from './ThemedGradient.js'; import { MemoryUsageDisplay } from './MemoryUsageDisplay.js'; import { ContextUsageDisplay } from './ContextUsageDisplay.js'; import { QuotaDisplay } from './QuotaDisplay.js'; import { DebugProfiler } from './DebugProfiler.js'; import { isDevelopment } from '../../utils/installationInfo.js'; import { useUIState } from '../contexts/UIStateContext.js'; import { useConfig } from '../contexts/ConfigContext.js'; import { useSettings } from '../contexts/SettingsContext.js'; import { useVimMode } from '../contexts/VimModeContext.js'; export const Footer: React.FC = () => { const uiState = useUIState(); const config = useConfig(); const settings = useSettings(); const { vimEnabled, vimMode } = useVimMode(); const { model, targetDir, debugMode, branchName, debugMessage, corgiMode, errorCount, showErrorDetails, promptTokenCount, nightly, isTrustedFolder, terminalWidth, quotaStats, } = { model: uiState.currentModel, targetDir: config.getTargetDir(), debugMode: config.getDebugMode(), branchName: uiState.branchName, debugMessage: uiState.debugMessage, corgiMode: uiState.corgiMode, errorCount: uiState.errorCount, showErrorDetails: uiState.showErrorDetails, promptTokenCount: uiState.sessionStats.lastPromptTokenCount, nightly: uiState.nightly, isTrustedFolder: uiState.isTrustedFolder, terminalWidth: uiState.terminalWidth, quotaStats: uiState.quota.stats, }; const showMemoryUsage = config.getDebugMode() || settings.merged.ui.showMemoryUsage; const hideCWD = settings.merged.ui.footer.hideCWD; const hideSandboxStatus = settings.merged.ui.footer.hideSandboxStatus; const hideModelInfo = settings.merged.ui.footer.hideModelInfo; const hideContextPercentage = settings.merged.ui.footer.hideContextPercentage; const pathLength = Math.max(20, Math.floor(terminalWidth * 0.25)); const displayPath = shortenPath(tildeifyPath(targetDir), pathLength); const justifyContent = hideCWD && hideModelInfo ? 'center' : 'space-between'; const displayVimMode = vimEnabled ? vimMode : undefined; const showDebugProfiler = debugMode || isDevelopment; return ( {(showDebugProfiler || displayVimMode || !hideCWD) && ( {showDebugProfiler && } {displayVimMode && ( [{displayVimMode}] )} {!hideCWD && (nightly ? ( {displayPath} {branchName && ({branchName}*)} ) : ( {displayPath} {branchName && ( ({branchName}*) )} ))} {debugMode && ( {' ' + (debugMessage || '--debug')} )} )} {/* Middle Section: Centered Trust/Sandbox Info */} {!hideSandboxStatus && ( {isTrustedFolder === false ? ( untrusted ) : process.env['SANDBOX'] && process.env['SANDBOX'] !== 'sandbox-exec' ? ( {process.env['SANDBOX'].replace(/^gemini-(?:cli-)?/, '')} ) : process.env['SANDBOX'] === 'sandbox-exec' ? ( macOS Seatbelt{' '} ({process.env['SEATBELT_PROFILE']}) ) : ( no sandbox {terminalWidth >= 100 && ( (see /docs) )} )} )} {/* Right Section: Gemini Label and Console Summary */} {!hideModelInfo && ( {getDisplayString(model)} /model {!hideContextPercentage && ( <> {' '} )} {quotaStats && ( <> {' '} )} {showMemoryUsage && } {corgiMode && ( | `) )} {!showErrorDetails && errorCount > 0 && ( | )} )} ); };