mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-08-02 05:01:04 -07:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c9254fd67a | |||
| a63fa13c31 | |||
| d99625458f | |||
| 02962f522e | |||
| 07c2a11dad | |||
| d7ce06c306 |
@@ -76,7 +76,7 @@ export const DetailedMessagesDisplay: React.FC<
|
|||||||
>
|
>
|
||||||
<Box marginBottom={1}>
|
<Box marginBottom={1}>
|
||||||
<Text bold color={theme.text.primary}>
|
<Text bold color={theme.text.primary}>
|
||||||
Debug Console <Text color={theme.text.secondary}>(F12 to close)</Text>
|
Debug console <Text color={theme.text.secondary}>(F12 to close)</Text>
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box height={maxHeight} width={width - borderAndPadding}>
|
<Box height={maxHeight} width={width - borderAndPadding}>
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ describe('<LoadingIndicator />', () => {
|
|||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display the elapsedTime correctly in human-readable format', async () => {
|
it('should display the elapsedTime correctly in minutes and OMIT seconds for > 1m', async () => {
|
||||||
const props = {
|
const props = {
|
||||||
currentLoadingPhrase: 'Thinking...',
|
currentLoadingPhrase: 'Thinking...',
|
||||||
elapsedTime: 125,
|
elapsedTime: 125,
|
||||||
@@ -130,7 +130,9 @@ describe('<LoadingIndicator />', () => {
|
|||||||
StreamingState.Responding,
|
StreamingState.Responding,
|
||||||
);
|
);
|
||||||
await waitUntilReady();
|
await waitUntilReady();
|
||||||
expect(lastFrame()).toContain('(esc to cancel, 2m 5s)');
|
const output = lastFrame();
|
||||||
|
expect(output).toContain('(esc to cancel, 2m)');
|
||||||
|
expect(output).not.toContain('5s');
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -258,15 +260,13 @@ describe('<LoadingIndicator />', () => {
|
|||||||
const output = lastFrame();
|
const output = lastFrame();
|
||||||
expect(output).toBeDefined();
|
expect(output).toBeDefined();
|
||||||
if (output) {
|
if (output) {
|
||||||
// Should NOT contain "Thinking... " prefix because the subject already starts with "Thinking"
|
expect(output).not.toContain('Gemini is thinking');
|
||||||
expect(output).not.toContain('Thinking... Thinking');
|
|
||||||
expect(output).toContain('Thinking about something...');
|
expect(output).toContain('Thinking about something...');
|
||||||
expect(output).not.toContain('and other stuff.');
|
|
||||||
}
|
}
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should NOT prepend "Thinking... " even if the subject does not start with "Thinking"', async () => {
|
it('should NOT prepend "Thinking... " if a subject is provided', async () => {
|
||||||
const props = {
|
const props = {
|
||||||
thought: {
|
thought: {
|
||||||
subject: 'Planning the response...',
|
subject: 'Planning the response...',
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import { theme } from '../semantic-colors.js';
|
|||||||
import { useStreamingContext } from '../contexts/StreamingContext.js';
|
import { useStreamingContext } from '../contexts/StreamingContext.js';
|
||||||
import { StreamingState } from '../types.js';
|
import { StreamingState } from '../types.js';
|
||||||
import { GeminiRespondingSpinner } from './GeminiRespondingSpinner.js';
|
import { GeminiRespondingSpinner } from './GeminiRespondingSpinner.js';
|
||||||
import { formatDuration } from '../utils/formatters.js';
|
|
||||||
import { useTerminalSize } from '../hooks/useTerminalSize.js';
|
import { useTerminalSize } from '../hooks/useTerminalSize.js';
|
||||||
import { isNarrowWidth } from '../utils/isNarrowWidth.js';
|
import { isNarrowWidth } from '../utils/isNarrowWidth.js';
|
||||||
import { INTERACTIVE_SHELL_WAITING_PHRASE } from '../hooks/usePhraseCycler.js';
|
import { INTERACTIVE_SHELL_WAITING_PHRASE } from '../hooks/usePhraseCycler.js';
|
||||||
@@ -74,7 +73,11 @@ export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({
|
|||||||
const cancelAndTimerContent =
|
const cancelAndTimerContent =
|
||||||
showCancelAndTimer &&
|
showCancelAndTimer &&
|
||||||
streamingState !== StreamingState.WaitingForConfirmation
|
streamingState !== StreamingState.WaitingForConfirmation
|
||||||
? `(esc to cancel, ${elapsedTime < 60 ? `${elapsedTime}s` : formatDuration(elapsedTime * 1000)})`
|
? `(esc to cancel, ${
|
||||||
|
elapsedTime < 60
|
||||||
|
? `${elapsedTime}s`
|
||||||
|
: `${Math.floor(elapsedTime / 60)}m`
|
||||||
|
})`
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const wittyPhraseNode =
|
const wittyPhraseNode =
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
exports[`DetailedMessagesDisplay > renders message counts 1`] = `
|
exports[`DetailedMessagesDisplay > renders message counts 1`] = `
|
||||||
"
|
"
|
||||||
╭──────────────────────────────────────────────────────────────────────────────╮
|
╭──────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Debug Console (F12 to close) │
|
│ Debug console (F12 to close) │
|
||||||
│ │
|
│ │
|
||||||
│ ℹ Repeated message (x5) │
|
│ ℹ Repeated message (x5) │
|
||||||
│ │
|
│ │
|
||||||
@@ -18,7 +18,7 @@ exports[`DetailedMessagesDisplay > renders message counts 1`] = `
|
|||||||
exports[`DetailedMessagesDisplay > renders messages correctly 1`] = `
|
exports[`DetailedMessagesDisplay > renders messages correctly 1`] = `
|
||||||
"
|
"
|
||||||
╭──────────────────────────────────────────────────────────────────────────────╮
|
╭──────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ Debug Console (F12 to close) │
|
│ Debug console (F12 to close) │
|
||||||
│ │
|
│ │
|
||||||
│ ℹ Log message │
|
│ ℹ Log message │
|
||||||
│ ⚠ Warning message │
|
│ ⚠ Warning message │
|
||||||
|
|||||||
@@ -1048,7 +1048,7 @@ describe('useGeminiStream', () => {
|
|||||||
).toBe(false);
|
).toBe(false);
|
||||||
expect(
|
expect(
|
||||||
infoTexts.some((text) =>
|
infoTexts.some((text) =>
|
||||||
text.includes('This request failed. Press F12 for diagnostics'),
|
text.includes('Request failed. Press F12 for diagnostics'),
|
||||||
),
|
),
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
@@ -1108,15 +1108,13 @@ describe('useGeminiStream', () => {
|
|||||||
([item]) => (item as { text?: string }).text ?? '',
|
([item]) => (item as { text?: string }).text ?? '',
|
||||||
);
|
);
|
||||||
const noteIndex = infoTexts.findIndex((text) =>
|
const noteIndex = infoTexts.findIndex((text) =>
|
||||||
text.includes(
|
text.includes('Previous tool attempts failed'),
|
||||||
'Some internal tool attempts failed before this final error',
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
const stopIndex = infoTexts.findIndex((text) =>
|
const stopIndex = infoTexts.findIndex((text) =>
|
||||||
text.includes('Agent execution stopped: Stop reason from hook'),
|
text.includes('Agent execution stopped: Stop reason from hook'),
|
||||||
);
|
);
|
||||||
const failureHintIndex = infoTexts.findIndex((text) =>
|
const failureHintIndex = infoTexts.findIndex((text) =>
|
||||||
text.includes('This request failed. Press F12 for diagnostics'),
|
text.includes('Request failed. Press F12 for diagnostics'),
|
||||||
);
|
);
|
||||||
expect(noteIndex).toBeGreaterThanOrEqual(0);
|
expect(noteIndex).toBeGreaterThanOrEqual(0);
|
||||||
expect(stopIndex).toBeGreaterThanOrEqual(0);
|
expect(stopIndex).toBeGreaterThanOrEqual(0);
|
||||||
|
|||||||
@@ -110,9 +110,9 @@ enum StreamProcessingStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SUPPRESSED_TOOL_ERRORS_NOTE =
|
const SUPPRESSED_TOOL_ERRORS_NOTE =
|
||||||
'Some internal tool attempts failed before this final error. Press F12 for diagnostics, or run /settings and change "Error Verbosity" to full for details.';
|
'Previous tool attempts failed. Press F12 for diagnostics or set ui.errorVerbosity=full for details';
|
||||||
const LOW_VERBOSITY_FAILURE_NOTE =
|
const LOW_VERBOSITY_FAILURE_NOTE =
|
||||||
'This request failed. Press F12 for diagnostics, or run /settings and change "Error Verbosity" to full for full details.';
|
'Request failed. Press F12 for diagnostics or set ui.errorVerbosity=full for details';
|
||||||
|
|
||||||
function getBackgroundedToolInfo(
|
function getBackgroundedToolInfo(
|
||||||
toolCall: TrackedCompletedToolCall | TrackedCancelledToolCall,
|
toolCall: TrackedCompletedToolCall | TrackedCancelledToolCall,
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ describe('useLoadingIndicator', () => {
|
|||||||
retryStatus,
|
retryStatus,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.current.currentLoadingPhrase).toContain('Trying to reach');
|
expect(result.current.currentLoadingPhrase).toContain('Retrying');
|
||||||
expect(result.current.currentLoadingPhrase).toContain('Attempt 3/3');
|
expect(result.current.currentLoadingPhrase).toContain('Attempt 3/3');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -258,7 +258,7 @@ describe('useLoadingIndicator', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(result.current.currentLoadingPhrase).not.toBe(
|
expect(result.current.currentLoadingPhrase).not.toBe(
|
||||||
"This is taking a bit longer, we're still on it.",
|
'System busy. Retrying...',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ describe('useLoadingIndicator', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(result.current.currentLoadingPhrase).toBe(
|
expect(result.current.currentLoadingPhrase).toBe(
|
||||||
"This is taking a bit longer, we're still on it.",
|
'System busy. Retrying...',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -82,9 +82,9 @@ export const useLoadingIndicator = ({
|
|||||||
const retryPhrase = retryStatus
|
const retryPhrase = retryStatus
|
||||||
? errorVerbosity === 'low'
|
? errorVerbosity === 'low'
|
||||||
? retryStatus.attempt >= LOW_VERBOSITY_RETRY_HINT_ATTEMPT_THRESHOLD
|
? retryStatus.attempt >= LOW_VERBOSITY_RETRY_HINT_ATTEMPT_THRESHOLD
|
||||||
? "This is taking a bit longer, we're still on it."
|
? 'System busy. Retrying...'
|
||||||
: null
|
: null
|
||||||
: `Trying to reach ${getDisplayString(retryStatus.model)} (Attempt ${retryStatus.attempt + 1}/${retryStatus.maxAttempts})`
|
: `Retrying ${getDisplayString(retryStatus.model)} (Attempt ${retryStatus.attempt + 1}/${retryStatus.maxAttempts})`
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import { AuthType } from '../core/contentGenerator.js';
|
|||||||
import type { StructuredError } from '../core/turn.js';
|
import type { StructuredError } from '../core/turn.js';
|
||||||
|
|
||||||
describe('parseAndFormatApiError', () => {
|
describe('parseAndFormatApiError', () => {
|
||||||
const vertexMessage = 'request a quota increase through Vertex';
|
const vertexMessage = 'request a quota increase in Vertex';
|
||||||
const geminiMessage = 'request a quota increase through AI Studio';
|
const geminiMessage = 'request a quota increase in AI Studio';
|
||||||
|
|
||||||
it('should format a valid API error JSON', () => {
|
it('should format a valid API error JSON', () => {
|
||||||
const errorMessage =
|
const errorMessage =
|
||||||
@@ -34,7 +34,7 @@ describe('parseAndFormatApiError', () => {
|
|||||||
);
|
);
|
||||||
expect(result).toContain('[API Error: Rate limit exceeded');
|
expect(result).toContain('[API Error: Rate limit exceeded');
|
||||||
expect(result).toContain(
|
expect(result).toContain(
|
||||||
'Possible quota limitations in place or slow response times detected. Switching to the gemini-2.5-flash model',
|
'System busy or quota limit reached. Switching to gemini-2.5-flash for the rest of this session.',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import type { UserTierId } from '../code_assist/types.js';
|
|||||||
import { AuthType } from '../core/contentGenerator.js';
|
import { AuthType } from '../core/contentGenerator.js';
|
||||||
|
|
||||||
const RATE_LIMIT_ERROR_MESSAGE_USE_GEMINI =
|
const RATE_LIMIT_ERROR_MESSAGE_USE_GEMINI =
|
||||||
'\nPlease wait and try again later. To increase your limits, request a quota increase through AI Studio, or switch to another /auth method';
|
'\nRate limit reached. Try again later, request a quota increase in AI Studio, or switch /auth method';
|
||||||
const RATE_LIMIT_ERROR_MESSAGE_VERTEX =
|
const RATE_LIMIT_ERROR_MESSAGE_VERTEX =
|
||||||
'\nPlease wait and try again later. To increase your limits, request a quota increase through Vertex, or switch to another /auth method';
|
'\nRate limit reached. Try again later, request a quota increase in Vertex, or switch /auth method';
|
||||||
const getRateLimitErrorMessageDefault = (
|
const getRateLimitErrorMessageDefault = (
|
||||||
fallbackModel: string = DEFAULT_GEMINI_FLASH_MODEL,
|
fallbackModel: string = DEFAULT_GEMINI_FLASH_MODEL,
|
||||||
) =>
|
) =>
|
||||||
`\nPossible quota limitations in place or slow response times detected. Switching to the ${fallbackModel} model for the rest of this session.`;
|
`\nSystem busy or quota limit reached. Switching to ${fallbackModel} for the rest of this session.`;
|
||||||
|
|
||||||
function getRateLimitMessage(
|
function getRateLimitMessage(
|
||||||
authType?: AuthType,
|
authType?: AuthType,
|
||||||
|
|||||||
Reference in New Issue
Block a user