Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/core/src/core/geminiChat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,7 @@
});

describe('sendMessageStream with retries', () => {
it('should not retry on invalid content if model does not start with gemini-2', async () => {

Check warning on line 1125 in packages/core/src/core/geminiChat.test.ts

View workflow job for this annotation

GitHub Actions / Lint

Found sensitive keyword "gemini-2". Please make sure this change is appropriate to submit.
// Mock the stream to fail.
vi.mocked(mockContentGenerator.generateContentStream).mockImplementation(
async () =>
Expand Down Expand Up @@ -1154,6 +1154,7 @@
1,
);
expect(mockLogContentRetry).not.toHaveBeenCalled();
expect(mockLogContentRetryFailure).toHaveBeenCalledTimes(1);
});

it('should yield a RETRY event when an invalid stream is encountered', async () => {
Expand Down
31 changes: 12 additions & 19 deletions packages/core/src/core/geminiChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down Expand Up @@ -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
}

Expand All @@ -397,7 +393,6 @@ export class GeminiChat {
value: error.syntheticResponse,
};
}
lastError = null; // Clear error as this is an expected stop
return; // Stop the generator
}

Expand All @@ -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)) ||
Expand All @@ -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,
Expand All @@ -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),
);
Comment thread
yunaseoul marked this conversation as resolved.

throw error;
}
throw lastError;
}
} finally {
streamDoneResolver!();
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/core/geminiChat_network_retry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down
Loading