From 7116ab9c293f6b59ae8490b234dd99c72d5dd72b Mon Sep 17 00:00:00 2001 From: Brandon Keiji Date: Wed, 14 May 2025 00:12:04 +0000 Subject: [PATCH] fix: pass startup warnings to app as prop (#342) --- packages/cli/src/gemini.ts | 3 ++ packages/cli/src/ui/App.tsx | 12 ++++--- packages/cli/src/ui/hooks/useAppEffects.ts | 42 ---------------------- packages/cli/src/utils/startupWarnings.ts | 40 +++++++++++++++++++++ 4 files changed, 50 insertions(+), 47 deletions(-) delete mode 100644 packages/cli/src/ui/hooks/useAppEffects.ts create mode 100644 packages/cli/src/utils/startupWarnings.ts diff --git a/packages/cli/src/gemini.ts b/packages/cli/src/gemini.ts index 1f48a99b..4225e8c3 100644 --- a/packages/cli/src/gemini.ts +++ b/packages/cli/src/gemini.ts @@ -16,6 +16,7 @@ import { dirname } from 'node:path'; import { sandbox_command, start_sandbox } from './utils/sandbox.js'; import { loadSettings } from './config/settings.js'; import { themeManager } from './ui/themes/theme-manager.js'; +import { getStartupWarnings } from './utils/startupWarnings.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -41,6 +42,7 @@ async function main() { } let input = config.getQuestion(); + const startupWarnings = await getStartupWarnings(); // Render UI, passing necessary config values. Check that there is no command line question. if (process.stdin.isTTY && input?.length === 0) { @@ -53,6 +55,7 @@ async function main() { config, settings, cliVersion, + startupWarnings, }), ); return; diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx index 39cbaf47..a838f524 100644 --- a/packages/cli/src/ui/App.tsx +++ b/packages/cli/src/ui/App.tsx @@ -16,7 +16,6 @@ import { LoadingIndicator } from './components/LoadingIndicator.js'; import { EditorState, InputPrompt } from './components/InputPrompt.js'; import { Footer } from './components/Footer.js'; import { ThemeDialog } from './components/ThemeDialog.js'; -import { useStartupWarnings } from './hooks/useAppEffects.js'; import { shortenPath, type Config } from '@gemini-code/server'; import { Colors } from './colors.js'; import { Help } from './components/Help.js'; @@ -33,16 +32,21 @@ interface AppProps { config: Config; settings: LoadedSettings; cliVersion: string; + startupWarnings?: string[]; } -export const App = ({ config, settings, cliVersion }: AppProps) => { +export const App = ({ + config, + settings, + cliVersion, + startupWarnings = [], +}: AppProps) => { const { history, addItem, clearItems } = useHistory(); const [staticKey, setStaticKey] = useState(0); const refreshStatic = useCallback(() => { setStaticKey((prev) => prev + 1); }, [setStaticKey]); - const [startupWarnings, setStartupWarnings] = useState([]); const [debugMessage, setDebugMessage] = useState(''); const [showHelp, setShowHelp] = useState(false); const [themeError, setThemeError] = useState(null); @@ -74,8 +78,6 @@ export const App = ({ config, settings, cliVersion }: AppProps) => { const { elapsedTime, currentLoadingPhrase } = useLoadingIndicator(streamingState); - useStartupWarnings(setStartupWarnings); - const handleFinalSubmit = useCallback( (submittedValue: string) => { const trimmedValue = submittedValue.trim(); diff --git a/packages/cli/src/ui/hooks/useAppEffects.ts b/packages/cli/src/ui/hooks/useAppEffects.ts deleted file mode 100644 index da1ab203..00000000 --- a/packages/cli/src/ui/hooks/useAppEffects.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2025 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useEffect } from 'react'; -import fs from 'fs'; -import path from 'path'; -import os from 'os'; -import { getErrorMessage } from '@gemini-code/server'; - -const warningsFilePath = path.join(os.tmpdir(), 'gemini-code-cli-warnings.txt'); - -// Effect to handle startup warnings -export function useStartupWarnings( - setStartupWarnings: React.Dispatch>, -) { - useEffect(() => { - try { - if (fs.existsSync(warningsFilePath)) { - const warningsContent = fs.readFileSync(warningsFilePath, 'utf-8'); - setStartupWarnings( - warningsContent.split('\n').filter((line) => line.trim() !== ''), - ); - try { - fs.unlinkSync(warningsFilePath); - } catch { - setStartupWarnings((prev) => [ - ...prev, - `Warning: Could not delete temporary warnings file.`, - ]); - } - } - } catch (err: unknown) { - setStartupWarnings((prev) => [ - ...prev, - `Error checking/reading warnings file: ${getErrorMessage(err)}`, - ]); - } - }, [setStartupWarnings]); // Include setStartupWarnings in dependency array -} diff --git a/packages/cli/src/utils/startupWarnings.ts b/packages/cli/src/utils/startupWarnings.ts new file mode 100644 index 00000000..a55003e6 --- /dev/null +++ b/packages/cli/src/utils/startupWarnings.ts @@ -0,0 +1,40 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import fs from 'fs/promises'; +import os from 'os'; +import { join as pathJoin } from 'node:path'; +import { getErrorMessage } from '@gemini-code/server'; + +const warningsFilePath = pathJoin(os.tmpdir(), 'gemini-code-cli-warnings.txt'); + +export async function getStartupWarnings(): Promise { + try { + await fs.access(warningsFilePath); // Check if file exists + const warningsContent = await fs.readFile(warningsFilePath, 'utf-8'); + const warnings = warningsContent + .split('\n') + .filter((line) => line.trim() !== ''); + try { + await fs.unlink(warningsFilePath); + } catch { + warnings.push('Warning: Could not delete temporary warnings file.'); + } + return warnings; + } catch (err: unknown) { + // If fs.access throws, it means the file doesn't exist or is not accessible. + // This is not an error in the context of fetching warnings, so return empty. + // Only return an error message if it's not a "file not found" type error. + // However, the original logic returned an error message for any fs.existsSync failure. + // To maintain closer parity while making it async, we'll check the error code. + // ENOENT is "Error NO ENTry" (file not found). + if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { + return []; // File not found, no warnings to return. + } + // For other errors (permissions, etc.), return the error message. + return [`Error checking/reading warnings file: ${getErrorMessage(err)}`]; + } +}