Classify streaming rate-limit errors (#40931)

## What changed

- Classify `response.failed` events with the `rate_limit_exceeded` code as a distinct retryable error while preserving any parsed retry delay.
- Expose the error as `rateLimitExceeded` through the core protocol and app-server schemas after stream retries are exhausted.
- Preserve the upstream message for TUI display while keeping it out of telemetry summaries.

## Testing

- Cover SSE classification, retry metadata, protocol conversion and serialization, exhausted stream retries, telemetry redaction, and TUI rendering.

GitOrigin-RevId: 02dab4d3477dcd7653a58c49c4bd38687a616579
This commit is contained in:
Steve Coffey
2026-08-26 17:45:42 +00:00
committed by copyberry
parent 7625bd5665
commit e0c727de04
38 changed files with 198 additions and 26 deletions
+5
View File
@@ -91,6 +91,9 @@ pub enum CodexErrorDetails {
/// The Session loop treats this as a transient error and will automatically retry the turn.
#[error("stream disconnected before completion: {0}")]
Stream(String),
/// A retryable upstream rate limit received inside the response stream.
#[error("rate limit exceeded: {0}")]
RateLimitExceeded(String),
#[error(
"Codex ran out of room in the model's context window. Start a new thread or clear earlier history before retrying."
)]
@@ -388,6 +391,7 @@ impl CodexErr {
| CodexErrorDetails::CyberPolicy { .. }
| CodexErrorDetails::MisalignmentPolicyViolation { .. } => false,
CodexErrorDetails::Stream(..)
| CodexErrorDetails::RateLimitExceeded(_)
| CodexErrorDetails::Timeout
| CodexErrorDetails::RequestTimeout
| CodexErrorDetails::UnexpectedStatus(_)
@@ -424,6 +428,7 @@ impl CodexErr {
match &self.details {
CodexErrorDetails::ContextWindowExceeded => CodexErrorInfo::ContextWindowExceeded,
CodexErrorDetails::SessionBudgetExceeded => CodexErrorInfo::SessionBudgetExceeded,
CodexErrorDetails::RateLimitExceeded(_) => CodexErrorInfo::RateLimitExceeded,
CodexErrorDetails::UsageLimitReached(_)
| CodexErrorDetails::QuotaExceeded
| CodexErrorDetails::UsageNotIncluded => CodexErrorInfo::UsageLimitExceeded,