From 88c695259f543a7067ff6be6c3116e9674d7b346 Mon Sep 17 00:00:00 2001 From: cabana8471 Date: Fri, 30 Jan 2026 21:41:01 +0100 Subject: [PATCH] fix: address 3 new CodeRabbit review comments 1. agent.py: Reset opposite retry counter when entering rate_limit or error status to prevent mixed events from inflating delays 2. rate_limit_utils.py: Fix parse_retry_after() regex to reject minute/hour units - patterns now require explicit "seconds"/"s" unit or end of string 3. test_rate_limit_utils.py: Add tests for "retry after 5 minutes" and other minute/hour variants to ensure they return None Co-Authored-By: Claude Opus 4.5 --- agent.py | 4 ++++ rate_limit_utils.py | 8 ++++++-- test_rate_limit_utils.py | 4 ++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/agent.py b/agent.py index 265a702..6688bcf 100644 --- a/agent.py +++ b/agent.py @@ -372,6 +372,8 @@ async def run_autonomous_agent( elif status == "rate_limit": # Smart rate limit handling with exponential backoff + # Reset error counter so mixed events don't inflate delays + error_retries = 0 if response != "unknown": try: delay_seconds = clamp_retry_delay(int(response)) @@ -390,6 +392,8 @@ async def run_autonomous_agent( elif status == "error": # Non-rate-limit errors: linear backoff capped at 5 minutes + # Reset rate limit counter so mixed events don't inflate delays + rate_limit_retries = 0 error_retries += 1 delay_seconds = calculate_error_backoff(error_retries) print("\nSession encountered an error") diff --git a/rate_limit_utils.py b/rate_limit_utils.py index de70b24..9bdbb22 100644 --- a/rate_limit_utils.py +++ b/rate_limit_utils.py @@ -45,9 +45,13 @@ def parse_retry_after(error_message: str) -> Optional[int]: Returns: Seconds to wait, or None if not parseable. """ + # Patterns require explicit "seconds" or "s" unit, OR no unit at all (end of string/sentence) + # This prevents matching "30 minutes" or "1 hour" since those have non-seconds units patterns = [ - r"retry.?after[:\s]+(\d+)\s*(?:seconds?)?", - r"try again in\s+(\d+)\s*(?:seconds?|s\b)", + r"retry.?after[:\s]+(\d+)\s*(?:seconds?|s\b)", # Requires seconds unit + r"retry.?after[:\s]+(\d+)(?:\s*$|\s*[,.])", # Or end of string/sentence + r"try again in\s+(\d+)\s*(?:seconds?|s\b)", # Requires seconds unit + r"try again in\s+(\d+)(?:\s*$|\s*[,.])", # Or end of string/sentence r"(\d+)\s*seconds?\s*(?:remaining|left|until)", ] diff --git a/test_rate_limit_utils.py b/test_rate_limit_utils.py index eb1f01c..55ecaa7 100644 --- a/test_rate_limit_utils.py +++ b/test_rate_limit_utils.py @@ -53,8 +53,12 @@ class TestParseRetryAfter(unittest.TestCase): def test_minutes_not_supported(self): """Test that minutes are not parsed (by design).""" # We only support seconds to avoid complexity + # These patterns should NOT match when followed by minute/hour units assert parse_retry_after("wait 5 minutes") is None assert parse_retry_after("try again in 2 minutes") is None + assert parse_retry_after("retry after 5 minutes") is None + assert parse_retry_after("retry after 1 hour") is None + assert parse_retry_after("try again in 30 min") is None class TestIsRateLimitError(unittest.TestCase):