/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import React from 'react'; import { Box, type DOMElement } from 'ink'; import { ShellInputPrompt } from '../ShellInputPrompt.js'; import { StickyHeader } from '../StickyHeader.js'; import { useUIActions } from '../../contexts/UIActionsContext.js'; import { useMouseClick } from '../../hooks/useMouseClick.js'; import { ToolResultDisplay } from './ToolResultDisplay.js'; import { ToolStatusIndicator, ToolInfo, TrailingIndicator, STATUS_INDICATOR_WIDTH, isThisShellFocusable as checkIsShellFocusable, isThisShellFocused as checkIsShellFocused, useFocusHint, FocusHint, } from './ToolShared.js'; import type { ToolMessageProps } from './ToolMessage.js'; import type { Config } from '@google/gemini-cli-core'; export interface ShellToolMessageProps extends ToolMessageProps { activeShellPtyId?: number | null; embeddedShellFocused?: boolean; config?: Config; } export const ShellToolMessage: React.FC = ({ name, description, resultDisplay, status, availableTerminalHeight, terminalWidth, emphasis = 'medium', renderOutputAsMarkdown = true, activeShellPtyId, embeddedShellFocused, ptyId, config, isFirst, borderColor, borderDimColor, }) => { const isThisShellFocused = checkIsShellFocused( name, status, ptyId, activeShellPtyId, embeddedShellFocused, ); const { setEmbeddedShellFocused } = useUIActions(); const headerRef = React.useRef(null); const contentRef = React.useRef(null); // The shell is focusable if it's the shell command, it's executing, and the interactive shell is enabled. const isThisShellFocusable = checkIsShellFocusable(name, status, config); const handleFocus = () => { if (isThisShellFocusable) { setEmbeddedShellFocused(true); } }; useMouseClick(headerRef, handleFocus, { isActive: !!isThisShellFocusable }); useMouseClick(contentRef, handleFocus, { isActive: !!isThisShellFocusable }); const wasFocusedRef = React.useRef(false); React.useEffect(() => { if (isThisShellFocused) { wasFocusedRef.current = true; } else if (wasFocusedRef.current) { if (embeddedShellFocused) { setEmbeddedShellFocused(false); } wasFocusedRef.current = false; } }, [isThisShellFocused, embeddedShellFocused, setEmbeddedShellFocused]); const { shouldShowFocusHint } = useFocusHint( isThisShellFocusable, isThisShellFocused, resultDisplay, ); return ( <> {emphasis === 'high' && } {isThisShellFocused && config && ( )} ); };