mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 14:10:37 -07:00
refactor(core): improve API response error logging when retry (#21784)
This commit is contained in:
@@ -1154,6 +1154,7 @@ describe('GeminiChat', () => {
|
||||
1,
|
||||
);
|
||||
expect(mockLogContentRetry).not.toHaveBeenCalled();
|
||||
expect(mockLogContentRetryFailure).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should yield a RETRY event when an invalid stream is encountered', async () => {
|
||||
|
||||
@@ -344,8 +344,6 @@ export class GeminiChat {
|
||||
this: GeminiChat,
|
||||
): AsyncGenerator<StreamEvent, void, void> {
|
||||
try {
|
||||
let lastError: unknown = new Error('Request failed after all retries.');
|
||||
|
||||
const maxAttempts = INVALID_CONTENT_RETRY_OPTIONS.maxAttempts;
|
||||
|
||||
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||
@@ -374,15 +372,13 @@ export class GeminiChat {
|
||||
yield { type: StreamEventType.CHUNK, value: chunk };
|
||||
}
|
||||
|
||||
lastError = null;
|
||||
break;
|
||||
return;
|
||||
} catch (error) {
|
||||
if (error instanceof AgentExecutionStoppedError) {
|
||||
yield {
|
||||
type: StreamEventType.AGENT_EXECUTION_STOPPED,
|
||||
reason: error.reason,
|
||||
};
|
||||
lastError = null; // Clear error as this is an expected stop
|
||||
return; // Stop the generator
|
||||
}
|
||||
|
||||
@@ -397,7 +393,6 @@ export class GeminiChat {
|
||||
value: error.syntheticResponse,
|
||||
};
|
||||
}
|
||||
lastError = null; // Clear error as this is an expected stop
|
||||
return; // Stop the generator
|
||||
}
|
||||
|
||||
@@ -415,8 +410,9 @@ export class GeminiChat {
|
||||
}
|
||||
// Fall through to retry logic for retryable connection errors
|
||||
}
|
||||
lastError = error;
|
||||
|
||||
const isContentError = error instanceof InvalidStreamError;
|
||||
const errorType = isContentError ? error.type : 'NETWORK_ERROR';
|
||||
|
||||
if (
|
||||
(isContentError && isGemini2Model(model)) ||
|
||||
@@ -425,11 +421,10 @@ export class GeminiChat {
|
||||
// Check if we have more attempts left.
|
||||
if (attempt < maxAttempts - 1) {
|
||||
const delayMs = INVALID_CONTENT_RETRY_OPTIONS.initialDelayMs;
|
||||
const retryType = isContentError ? error.type : 'NETWORK_ERROR';
|
||||
|
||||
logContentRetry(
|
||||
this.config,
|
||||
new ContentRetryEvent(attempt, retryType, delayMs, model),
|
||||
new ContentRetryEvent(attempt, errorType, delayMs, model),
|
||||
);
|
||||
coreEvents.emitRetryAttempt({
|
||||
attempt: attempt + 1,
|
||||
@@ -444,21 +439,19 @@ export class GeminiChat {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastError) {
|
||||
if (
|
||||
lastError instanceof InvalidStreamError &&
|
||||
isGemini2Model(model)
|
||||
) {
|
||||
// If we've aborted, we throw without logging a failure.
|
||||
if (signal.aborted) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
logContentRetryFailure(
|
||||
this.config,
|
||||
new ContentRetryFailureEvent(maxAttempts, lastError.type, model),
|
||||
new ContentRetryFailureEvent(attempt + 1, errorType, model),
|
||||
);
|
||||
|
||||
throw error;
|
||||
}
|
||||
throw lastError;
|
||||
}
|
||||
} finally {
|
||||
streamDoneResolver!();
|
||||
|
||||
@@ -401,6 +401,7 @@ describe('GeminiChat Network Retries', () => {
|
||||
|
||||
// Should only be called once (no retry)
|
||||
expect(mockContentGenerator.generateContentStream).toHaveBeenCalledTimes(1);
|
||||
expect(mockLogContentRetryFailure).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should retry on SSL error during stream iteration (mid-stream failure)', async () => {
|
||||
|
||||
Reference in New Issue
Block a user