2025-06-07 22:04:57 -07:00
/ * *
* @license
* Copyright 2025 Google LLC
* SPDX - License - Identifier : Apache - 2.0
* /
2025-07-09 10:18:15 -04:00
import {
isProQuotaExceededError ,
isGenericQuotaExceededError ,
isApiError ,
isStructuredError ,
2025-08-13 17:57:11 +00:00
} from './quotaErrorDetection.js' ;
import {
DEFAULT_GEMINI_MODEL ,
DEFAULT_GEMINI_FLASH_MODEL ,
} from '../config/models.js' ;
import { UserTierId } from '../code_assist/types.js' ;
import { AuthType } from '../core/contentGenerator.js' ;
2025-06-23 17:30:13 -04:00
2025-07-09 10:18:15 -04:00
// Free Tier message functions
const getRateLimitErrorMessageGoogleFree = (
fallbackModel : string = DEFAULT_GEMINI_FLASH_MODEL ,
) = >
2025-07-09 13:55:56 -04:00
` \ nPossible quota limitations in place or slow response times detected. Switching to the ${ fallbackModel } model for the rest of this session. ` ;
2025-07-09 10:18:15 -04:00
const getRateLimitErrorMessageGoogleProQuotaFree = (
currentModel : string = DEFAULT_GEMINI_MODEL ,
fallbackModel : string = DEFAULT_GEMINI_FLASH_MODEL ,
) = >
` \ nYou have reached your daily ${ currentModel } quota limit. You will be switched to the ${ fallbackModel } model for the rest of this session. To increase your limits, upgrade to a Gemini Code Assist Standard or Enterprise plan with higher limits at https://goo.gle/set-up-gemini-code-assist, or use /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey ` ;
const getRateLimitErrorMessageGoogleGenericQuotaFree = ( ) = >
` \ nYou have reached your daily quota limit. To increase your limits, upgrade to a Gemini Code Assist Standard or Enterprise plan with higher limits at https://goo.gle/set-up-gemini-code-assist, or use /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey ` ;
// Legacy/Standard Tier message functions
const getRateLimitErrorMessageGooglePaid = (
fallbackModel : string = DEFAULT_GEMINI_FLASH_MODEL ,
) = >
2025-07-09 13:55:56 -04:00
` \ nPossible quota limitations in place or slow response times detected. Switching to the ${ fallbackModel } model for the rest of this session. We appreciate you for choosing Gemini Code Assist and the Gemini CLI. ` ;
2025-07-09 10:18:15 -04:00
const getRateLimitErrorMessageGoogleProQuotaPaid = (
currentModel : string = DEFAULT_GEMINI_MODEL ,
fallbackModel : string = DEFAULT_GEMINI_FLASH_MODEL ,
) = >
` \ nYou have reached your daily ${ currentModel } quota limit. You will be switched to the ${ fallbackModel } model for the rest of this session. We appreciate you for choosing Gemini Code Assist and the Gemini CLI. To continue accessing the ${ currentModel } model today, consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey ` ;
const getRateLimitErrorMessageGoogleGenericQuotaPaid = (
currentModel : string = DEFAULT_GEMINI_MODEL ,
) = >
` \ nYou have reached your daily quota limit. We appreciate you for choosing Gemini Code Assist and the Gemini CLI. To continue accessing the ${ currentModel } model today, consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey ` ;
2025-06-23 23:43:00 -04:00
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' ;
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' ;
2025-07-09 10:18:15 -04:00
const getRateLimitErrorMessageDefault = (
fallbackModel : string = DEFAULT_GEMINI_FLASH_MODEL ,
) = >
2025-07-09 13:55:56 -04:00
` \ nPossible quota limitations in place or slow response times detected. Switching to the ${ fallbackModel } model for the rest of this session. ` ;
2025-06-23 17:30:13 -04:00
2025-07-09 10:18:15 -04:00
function getRateLimitMessage (
authType? : AuthType ,
error? : unknown ,
userTier? : UserTierId ,
currentModel? : string ,
fallbackModel? : string ,
) : string {
2025-06-23 23:43:00 -04:00
switch ( authType ) {
2025-07-09 10:18:15 -04:00
case AuthType . LOGIN_WITH_GOOGLE : {
// Determine if user is on a paid tier (Legacy or Standard) - default to FREE if not specified
const isPaidTier =
userTier === UserTierId . LEGACY || userTier === UserTierId . STANDARD ;
if ( isProQuotaExceededError ( error ) ) {
return isPaidTier
? getRateLimitErrorMessageGoogleProQuotaPaid (
currentModel || DEFAULT_GEMINI_MODEL ,
fallbackModel ,
)
: getRateLimitErrorMessageGoogleProQuotaFree (
currentModel || DEFAULT_GEMINI_MODEL ,
fallbackModel ,
) ;
} else if ( isGenericQuotaExceededError ( error ) ) {
return isPaidTier
? getRateLimitErrorMessageGoogleGenericQuotaPaid (
currentModel || DEFAULT_GEMINI_MODEL ,
)
: getRateLimitErrorMessageGoogleGenericQuotaFree ( ) ;
} else {
return isPaidTier
? getRateLimitErrorMessageGooglePaid ( fallbackModel )
: getRateLimitErrorMessageGoogleFree ( fallbackModel ) ;
}
}
2025-06-23 23:43:00 -04:00
case AuthType . USE_GEMINI :
return RATE_LIMIT_ERROR_MESSAGE_USE_GEMINI ;
case AuthType . USE_VERTEX_AI :
return RATE_LIMIT_ERROR_MESSAGE_VERTEX ;
default :
2025-07-09 10:18:15 -04:00
return getRateLimitErrorMessageDefault ( fallbackModel ) ;
2025-06-23 23:43:00 -04:00
}
}
export function parseAndFormatApiError (
error : unknown ,
authType? : AuthType ,
2025-07-09 10:18:15 -04:00
userTier? : UserTierId ,
currentModel? : string ,
fallbackModel? : string ,
2025-06-23 23:43:00 -04:00
) : string {
2025-06-23 17:30:13 -04:00
if ( isStructuredError ( error ) ) {
let text = ` [API Error: ${ error . message } ] ` ;
if ( error . status === 429 ) {
2025-07-09 10:18:15 -04:00
text += getRateLimitMessage (
authType ,
error ,
userTier ,
currentModel ,
fallbackModel ,
) ;
2025-06-23 17:30:13 -04:00
}
return text ;
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
// The error message might be a string containing a JSON object.
if ( typeof error === 'string' ) {
const jsonStart = error . indexOf ( '{' ) ;
if ( jsonStart === - 1 ) {
return ` [API Error: ${ error } ] ` ; // Not a JSON error, return as is.
}
const jsonString = error . substring ( jsonStart ) ;
try {
const parsedError = JSON . parse ( jsonString ) as unknown ;
if ( isApiError ( parsedError ) ) {
let finalMessage = parsedError . error . message ;
try {
// See if the message is a stringified JSON with another error
const nestedError = JSON . parse ( finalMessage ) as unknown ;
if ( isApiError ( nestedError ) ) {
finalMessage = nestedError . error . message ;
}
} catch ( _e ) {
// It's not a nested JSON error, so we just use the message as is.
}
let text = ` [API Error: ${ finalMessage } (Status: ${ parsedError . error . status } )] ` ;
if ( parsedError . error . code === 429 ) {
2025-07-09 10:18:15 -04:00
text += getRateLimitMessage (
authType ,
parsedError ,
userTier ,
currentModel ,
fallbackModel ,
) ;
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
return text ;
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
} catch ( _e ) {
// Not a valid JSON, fall through and return the original message.
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
return ` [API Error: ${ error } ] ` ;
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
return '[API Error: An unknown error occurred.]' ;
2025-06-07 22:04:57 -07:00
}