Allow users to type while waiting for MCP servers (#8021)

This commit is contained in:
Tommaso Sciortino
2025-09-08 16:37:36 -07:00
committed by GitHub
parent f0bbfe5f0a
commit 2b05cf3bb4
10 changed files with 122 additions and 95 deletions

View File

@@ -23,6 +23,7 @@ import { useConfig } from '../contexts/ConfigContext.js';
import { useSettings } from '../contexts/SettingsContext.js';
import { ApprovalMode } from '@google/gemini-cli-core';
import { StreamingState } from '../types.js';
import { ConfigInitDisplay } from '../components/ConfigInitDisplay.js';
const MAX_DISPLAYED_QUEUED_MESSAGES = 3;
@@ -72,6 +73,8 @@ export const Composer = () => {
elapsedTime={uiState.elapsedTime}
/>
{!uiState.isConfigInitialized && <ConfigInitDisplay />}
{uiState.messageQueue.length > 0 && (
<Box flexDirection="column" marginTop={1}>
{uiState.messageQueue

View File

@@ -0,0 +1,46 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { useEffect, useState } from 'react';
import { appEvents } from './../../utils/events.js';
import { Box, Text } from 'ink';
import { useConfig } from '../contexts/ConfigContext.js';
import { type McpClient, MCPServerStatus } from '@google/gemini-cli-core';
import { GeminiSpinner } from './GeminiRespondingSpinner.js';
export const ConfigInitDisplay = () => {
const config = useConfig();
const [message, setMessage] = useState('Initializing...');
useEffect(() => {
const onChange = (clients?: Map<string, McpClient>) => {
if (!clients || clients.size === 0) {
setMessage(`Initializing...`);
return;
}
let connected = 0;
for (const client of clients.values()) {
if (client.getStatus() === MCPServerStatus.CONNECTED) {
connected++;
}
}
setMessage(`Connecting to MCP servers... (${connected}/${clients.size})`);
};
appEvents.on('mcp-client-update', onChange);
return () => {
appEvents.off('mcp-client-update', onChange);
};
}, [config]);
return (
<Box marginTop={1}>
<Text>
<GeminiSpinner /> {message}
</Text>
</Box>
);
};

View File

@@ -30,10 +30,11 @@ export const GeminiRespondingSpinner: React.FC<
const streamingState = useStreamingContext();
const isScreenReaderEnabled = useIsScreenReaderEnabled();
if (streamingState === StreamingState.Responding) {
return isScreenReaderEnabled ? (
<Text>{SCREEN_READER_RESPONDING}</Text>
) : (
<Spinner type={spinnerType} />
return (
<GeminiSpinner
spinnerType={spinnerType}
altText={SCREEN_READER_RESPONDING}
/>
);
} else if (nonRespondingDisplay) {
return isScreenReaderEnabled ? (
@@ -44,3 +45,20 @@ export const GeminiRespondingSpinner: React.FC<
}
return null;
};
interface GeminiSpinnerProps {
spinnerType?: SpinnerName;
altText?: string;
}
export const GeminiSpinner: React.FC<GeminiSpinnerProps> = ({
spinnerType = 'dots',
altText,
}) => {
const isScreenReaderEnabled = useIsScreenReaderEnabled();
return isScreenReaderEnabled ? (
<Text>{altText}</Text>
) : (
<Spinner type={spinnerType} />
);
};