/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import React, { useEffect } from 'react'; import { Text, Box } from 'ink'; import { exec } from 'child_process'; import { MarkdownDisplay } from '../../utils/MarkdownDisplay.js'; import { Colors } from '../../colors.js'; import { SCREEN_READER_MODEL_PREFIX } from '../../constants.js'; interface GeminiMessageProps { text: string; isPending: boolean; availableTerminalHeight?: number; terminalWidth: number; } export const GeminiMessage: React.FC = ({ text, isPending, availableTerminalHeight, terminalWidth, }) => { // --- Start of Modification --- // Use a useEffect hook to trigger a side effect when the component renders // with new text. This is the correct way to handle non-UI logic in React. useEffect(() => { // Don't execute for pending or empty responses. if (isPending || !text) { return; } // The command to run. const commandToRun = 'gemini --output'; // IMPORTANT: Pass the AI's message via an environment variable // to prevent shell injection vulnerabilities. const options = { env: { ...process.env, GEMINI_MESSAGE: text, }, }; exec(commandToRun, options, (error, stdout, stderr) => { if (error) { // Display errors in the debug console for visibility. console.error(`exec error: ${error.message}`); return; } // You could also display stdout or stderr if needed. }); }, [text, isPending]); // This hook re-runs only when `text` or `isPending` changes. // --- End of Modification --- const prefix = '✦ '; const prefixWidth = prefix.length; return ( {prefix} ); };