mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-28 14:04:41 -07:00
feat: launch Gemini 3 in Gemini CLI 🚀🚀🚀 (in main) (#13287)
Co-authored-by: Adam Weidman <65992621+adamfweidman@users.noreply.github.com> Co-authored-by: Sehoon Shon <sshon@google.com> Co-authored-by: Adib234 <30782825+Adib234@users.noreply.github.com> Co-authored-by: Sandy Tao <sandytao520@icloud.com> Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com> Co-authored-by: Aishanee Shah <aishaneeshah@gmail.com> Co-authored-by: gemini-cli-robot <gemini-cli-robot@google.com> Co-authored-by: Gal Zahavi <38544478+galz10@users.noreply.github.com> Co-authored-by: Jacob Richman <jacob314@gmail.com> Co-authored-by: joshualitt <joshualitt@google.com> Co-authored-by: Jenna Inouye <jinouye@google.com>
This commit is contained in:
@@ -14,14 +14,11 @@ import {
|
||||
} from './googleQuotaErrors.js';
|
||||
import { delay, createAbortError } from './delay.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
import { getErrorStatus, ModelNotFoundError } from './httpErrors.js';
|
||||
|
||||
const FETCH_FAILED_MESSAGE =
|
||||
'exception TypeError: fetch failed sending request';
|
||||
|
||||
export interface HttpError extends Error {
|
||||
status?: number;
|
||||
}
|
||||
|
||||
export interface RetryOptions {
|
||||
maxAttempts: number;
|
||||
initialDelayMs: number;
|
||||
@@ -146,8 +143,12 @@ export async function retryWithBackoff<T>(
|
||||
}
|
||||
|
||||
const classifiedError = classifyGoogleError(error);
|
||||
const errorCode = getErrorStatus(error);
|
||||
|
||||
if (classifiedError instanceof TerminalQuotaError) {
|
||||
if (
|
||||
classifiedError instanceof TerminalQuotaError ||
|
||||
classifiedError instanceof ModelNotFoundError
|
||||
) {
|
||||
if (onPersistent429 && authType === AuthType.LOGIN_WITH_GOOGLE) {
|
||||
try {
|
||||
const fallbackModel = await onPersistent429(
|
||||
@@ -166,7 +167,10 @@ export async function retryWithBackoff<T>(
|
||||
throw classifiedError; // Throw if no fallback or fallback failed.
|
||||
}
|
||||
|
||||
if (classifiedError instanceof RetryableQuotaError) {
|
||||
const is500 =
|
||||
errorCode !== undefined && errorCode >= 500 && errorCode < 600;
|
||||
|
||||
if (classifiedError instanceof RetryableQuotaError || is500) {
|
||||
if (attempt >= maxAttempts) {
|
||||
if (onPersistent429 && authType === AuthType.LOGIN_WITH_GOOGLE) {
|
||||
try {
|
||||
@@ -183,13 +187,28 @@ export async function retryWithBackoff<T>(
|
||||
console.warn('Model fallback failed:', fallbackError);
|
||||
}
|
||||
}
|
||||
throw classifiedError;
|
||||
throw classifiedError instanceof RetryableQuotaError
|
||||
? classifiedError
|
||||
: error;
|
||||
}
|
||||
|
||||
if (classifiedError instanceof RetryableQuotaError) {
|
||||
console.warn(
|
||||
`Attempt ${attempt} failed: ${classifiedError.message}. Retrying after ${classifiedError.retryDelayMs}ms...`,
|
||||
);
|
||||
await delay(classifiedError.retryDelayMs, signal);
|
||||
continue;
|
||||
} else {
|
||||
const errorStatus = getErrorStatus(error);
|
||||
logRetryAttempt(attempt, error, errorStatus);
|
||||
|
||||
// Exponential backoff with jitter for non-quota errors
|
||||
const jitter = currentDelay * 0.3 * (Math.random() * 2 - 1);
|
||||
const delayWithJitter = Math.max(0, currentDelay + jitter);
|
||||
await delay(delayWithJitter, signal);
|
||||
currentDelay = Math.min(maxDelayMs, currentDelay * 2);
|
||||
continue;
|
||||
}
|
||||
console.warn(
|
||||
`Attempt ${attempt} failed: ${classifiedError.message}. Retrying after ${classifiedError.retryDelayMs}ms...`,
|
||||
);
|
||||
await delay(classifiedError.retryDelayMs, signal);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Generic retry logic for other errors
|
||||
@@ -214,33 +233,6 @@ export async function retryWithBackoff<T>(
|
||||
throw new Error('Retry attempts exhausted');
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the HTTP status code from an error object.
|
||||
* @param error The error object.
|
||||
* @returns The HTTP status code, or undefined if not found.
|
||||
*/
|
||||
export function getErrorStatus(error: unknown): number | undefined {
|
||||
if (typeof error === 'object' && error !== null) {
|
||||
if ('status' in error && typeof error.status === 'number') {
|
||||
return error.status;
|
||||
}
|
||||
// Check for error.response.status (common in axios errors)
|
||||
if (
|
||||
'response' in error &&
|
||||
typeof (error as { response?: unknown }).response === 'object' &&
|
||||
(error as { response?: unknown }).response !== null
|
||||
) {
|
||||
const response = (
|
||||
error as { response: { status?: unknown; headers?: unknown } }
|
||||
).response;
|
||||
if ('status' in response && typeof response.status === 'number') {
|
||||
return response.status;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message for a retry attempt when using exponential backoff.
|
||||
* @param attempt The current attempt number.
|
||||
|
||||
Reference in New Issue
Block a user