mirror of
https://github.com/usestrix/strix.git
synced 2026-08-25 20:32:38 +02:00
fix(llm): retry statusless mid-stream provider errors (quota/billing)
The SDK's http_status retry policy only retries errors carrying a known HTTP status code, but quota/billing (and other provider-side) failures often surface inside a streamed response as a bare error with no status code, so they were failing on the first attempt. Add a statusless retry policy to DEFAULT_MODEL_RETRY so they are retried (before any content is streamed; user aborts are never retried), restoring the pre-SDK engine's resilience. If the provider is genuinely exhausted, the error still propagates and fails the scan after retries.
This commit is contained in:
@@ -10,6 +10,7 @@ from agents.models.multi_provider import MultiProvider
|
||||
from agents.retry import (
|
||||
ModelRetryBackoffSettings,
|
||||
ModelRetrySettings,
|
||||
RetryPolicyContext,
|
||||
retry_policies,
|
||||
)
|
||||
|
||||
@@ -20,6 +21,24 @@ if TYPE_CHECKING:
|
||||
from strix.config.settings import Settings
|
||||
|
||||
|
||||
def _retry_statusless_provider_errors(context: RetryPolicyContext) -> bool:
|
||||
"""Retry provider errors that arrive without an HTTP status code.
|
||||
|
||||
Quota, billing, and other provider-side failures frequently surface *inside*
|
||||
a streamed response as a bare error with no ``status_code`` (the transport
|
||||
already returned ``200`` before the failure). The built-in ``http_status``
|
||||
policy skips these because it requires a known code, so they would otherwise
|
||||
fail on the first attempt. Retrying a statusless error (the runner still
|
||||
refuses to replay a stream once content has been emitted, and never retries a
|
||||
user abort) mirrors the pre-SDK engine, which retried any error lacking a
|
||||
definitive client status code.
|
||||
"""
|
||||
normalized = context.normalized
|
||||
if normalized.is_abort:
|
||||
return False
|
||||
return normalized.status_code is None
|
||||
|
||||
|
||||
class StrixProvider(MultiProvider):
|
||||
"""Route any non-OpenAI prefix through LiteLLM with the prefix preserved,
|
||||
so users type ``deepseek/deepseek-chat`` rather than
|
||||
@@ -56,6 +75,7 @@ DEFAULT_MODEL_RETRY = ModelRetrySettings(
|
||||
retry_policies.provider_suggested(),
|
||||
retry_policies.network_error(),
|
||||
retry_policies.http_status((429, 500, 502, 503, 504)),
|
||||
_retry_statusless_provider_errors,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user