summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/cli/src/ui/App.tsx35
-rw-r--r--packages/cli/src/ui/hooks/atCommandProcessor.ts14
-rw-r--r--packages/cli/src/ui/hooks/shellCommandProcessor.ts6
-rw-r--r--packages/cli/src/ui/hooks/slashCommandProcessor.ts10
-rw-r--r--packages/cli/src/ui/hooks/useGeminiStream.ts26
5 files changed, 42 insertions, 49 deletions
diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx
index a2ed7cdc..39cbaf47 100644
--- a/packages/cli/src/ui/App.tsx
+++ b/packages/cli/src/ui/App.tsx
@@ -10,6 +10,7 @@ import { StreamingState, type HistoryItem } from './types.js';
import { useGeminiStream } from './hooks/useGeminiStream.js';
import { useLoadingIndicator } from './hooks/useLoadingIndicator.js';
import { useThemeCommand } from './hooks/useThemeCommand.js';
+import { useSlashCommandProcessor } from './hooks/slashCommandProcessor.js';
import { Header } from './components/Header.js';
import { LoadingIndicator } from './components/LoadingIndicator.js';
import { EditorState, InputPrompt } from './components/InputPrompt.js';
@@ -36,36 +37,40 @@ interface AppProps {
export const App = ({ config, settings, cliVersion }: AppProps) => {
const { history, addItem, clearItems } = useHistory();
+ const [staticKey, setStaticKey] = useState(0);
+ const refreshStatic = useCallback(() => {
+ setStaticKey((prev) => prev + 1);
+ }, [setStaticKey]);
+
const [startupWarnings, setStartupWarnings] = useState<string[]>([]);
+ const [debugMessage, setDebugMessage] = useState<string>('');
const [showHelp, setShowHelp] = useState<boolean>(false);
const [themeError, setThemeError] = useState<string | null>(null);
+
const {
isThemeDialogOpen,
openThemeDialog,
handleThemeSelect,
handleThemeHighlight,
} = useThemeCommand(settings, setThemeError);
-
- const [staticKey, setStaticKey] = useState(0);
- const refreshStatic = useCallback(() => {
- setStaticKey((prev) => prev + 1);
- }, [setStaticKey]);
-
- const {
- streamingState,
- submitQuery,
- initError,
- debugMessage,
- slashCommands,
- pendingHistoryItem,
- } = useGeminiStream(
+ const { handleSlashCommand, slashCommands } = useSlashCommandProcessor(
addItem,
clearItems,
refreshStatic,
setShowHelp,
- config,
+ setDebugMessage,
openThemeDialog,
);
+
+ const { streamingState, submitQuery, initError, pendingHistoryItem } =
+ useGeminiStream(
+ addItem,
+ refreshStatic,
+ setShowHelp,
+ config,
+ setDebugMessage,
+ handleSlashCommand,
+ );
const { elapsedTime, currentLoadingPhrase } =
useLoadingIndicator(streamingState);
diff --git a/packages/cli/src/ui/hooks/atCommandProcessor.ts b/packages/cli/src/ui/hooks/atCommandProcessor.ts
index a13a7d36..e0cf65c5 100644
--- a/packages/cli/src/ui/hooks/atCommandProcessor.ts
+++ b/packages/cli/src/ui/hooks/atCommandProcessor.ts
@@ -24,7 +24,7 @@ interface HandleAtCommandParams {
query: string;
config: Config;
addItem: UseHistoryManagerReturn['addItem'];
- setDebugMessage: React.Dispatch<React.SetStateAction<string>>;
+ onDebugMessage: (message: string) => void;
messageId: number;
signal: AbortSignal;
}
@@ -89,7 +89,7 @@ export async function handleAtCommand({
query,
config,
addItem,
- setDebugMessage,
+ onDebugMessage,
messageId: userMessageTimestamp,
signal,
}: HandleAtCommandParams): Promise<HandleAtCommandResult> {
@@ -109,7 +109,7 @@ export async function handleAtCommand({
// If the atPath is just "@", pass the original query to the LLM
if (atPath === '@') {
- setDebugMessage('Lone @ detected, passing directly to LLM.');
+ onDebugMessage('Lone @ detected, passing directly to LLM.');
return { processedQuery: [{ text: query }], shouldProceed: true };
}
@@ -144,18 +144,18 @@ export async function handleAtCommand({
const stats = await fs.stat(absolutePath);
if (stats.isDirectory()) {
pathSpec = pathPart.endsWith('/') ? `${pathPart}**` : `${pathPart}/**`;
- setDebugMessage(`Path resolved to directory, using glob: ${pathSpec}`);
+ onDebugMessage(`Path resolved to directory, using glob: ${pathSpec}`);
} else {
- setDebugMessage(`Path resolved to file: ${pathSpec}`);
+ onDebugMessage(`Path resolved to file: ${pathSpec}`);
}
} catch (error) {
// If stat fails (e.g., not found), proceed with original path.
// The tool itself will handle the error during execution.
if (isNodeError(error) && error.code === 'ENOENT') {
- setDebugMessage(`Path not found, proceeding with original: ${pathSpec}`);
+ onDebugMessage(`Path not found, proceeding with original: ${pathSpec}`);
} else {
console.error(`Error stating path ${pathPart}:`, error);
- setDebugMessage(
+ onDebugMessage(
`Error stating path, proceeding with original: ${pathSpec}`,
);
}
diff --git a/packages/cli/src/ui/hooks/shellCommandProcessor.ts b/packages/cli/src/ui/hooks/shellCommandProcessor.ts
index 16106bb0..d0615ce5 100644
--- a/packages/cli/src/ui/hooks/shellCommandProcessor.ts
+++ b/packages/cli/src/ui/hooks/shellCommandProcessor.ts
@@ -19,7 +19,7 @@ import { UseHistoryManagerReturn } from './useHistoryManager.js';
export const useShellCommandProcessor = (
addItemToHistory: UseHistoryManagerReturn['addItem'],
setStreamingState: React.Dispatch<React.SetStateAction<StreamingState>>,
- setDebugMessage: React.Dispatch<React.SetStateAction<string>>,
+ onDebugMessage: (message: string) => void,
config: Config,
) => {
/**
@@ -50,7 +50,7 @@ export const useShellCommandProcessor = (
}
const targetDir = config.getTargetDir();
- setDebugMessage(
+ onDebugMessage(
`Executing shell command in ${targetDir}: ${commandToExecute}`,
);
const execOptions = {
@@ -80,7 +80,7 @@ export const useShellCommandProcessor = (
return true; // Command was initiated
},
- [config, setDebugMessage, addItemToHistory, setStreamingState],
+ [config, onDebugMessage, addItemToHistory, setStreamingState],
);
return { handleShellCommand };
diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.ts
index 0a0a5fc5..aa7323ca 100644
--- a/packages/cli/src/ui/hooks/slashCommandProcessor.ts
+++ b/packages/cli/src/ui/hooks/slashCommandProcessor.ts
@@ -24,7 +24,7 @@ export const useSlashCommandProcessor = (
clearItems: UseHistoryManagerReturn['clearItems'],
refreshStatic: () => void,
setShowHelp: React.Dispatch<React.SetStateAction<boolean>>,
- setDebugMessage: React.Dispatch<React.SetStateAction<string>>,
+ onDebugMessage: (message: string) => void,
openThemeDialog: () => void,
) => {
const slashCommands: SlashCommand[] = useMemo(
@@ -34,7 +34,7 @@ export const useSlashCommandProcessor = (
altName: '?',
description: 'for help on gemini-code',
action: (_value: PartListUnion) => {
- setDebugMessage('Opening help.');
+ onDebugMessage('Opening help.');
setShowHelp(true);
},
},
@@ -42,7 +42,7 @@ export const useSlashCommandProcessor = (
name: 'clear',
description: 'clear the screen',
action: (_value: PartListUnion) => {
- setDebugMessage('Clearing terminal.');
+ onDebugMessage('Clearing terminal.');
clearItems();
refreshStatic();
},
@@ -59,12 +59,12 @@ export const useSlashCommandProcessor = (
altName: 'exit',
description: '',
action: (_value: PartListUnion) => {
- setDebugMessage('Quitting. Good-bye.');
+ onDebugMessage('Quitting. Good-bye.');
process.exit(0);
},
},
],
- [setDebugMessage, setShowHelp, refreshStatic, openThemeDialog, clearItems],
+ [onDebugMessage, setShowHelp, refreshStatic, openThemeDialog, clearItems],
);
/**
diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts
index 4fcc503b..15239bb1 100644
--- a/packages/cli/src/ui/hooks/useGeminiStream.ts
+++ b/packages/cli/src/ui/hooks/useGeminiStream.ts
@@ -28,7 +28,6 @@ import {
HistoryItemWithoutId,
} from '../types.js';
import { isAtCommand } from '../utils/commandUtils.js';
-import { useSlashCommandProcessor } from './slashCommandProcessor.js';
import { useShellCommandProcessor } from './shellCommandProcessor.js';
import { handleAtCommand } from './atCommandProcessor.js';
import { findLastSafeSplitPoint } from '../utils/markdownUtilities.js';
@@ -41,17 +40,16 @@ import { UseHistoryManagerReturn } from './useHistoryManager.js';
*/
export const useGeminiStream = (
addItem: UseHistoryManagerReturn['addItem'],
- clearItems: UseHistoryManagerReturn['clearItems'],
refreshStatic: () => void,
setShowHelp: React.Dispatch<React.SetStateAction<boolean>>,
config: Config,
- openThemeDialog: () => void,
+ onDebugMessage: (message: string) => void,
+ handleSlashCommand: (cmd: PartListUnion) => boolean,
) => {
const toolRegistry = config.getToolRegistry();
const [streamingState, setStreamingState] = useState<StreamingState>(
StreamingState.Idle,
);
- const [debugMessage, setDebugMessage] = useState<string>('');
const [initError, setInitError] = useState<string | null>(null);
const abortControllerRef = useRef<AbortController | null>(null);
const chatSessionRef = useRef<Chat | null>(null);
@@ -59,19 +57,10 @@ export const useGeminiStream = (
const [pendingHistoryItemRef, setPendingHistoryItem] =
useStateAndRef<HistoryItemWithoutId | null>(null);
- const { handleSlashCommand, slashCommands } = useSlashCommandProcessor(
- addItem,
- clearItems,
- refreshStatic,
- setShowHelp,
- setDebugMessage,
- openThemeDialog,
- );
-
const { handleShellCommand } = useShellCommandProcessor(
addItem,
setStreamingState,
- setDebugMessage,
+ onDebugMessage,
config,
);
@@ -109,7 +98,7 @@ export const useGeminiStream = (
if (typeof query === 'string') {
const trimmedQuery = query.trim();
- setDebugMessage(`User query: '${trimmedQuery}'`);
+ onDebugMessage(`User query: '${trimmedQuery}'`);
// Handle UI-only commands first
if (handleSlashCommand(trimmedQuery)) return;
@@ -121,7 +110,7 @@ export const useGeminiStream = (
query: trimmedQuery,
config,
addItem,
- setDebugMessage,
+ onDebugMessage,
messageId: userMessageTimestamp,
signal,
});
@@ -138,7 +127,7 @@ export const useGeminiStream = (
}
if (queryToSendToGemini === null) {
- setDebugMessage(
+ onDebugMessage(
'Query processing resulted in null, not sending to Gemini.',
);
return;
@@ -558,6 +547,7 @@ export const useGeminiStream = (
setPendingHistoryItem,
toolRegistry,
refreshStatic,
+ onDebugMessage,
],
);
@@ -565,8 +555,6 @@ export const useGeminiStream = (
streamingState,
submitQuery,
initError,
- debugMessage,
- slashCommands,
// Normally we would be concerned that the ref would not be up-to-date, but
// this isn't a concern as the ref is updated whenever the corresponding
// state is updated.