Repository navigation
Conversation
…-only streams on transient drops
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
close_notify/unexpected-eofretry: Classifies rustls's statuslesspeer closed connection without sending TLS close_notify(#unexpected-eof) transport failure as retryable inproviders::codex::events::retryable_messagesoclaude-code-proxyautomatically retries pre-semantic WebSocket/HTTP drops withinsend_with_retry(while keeping*_policy/*_policy_violationevent errorsPermanent400).codex,grok,opencode,cursor): When an upstream stream fails mid-turn with a retryable transport or transient (5xx/529) error after emittingthinkingdeltas (HTTP 200headers already flushed) before any visibletext,tool_use, orserver_tool_usecontent block has started, aborts the downstream HTTP chunked body withErr(std::io::Error)instead of synthesizingevent: error+ clean EOF.withRetrytreats a synthetic SSEevent: error+ clean0\r\n\r\nEOF as a terminalAPIErrorand stops the turn, whereas an aborted chunked stream surfaces asUND_ERR_SOCKET(APIConnectionError) and triggers seamless turn-level retry (maxRetries = 10, exponential backoff from500ms), discarding any uncommitted thinking blocks on the discarded attempt.text,tool_use,server_tool_use) has started—or when the upstream failure is non-retryable (4xx, policy violation, invalid prompt, auth/quota)—continues emittingevent: error+ clean EOF to avoid duplicating side effects or retrying deterministic rejections.Test Plan
cargo fmt --all -- --checkcargo clippy --all-targets -- -D warningscargo test --all --lockedclose_notify/unexpected-eofretry classification andcyber_policy_violationpermanent classification (providers::codex::client::tests)event: error+ clean EOF vs. mid-thinking permanentcyber_policy_violation->event: error+ clean EOF (providers::codex::tests)event: error(providers::grok::tests)messages,chat,responses) and Cursor visible-output tracking and mid-thinking chunked-body abort