diff --git a/packages/cli/src/nonInteractiveCliCommands.ts b/packages/cli/src/nonInteractiveCliCommands.ts index 31b748d786..15b9301ad4 100644 --- a/packages/cli/src/nonInteractiveCliCommands.ts +++ b/packages/cli/src/nonInteractiveCliCommands.ts @@ -39,9 +39,8 @@ export const handleSlashCommand = async ( } // Only custom commands are supported for now. - const loaders = [new FileCommandLoader(config)]; const commandService = await CommandService.create( - loaders, + [new FileCommandLoader(config)], abortController.signal, ); const commands = commandService.getCommands(); diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index bad03fa568..4eab2524f9 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -681,6 +681,7 @@ Logging in with Google... Please restart Gemini CLI to continue. const isInputActive = !initError && !isProcessing && + !!slashCommands && (streamingState === StreamingState.Idle || streamingState === StreamingState.Responding) && !proQuotaRequest; diff --git a/packages/cli/src/ui/components/Composer.tsx b/packages/cli/src/ui/components/Composer.tsx index 1d4e942624..d87737619a 100644 --- a/packages/cli/src/ui/components/Composer.tsx +++ b/packages/cli/src/ui/components/Composer.tsx @@ -58,7 +58,9 @@ export const Composer = () => { /> )} - {!uiState.isConfigInitialized && } + {(!uiState.slashCommands || !uiState.isConfigInitialized) && ( + + )} @@ -133,7 +135,7 @@ export const Composer = () => { userMessages={uiState.userMessages} onClearScreen={uiActions.handleClearScreen} config={config} - slashCommands={uiState.slashCommands} + slashCommands={uiState.slashCommands || []} commandContext={uiState.commandContext} shellModeActive={uiState.shellModeActive} setShellModeActive={uiActions.setShellModeActive} diff --git a/packages/cli/src/ui/contexts/UIStateContext.tsx b/packages/cli/src/ui/contexts/UIStateContext.tsx index b9a8b6f739..fcc86f02e2 100644 --- a/packages/cli/src/ui/contexts/UIStateContext.tsx +++ b/packages/cli/src/ui/contexts/UIStateContext.tsx @@ -56,7 +56,7 @@ export interface UIState { isSettingsDialogOpen: boolean; isModelDialogOpen: boolean; isPermissionsDialogOpen: boolean; - slashCommands: readonly SlashCommand[]; + slashCommands: readonly SlashCommand[] | undefined; pendingSlashCommandHistoryItems: HistoryItemWithoutId[]; commandContext: CommandContext; shellConfirmationRequest: ShellConfirmationRequest | null; diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts index a59258a265..8762583494 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts @@ -342,6 +342,8 @@ describe('useSlashCommandProcessor', () => { setMockIsProcessing, ); + await waitFor(() => expect(result.current.slashCommands).toBeDefined()); + await act(async () => { await result.current.handleSlashCommand('/fail'); }); diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.ts index c6c6ea57b8..c5b5d5db4e 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.ts @@ -74,7 +74,9 @@ export const useSlashCommandProcessor = ( isConfigInitialized: boolean, ) => { const session = useSessionStats(); - const [commands, setCommands] = useState([]); + const [commands, setCommands] = useState( + undefined, + ); const [reloadTrigger, setReloadTrigger] = useState(0); const reloadCommands = useCallback(() => { @@ -257,20 +259,18 @@ export const useSlashCommandProcessor = ( useEffect(() => { const controller = new AbortController(); - const load = async () => { - const loaders = [ - new McpPromptLoader(config), - new BuiltinCommandLoader(config), - new FileCommandLoader(config), - ]; + + (async () => { const commandService = await CommandService.create( - loaders, + [ + new McpPromptLoader(config), + new BuiltinCommandLoader(config), + new FileCommandLoader(config), + ], controller.signal, ); setCommands(commandService.getCommands()); - }; - - load(); + })(); return () => { controller.abort(); @@ -283,6 +283,9 @@ export const useSlashCommandProcessor = ( oneTimeShellAllowlist?: Set, overwriteConfirmed?: boolean, ): Promise => { + if (!commands) { + return false; + } if (typeof rawQuery !== 'string') { return false; }