From 4f004adefa00acc0847a277090046f69cdae48a4 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 29 Jan 2026 01:12:29 +0100 Subject: [PATCH] fix(coding-agent): reset retry counter after each successful LLM response Previously, within a single tool-use turn, rate limit retries would accumulate across separate LLM calls. For example, if each of 3 tool calls hit a 429 and retried once, the counter would show '3/3' and fail even though each individual retry succeeded. Now the counter resets immediately when a successful (non-error) assistant message arrives, so each LLM call gets a fresh set of retries. Fixes #1019 --- packages/coding-agent/CHANGELOG.md | 1 + .../coding-agent/src/core/agent-session.ts | 23 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index c24debd3..adeffc40 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixed - Empty array in package filter now disables all resources instead of falling back to manifest defaults ([#1044](https://github.com/badlogic/pi-mono/issues/1044)) +- Auto-retry counter now resets after each successful LLM response instead of accumulating across tool-use turns ([#1019](https://github.com/badlogic/pi-mono/issues/1019)) ## [0.50.1] - 2026-01-26 diff --git a/packages/coding-agent/src/core/agent-session.ts b/packages/coding-agent/src/core/agent-session.ts index 5d757197..8a7a2e52 100644 --- a/packages/coding-agent/src/core/agent-session.ts +++ b/packages/coding-agent/src/core/agent-session.ts @@ -354,6 +354,19 @@ export class AgentSession { // Track assistant message for auto-compaction (checked on agent_end) if (event.message.role === "assistant") { this._lastAssistantMessage = event.message; + + // Reset retry counter immediately on successful assistant response + // This prevents accumulation across multiple LLM calls within a turn + const assistantMsg = event.message as AssistantMessage; + if (assistantMsg.stopReason !== "error" && this._retryAttempt > 0) { + this._emit({ + type: "auto_retry_end", + success: true, + attempt: this._retryAttempt, + }); + this._retryAttempt = 0; + this._resolveRetry(); + } } } @@ -366,16 +379,6 @@ export class AgentSession { if (this._isRetryableError(msg)) { const didRetry = await this._handleRetryableError(msg); if (didRetry) return; // Retry was initiated, don't proceed to compaction - } else if (this._retryAttempt > 0) { - // Previous retry succeeded - emit success event and reset counter - this._emit({ - type: "auto_retry_end", - success: true, - attempt: this._retryAttempt, - }); - this._retryAttempt = 0; - // Resolve the retry promise so waitForRetry() completes - this._resolveRetry(); } await this._checkCompaction(msg);