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:
Shreya Keshive
2025-11-18 12:01:16 -05:00
committed by GitHub
parent 78075c8a37
commit 86828bb561
79 changed files with 3148 additions and 605 deletions
+24 -9
View File
@@ -11,17 +11,22 @@ import type {
RetryInfo,
} from './googleErrors.js';
import { parseGoogleApiError } from './googleErrors.js';
import { getErrorStatus, ModelNotFoundError } from './httpErrors.js';
/**
* A non-retryable error indicating a hard quota limit has been reached (e.g., daily limit).
*/
export class TerminalQuotaError extends Error {
retryDelayMs?: number;
constructor(
message: string,
override readonly cause: GoogleApiError,
retryDelayMs?: number,
) {
super(message);
this.name = 'TerminalQuotaError';
this.retryDelayMs = retryDelayMs ? retryDelayMs * 1000 : undefined;
}
}
@@ -75,6 +80,14 @@ function parseDurationInSeconds(duration: string): number | null {
*/
export function classifyGoogleError(error: unknown): unknown {
const googleApiError = parseGoogleApiError(error);
const status = googleApiError?.code ?? getErrorStatus(error);
if (status === 404) {
const message =
googleApiError?.message ||
(error instanceof Error ? error.message : 'Model not found');
return new ModelNotFoundError(message, status);
}
if (!googleApiError || googleApiError.code !== 429) {
// Fallback: try to parse the error message for a retry delay
@@ -125,6 +138,14 @@ export function classifyGoogleError(error: unknown): unknown {
}
}
}
let delaySeconds;
if (retryInfo?.retryDelay) {
const parsedDelay = parseDurationInSeconds(retryInfo.retryDelay);
if (parsedDelay) {
delaySeconds = parsedDelay;
}
}
if (errorInfo) {
// New Cloud Code API quota handling
@@ -136,23 +157,17 @@ export function classifyGoogleError(error: unknown): unknown {
];
if (validDomains.includes(errorInfo.domain)) {
if (errorInfo.reason === 'RATE_LIMIT_EXCEEDED') {
let delaySeconds = 10; // Default retry of 10s
if (retryInfo?.retryDelay) {
const parsedDelay = parseDurationInSeconds(retryInfo.retryDelay);
if (parsedDelay) {
delaySeconds = parsedDelay;
}
}
return new RetryableQuotaError(
`${googleApiError.message}`,
googleApiError,
delaySeconds,
delaySeconds ?? 10,
);
}
if (errorInfo.reason === 'QUOTA_EXHAUSTED') {
return new TerminalQuotaError(
`${googleApiError.message}`,
googleApiError,
delaySeconds,
);
}
}
@@ -170,12 +185,12 @@ export function classifyGoogleError(error: unknown): unknown {
// 2. Check for long delays in RetryInfo
if (retryInfo?.retryDelay) {
const delaySeconds = parseDurationInSeconds(retryInfo.retryDelay);
if (delaySeconds) {
if (delaySeconds > 120) {
return new TerminalQuotaError(
`${googleApiError.message}\nSuggested retry after ${retryInfo.retryDelay}.`,
googleApiError,
delaySeconds,
);
}
// This is a retryable error with a specific delay.