From 75ecb4a81fa76aa00374601b2c0bbe9d657b4aa7 Mon Sep 17 00:00:00 2001 From: Evan Senter Date: Sat, 19 Apr 2025 14:31:59 +0100 Subject: Adding in a history buffer (#38) Up and down arrows traverse the command history. --- packages/cli/src/ui/App.tsx | 49 ++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'packages/cli/src/ui/App.tsx') diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx index 860663ce..5b4890e3 100644 --- a/packages/cli/src/ui/App.tsx +++ b/packages/cli/src/ui/App.tsx @@ -4,11 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useState } from 'react'; +import React, { useState, useMemo } from 'react'; import { Box, Text } from 'ink'; 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'; @@ -16,7 +17,6 @@ import { LoadingIndicator } from './components/LoadingIndicator.js'; import { InputPrompt } from './components/InputPrompt.js'; import { Footer } from './components/Footer.js'; import { StreamingState } from '../core/gemini-stream.js'; -import { PartListUnion } from '@google/genai'; import { ITermDetectionWarning } from './utils/itermDetection.js'; import { useStartupWarnings, @@ -28,7 +28,6 @@ interface AppProps { } export const App = ({ directory }: AppProps) => { - const [query, setQuery] = useState(''); const [history, setHistory] = useState([]); const [startupWarnings, setStartupWarnings] = useState([]); const { streamingState, submitQuery, initError } = @@ -39,22 +38,39 @@ export const App = ({ directory }: AppProps) => { useStartupWarnings(setStartupWarnings); useInitializationErrorEffect(initError, history, setHistory); - const handleInputSubmit = (value: PartListUnion) => { - submitQuery(value) - .then(() => { - setQuery(''); - }) - .catch(() => { - setQuery(''); - }); - }; + const userMessages = useMemo( + () => + history + .filter( + (item): item is HistoryItem & { type: 'user'; text: string } => + item.type === 'user' && + typeof item.text === 'string' && + item.text.trim() !== '', + ) + .map((item) => item.text), + [history], + ); const isWaitingForToolConfirmation = history.some( (item) => item.type === 'tool_group' && item.tools.some((tool) => tool.confirmationDetails !== undefined), ); - const isInputActive = streamingState === StreamingState.Idle && !initError; + const isInputActive = + streamingState === StreamingState.Idle && + !initError && + !isWaitingForToolConfirmation; + + const { + query, + setQuery, + handleSubmit: handleHistorySubmit, + inputKey, + } = useInputHistory({ + userMessages, + onSubmit: submitQuery, + isActive: isInputActive, + }); return ( @@ -111,7 +127,7 @@ export const App = ({ directory }: AppProps) => { )} - + { /> - {!isWaitingForToolConfirmation && isInputActive && ( + {isInputActive && ( )} -- cgit v1.2.3