Don't accept input until slash commands are loaded (#11162)

This commit is contained in:
Tommaso Sciortino
2025-10-14 18:15:57 -07:00
committed by GitHub
parent a2f3339a0e
commit dabe161a6f
6 changed files with 23 additions and 16 deletions
@@ -39,9 +39,8 @@ export const handleSlashCommand = async (
} }
// Only custom commands are supported for now. // Only custom commands are supported for now.
const loaders = [new FileCommandLoader(config)];
const commandService = await CommandService.create( const commandService = await CommandService.create(
loaders, [new FileCommandLoader(config)],
abortController.signal, abortController.signal,
); );
const commands = commandService.getCommands(); const commands = commandService.getCommands();
+1
View File
@@ -681,6 +681,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
const isInputActive = const isInputActive =
!initError && !initError &&
!isProcessing && !isProcessing &&
!!slashCommands &&
(streamingState === StreamingState.Idle || (streamingState === StreamingState.Idle ||
streamingState === StreamingState.Responding) && streamingState === StreamingState.Responding) &&
!proQuotaRequest; !proQuotaRequest;
+4 -2
View File
@@ -58,7 +58,9 @@ export const Composer = () => {
/> />
)} )}
{!uiState.isConfigInitialized && <ConfigInitDisplay />} {(!uiState.slashCommands || !uiState.isConfigInitialized) && (
<ConfigInitDisplay />
)}
<QueuedMessageDisplay messageQueue={uiState.messageQueue} /> <QueuedMessageDisplay messageQueue={uiState.messageQueue} />
@@ -133,7 +135,7 @@ export const Composer = () => {
userMessages={uiState.userMessages} userMessages={uiState.userMessages}
onClearScreen={uiActions.handleClearScreen} onClearScreen={uiActions.handleClearScreen}
config={config} config={config}
slashCommands={uiState.slashCommands} slashCommands={uiState.slashCommands || []}
commandContext={uiState.commandContext} commandContext={uiState.commandContext}
shellModeActive={uiState.shellModeActive} shellModeActive={uiState.shellModeActive}
setShellModeActive={uiActions.setShellModeActive} setShellModeActive={uiActions.setShellModeActive}
@@ -56,7 +56,7 @@ export interface UIState {
isSettingsDialogOpen: boolean; isSettingsDialogOpen: boolean;
isModelDialogOpen: boolean; isModelDialogOpen: boolean;
isPermissionsDialogOpen: boolean; isPermissionsDialogOpen: boolean;
slashCommands: readonly SlashCommand[]; slashCommands: readonly SlashCommand[] | undefined;
pendingSlashCommandHistoryItems: HistoryItemWithoutId[]; pendingSlashCommandHistoryItems: HistoryItemWithoutId[];
commandContext: CommandContext; commandContext: CommandContext;
shellConfirmationRequest: ShellConfirmationRequest | null; shellConfirmationRequest: ShellConfirmationRequest | null;
@@ -342,6 +342,8 @@ describe('useSlashCommandProcessor', () => {
setMockIsProcessing, setMockIsProcessing,
); );
await waitFor(() => expect(result.current.slashCommands).toBeDefined());
await act(async () => { await act(async () => {
await result.current.handleSlashCommand('/fail'); await result.current.handleSlashCommand('/fail');
}); });
@@ -74,7 +74,9 @@ export const useSlashCommandProcessor = (
isConfigInitialized: boolean, isConfigInitialized: boolean,
) => { ) => {
const session = useSessionStats(); const session = useSessionStats();
const [commands, setCommands] = useState<readonly SlashCommand[]>([]); const [commands, setCommands] = useState<readonly SlashCommand[] | undefined>(
undefined,
);
const [reloadTrigger, setReloadTrigger] = useState(0); const [reloadTrigger, setReloadTrigger] = useState(0);
const reloadCommands = useCallback(() => { const reloadCommands = useCallback(() => {
@@ -257,20 +259,18 @@ export const useSlashCommandProcessor = (
useEffect(() => { useEffect(() => {
const controller = new AbortController(); const controller = new AbortController();
const load = async () => {
const loaders = [ (async () => {
const commandService = await CommandService.create(
[
new McpPromptLoader(config), new McpPromptLoader(config),
new BuiltinCommandLoader(config), new BuiltinCommandLoader(config),
new FileCommandLoader(config), new FileCommandLoader(config),
]; ],
const commandService = await CommandService.create(
loaders,
controller.signal, controller.signal,
); );
setCommands(commandService.getCommands()); setCommands(commandService.getCommands());
}; })();
load();
return () => { return () => {
controller.abort(); controller.abort();
@@ -283,6 +283,9 @@ export const useSlashCommandProcessor = (
oneTimeShellAllowlist?: Set<string>, oneTimeShellAllowlist?: Set<string>,
overwriteConfirmed?: boolean, overwriteConfirmed?: boolean,
): Promise<SlashCommandProcessorResult | false> => { ): Promise<SlashCommandProcessorResult | false> => {
if (!commands) {
return false;
}
if (typeof rawQuery !== 'string') { if (typeof rawQuery !== 'string') {
return false; return false;
} }