diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index 977f04527a..dff16d4df6 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -84,13 +84,16 @@ export type StreamEvent = interface MidStreamRetryOptions { /** Total number of attempts to make (1 initial + N retries). */ maxAttempts: number; - /** The base delay in milliseconds for linear backoff. */ + /** The base delay in milliseconds for backoff. */ initialDelayMs: number; + /** Whether to use exponential backoff instead of linear. */ + useExponentialBackoff: boolean; } const MID_STREAM_RETRY_OPTIONS: MidStreamRetryOptions = { maxAttempts: 4, // 1 initial call + 3 retries mid-stream - initialDelayMs: 500, + initialDelayMs: 1000, + useExponentialBackoff: true, }; export const SYNTHETIC_THOUGHT_SIGNATURE = 'skip_thought_signature_validator'; @@ -433,7 +436,10 @@ export class GeminiChat { attempt < maxAttempts - 1 && attempt < maxMidStreamAttempts - 1 ) { - const delayMs = MID_STREAM_RETRY_OPTIONS.initialDelayMs; + const delayMs = MID_STREAM_RETRY_OPTIONS.useExponentialBackoff + ? MID_STREAM_RETRY_OPTIONS.initialDelayMs * + Math.pow(2, attempt) + : MID_STREAM_RETRY_OPTIONS.initialDelayMs * (attempt + 1); if (isContentError) { logContentRetry( @@ -447,7 +453,7 @@ export class GeminiChat { attempt + 1, maxAttempts, errorType, - delayMs * (attempt + 1), + delayMs, model, ), ); @@ -455,13 +461,11 @@ export class GeminiChat { coreEvents.emitRetryAttempt({ attempt: attempt + 1, maxAttempts: Math.min(maxAttempts, maxMidStreamAttempts), - delayMs: delayMs * (attempt + 1), + delayMs, error: errorType, model, }); - await new Promise((res) => - setTimeout(res, delayMs * (attempt + 1)), - ); + await new Promise((res) => setTimeout(res, delayMs)); continue; } }