mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-01 00:40:42 -07:00
Add new setting to configure maxRetries (#20064)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import type { Mock } from 'vitest';
|
||||
import type { ConfigParameters, SandboxConfig } from './config.js';
|
||||
import { Config, DEFAULT_FILE_FILTERING_OPTIONS } from './config.js';
|
||||
import { DEFAULT_MAX_ATTEMPTS } from '../utils/retry.js';
|
||||
import { ExperimentFlags } from '../code_assist/experiments/flagNames.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
import { ApprovalMode } from '../policy/types.js';
|
||||
@@ -259,6 +260,29 @@ describe('Server Config (config.ts)', () => {
|
||||
usageStatisticsEnabled: false,
|
||||
};
|
||||
|
||||
describe('maxAttempts', () => {
|
||||
it('should default to DEFAULT_MAX_ATTEMPTS', () => {
|
||||
const config = new Config(baseParams);
|
||||
expect(config.getMaxAttempts()).toBe(DEFAULT_MAX_ATTEMPTS);
|
||||
});
|
||||
|
||||
it('should use provided maxAttempts if <= DEFAULT_MAX_ATTEMPTS', () => {
|
||||
const config = new Config({
|
||||
...baseParams,
|
||||
maxAttempts: 5,
|
||||
});
|
||||
expect(config.getMaxAttempts()).toBe(5);
|
||||
});
|
||||
|
||||
it('should cap maxAttempts at DEFAULT_MAX_ATTEMPTS', () => {
|
||||
const config = new Config({
|
||||
...baseParams,
|
||||
maxAttempts: 20,
|
||||
});
|
||||
expect(config.getMaxAttempts()).toBe(DEFAULT_MAX_ATTEMPTS);
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset mocks if necessary
|
||||
vi.clearAllMocks();
|
||||
|
||||
@@ -291,6 +291,7 @@ export interface ExtensionInstallMetadata {
|
||||
allowPreRelease?: boolean;
|
||||
}
|
||||
|
||||
import { DEFAULT_MAX_ATTEMPTS } from '../utils/retry.js';
|
||||
import type { FileFilteringOptions } from './constants.js';
|
||||
import {
|
||||
DEFAULT_FILE_FILTERING_OPTIONS,
|
||||
@@ -476,6 +477,7 @@ export interface ConfigParameters {
|
||||
disableModelRouterForAuth?: AuthType[];
|
||||
continueOnFailedApiCall?: boolean;
|
||||
retryFetchErrors?: boolean;
|
||||
maxAttempts?: number;
|
||||
enableShellOutputEfficiency?: boolean;
|
||||
shellToolInactivityTimeout?: number;
|
||||
fakeResponses?: string;
|
||||
@@ -657,6 +659,7 @@ export class Config {
|
||||
private readonly outputSettings: OutputSettings;
|
||||
private readonly continueOnFailedApiCall: boolean;
|
||||
private readonly retryFetchErrors: boolean;
|
||||
private readonly maxAttempts: number;
|
||||
private readonly enableShellOutputEfficiency: boolean;
|
||||
private readonly shellToolInactivityTimeout: number;
|
||||
readonly fakeResponses?: string;
|
||||
@@ -879,6 +882,10 @@ export class Config {
|
||||
format: params.output?.format ?? OutputFormat.TEXT,
|
||||
};
|
||||
this.retryFetchErrors = params.retryFetchErrors ?? false;
|
||||
this.maxAttempts = Math.min(
|
||||
params.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
|
||||
DEFAULT_MAX_ATTEMPTS,
|
||||
);
|
||||
this.disableYoloMode = params.disableYoloMode ?? false;
|
||||
this.rawOutput = params.rawOutput ?? false;
|
||||
this.acceptRawOutputRisk = params.acceptRawOutputRisk ?? false;
|
||||
@@ -2415,6 +2422,10 @@ export class Config {
|
||||
return this.retryFetchErrors;
|
||||
}
|
||||
|
||||
getMaxAttempts(): number {
|
||||
return this.maxAttempts;
|
||||
}
|
||||
|
||||
getEnableShellOutputEfficiency(): boolean {
|
||||
return this.enableShellOutputEfficiency;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,7 @@ describe('GeminiChat', () => {
|
||||
}),
|
||||
getContentGenerator: vi.fn().mockReturnValue(mockContentGenerator),
|
||||
getRetryFetchErrors: vi.fn().mockReturnValue(false),
|
||||
getMaxAttempts: vi.fn().mockReturnValue(10),
|
||||
getUserTier: vi.fn().mockReturnValue(undefined),
|
||||
modelConfigService: {
|
||||
getResolvedConfig: vi.fn().mockImplementation((modelConfigKey) => {
|
||||
|
||||
@@ -18,11 +18,7 @@ import type {
|
||||
} from '@google/genai';
|
||||
import { toParts } from '../code_assist/converter.js';
|
||||
import { createUserContent, FinishReason } from '@google/genai';
|
||||
import {
|
||||
retryWithBackoff,
|
||||
isRetryableError,
|
||||
DEFAULT_MAX_ATTEMPTS,
|
||||
} from '../utils/retry.js';
|
||||
import { retryWithBackoff, isRetryableError } from '../utils/retry.js';
|
||||
import type { ValidationRequiredError } from '../utils/googleQuotaErrors.js';
|
||||
import type { Config } from '../config/config.js';
|
||||
import {
|
||||
@@ -635,12 +631,12 @@ export class GeminiChat {
|
||||
authType: this.config.getContentGeneratorConfig()?.authType,
|
||||
retryFetchErrors: this.config.getRetryFetchErrors(),
|
||||
signal: abortSignal,
|
||||
maxAttempts: availabilityMaxAttempts,
|
||||
maxAttempts: availabilityMaxAttempts ?? this.config.getMaxAttempts(),
|
||||
getAvailabilityContext,
|
||||
onRetry: (attempt, error, delayMs) => {
|
||||
coreEvents.emitRetryAttempt({
|
||||
attempt,
|
||||
maxAttempts: availabilityMaxAttempts ?? DEFAULT_MAX_ATTEMPTS,
|
||||
maxAttempts: availabilityMaxAttempts ?? this.config.getMaxAttempts(),
|
||||
delayMs,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
model: lastModelToUse,
|
||||
|
||||
@@ -94,6 +94,7 @@ describe('GeminiChat Network Retries', () => {
|
||||
getToolRegistry: vi.fn().mockReturnValue({ getTool: vi.fn() }),
|
||||
getContentGenerator: vi.fn().mockReturnValue(mockContentGenerator),
|
||||
getRetryFetchErrors: vi.fn().mockReturnValue(false), // Default false
|
||||
getMaxAttempts: vi.fn().mockReturnValue(10),
|
||||
modelConfigService: {
|
||||
getResolvedConfig: vi.fn().mockImplementation((modelConfigKey) => ({
|
||||
model: modelConfigKey.model,
|
||||
|
||||
Reference in New Issue
Block a user