fix(agent): only set rate-limit cooldown when leaving primary; add tests

This commit is contained in:
vlwkaos
2026-04-12 14:14:26 +09:00
committed by Teknium
parent a9fd8d7c88
commit f7f7588893
4 changed files with 135 additions and 2 deletions

View File

@@ -6494,7 +6494,7 @@ class AIAgent:
# ── Provider fallback ──────────────────────────────────────────────────
def _try_activate_fallback(self) -> bool:
def _try_activate_fallback(self, reason: "FailoverReason | None" = None) -> bool:
"""Switch to the next fallback model/provider in the chain.
Called when the current model is failing after retries. Swaps the
@@ -6506,6 +6506,15 @@ class AIAgent:
auth resolution and client construction — no duplicated provider→key
mappings.
"""
if reason in (FailoverReason.rate_limit, FailoverReason.billing):
# Only start cooldown when leaving the primary provider. If we're
# already on a fallback and chain-switching, the primary wasn't the
# source of the 429 so the cooldown should not be reset/extended.
fallback_already_active = bool(getattr(self, "_fallback_activated", False))
current_provider = (getattr(self, "provider", "") or "").strip().lower()
primary_provider = ((self._primary_runtime or {}).get("provider") or "").strip().lower()
if (not fallback_already_active) or (primary_provider and current_provider == primary_provider):
self._rate_limited_until = time.monotonic() + 60
if self._fallback_index >= len(self._fallback_chain):
return False
@@ -6689,6 +6698,9 @@ class AIAgent:
if not self._fallback_activated:
return False
if getattr(self, "_rate_limited_until", 0) > time.monotonic():
return False # primary still in rate-limit cooldown, stay on fallback
rt = self._primary_runtime
try:
# ── Core runtime state ──
@@ -10665,7 +10677,7 @@ class AIAgent:
)
if not pool_may_recover:
self._emit_status("⚠️ Rate limited — switching to fallback provider...")
if self._try_activate_fallback():
if self._try_activate_fallback(reason=classified.reason):
retry_count = 0
compression_attempts = 0
primary_recovery_attempted = False