diff options
Diffstat (limited to 'packages/cli/src/ui/App.tsx')
| -rw-r--r-- | packages/cli/src/ui/App.tsx | 96 |
1 files changed, 37 insertions, 59 deletions
diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx index cda748f4..5a88c90b 100644 --- a/packages/cli/src/ui/App.tsx +++ b/packages/cli/src/ui/App.tsx @@ -1,11 +1,12 @@ import React, { useState, useEffect, useMemo } from 'react'; -import { Box, Text, useInput } from 'ink'; +import { Box, Text } from 'ink'; import fs from 'fs'; import path from 'path'; import os from 'os'; import type { HistoryItem } from './types.js'; import { useGeminiStream } from './hooks/useGeminiStream.js'; import { useLoadingIndicator } from './hooks/useLoadingIndicator.js'; +import { useInputHistory } from './hooks/useInputHistory.js'; import Header from './components/Header.js'; import Tips from './components/Tips.js'; import HistoryDisplay from './components/HistoryDisplay.js'; @@ -22,11 +23,8 @@ interface AppProps { } const App = ({ directory }: AppProps) => { - const [query, setQuery] = useState(''); const [history, setHistory] = useState<HistoryItem[]>([]); const [startupWarnings, setStartupWarnings] = useState<string[]>([]); - const [historyIndex, setHistoryIndex] = useState<number>(-1); - const [originalQueryBeforeNav, setOriginalQueryBeforeNav] = useState<string>(''); const { streamingState, submitQuery, initError } = useGeminiStream(setHistory); const { elapsedTime, currentLoadingPhrase } = @@ -34,34 +32,54 @@ const App = ({ directory }: AppProps) => { const userMessages = useMemo(() => { return history - .filter((item): item is HistoryItem & { type: 'user'; text: string } => - item.type === 'user' && typeof item.text === 'string' && item.text.trim() !== '' - ) - .map(item => item.text); + .filter( + (item): item is HistoryItem & { type: 'user'; text: string } => + item.type === 'user' && + typeof item.text === 'string' && + item.text.trim() !== '', + ) + .map((item) => item.text); }, [history]); useEffect(() => { try { if (fs.existsSync(warningsFilePath)) { - console.log('[App] Found warnings file:', warningsFilePath); const warningsContent = fs.readFileSync(warningsFilePath, 'utf-8'); - setStartupWarnings(warningsContent.split('\n').filter(line => line.trim() !== '')); + setStartupWarnings( + warningsContent.split('\n').filter((line) => line.trim() !== ''), + ); try { - fs.unlinkSync(warningsFilePath); + fs.unlinkSync(warningsFilePath); } catch (unlinkErr: any) { - console.warn(`[App] Warning: Could not delete warnings file: ${unlinkErr.message}`); + console.warn( + `[App] Warning: Could not delete warnings file: ${unlinkErr.message}`, + ); } - } else { - console.log('[App] No warnings file found.'); } } catch (err: any) { - console.error(`[App] Error checking/reading warnings file: ${err.message}`); + console.error( + `[App] Error checking/reading warnings file: ${err.message}`, + ); } }, []); + const isWaitingForToolConfirmation = history.some( + (item) => + item.type === 'tool_group' && + item.tools.some((tool) => tool.confirmationDetails !== undefined), + ); + const isInputActive = + streamingState === StreamingState.Idle && + !initError && + !isWaitingForToolConfirmation; + + const { query, setQuery, resetHistoryNav, inputKey } = useInputHistory({ + userMessages, + isActive: isInputActive, + }); + const handleInputSubmit = (value: PartListUnion) => { - setHistoryIndex(-1); - setOriginalQueryBeforeNav(''); + resetHistoryNav(); submitQuery(value) .then(() => { setQuery(''); @@ -89,47 +107,6 @@ const App = ({ directory }: AppProps) => { } }, [initError, history]); - const isWaitingForToolConfirmation = history.some( - (item) => - item.type === 'tool_group' && - item.tools.some((tool) => tool.confirmationDetails !== undefined), - ); - const isInputActive = streamingState === StreamingState.Idle && !initError; - - useInput((input, key) => { - if (!isInputActive || isWaitingForToolConfirmation) { - return; - } - - if (key.upArrow) { - if (userMessages.length === 0) return; - if (historyIndex === -1) { - setOriginalQueryBeforeNav(query); - } - const nextIndex = Math.min(historyIndex + 1, userMessages.length - 1); - if (nextIndex !== historyIndex) { - setHistoryIndex(nextIndex); - setQuery(userMessages[userMessages.length - 1 - nextIndex]); - } - } else if (key.downArrow) { - if (historyIndex < 0) return; - const nextIndex = Math.max(historyIndex - 1, -1); - setHistoryIndex(nextIndex); - if (nextIndex === -1) { - setQuery(originalQueryBeforeNav); - } else { - setQuery(userMessages[userMessages.length - 1 - nextIndex]); - } - } else { - if (input || key.backspace || key.delete || key.leftArrow || key.rightArrow) { - if (historyIndex !== -1) { - setHistoryIndex(-1); - setOriginalQueryBeforeNav(''); - } - } - } - }, { isActive: isInputActive }); - return ( <Box flexDirection="column" padding={1} marginBottom={1} width="100%"> <Header cwd={directory} /> @@ -193,12 +170,13 @@ const App = ({ directory }: AppProps) => { /> </Box> - {!isWaitingForToolConfirmation && isInputActive && ( + {!isWaitingForToolConfirmation && ( <InputPrompt query={query} setQuery={setQuery} onSubmit={handleInputSubmit} isActive={isInputActive} + forceKey={inputKey} /> )} |
