feat(openai)!: expose typed Responses retry observability - #21
Merged
Conversation
Forward bounded per-request retry observations through loop observers and retain sanitized provider classification with terminal accounting. Count actual sends and completed waits, preserve cancellation semantics, and finalize library-owned cancellation and deadline races. BREAKING CHANGE: Responses model-session failures now use LoopError::ProviderFailure. Downstream exhaustive LoopError matches and versioned AgentEvent readers must be updated before consuming the new contract.
Reject malformed and non-HTTP(S) endpoints locally instead of counting and retrying reqwest builder failures. Align invalid local attribution headers with InvalidRequest and verify zero executions with a real reqwest-backed transport.
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
Expose typed, sanitized Responses retry progress through loop observers and retain provider classification and retry accounting in terminal model failures. This supplies the upstream contract needed by Kit #45, #46, and #47.
Motivation
Initial retries occur inside
begin_turn, before a model stream is available. Hosts need live progress during those waits and structured terminal metadata without parsing provider error strings.Impact
Responses model-session failures now use
LoopError::ProviderFailure, with an accessor for typed metadata. This is a breaking change for exhaustiveLoopErrormatches. Existing serializedAgentEventvariants remain unchanged, but readers must understand the new retry variant before it crosses a versioned boundary.The host still owns ACP delivery, fatal-record persistence, stable fatal correlation, and effects provenance. Downstream integration requires coordinated reader updates and separately published compatible crates.
Technical details
Bounded observations across request setup and streaming
A default-compatible
ModelSession::set_retry_observerhook forwardsScheduled,Stopped, andSucceededobservations throughAgentEvent::ProviderRetry. Scheduled snapshots are limited to one per 250 ms per model request, with no queue and unsuppressed terminal observations. These are not additional model results or effects records.Sanitized classification and exact accounting
Canonical allowlists retain upstream type/code separately from local terminal and last-attempt reasons; unknown values become
Unknown. No provider messages, response bodies, credentials, prompts, or endpoint URLs enter the payloads. Attempts count polled HTTP client executions, including reactive-authentication resends. Completed backoff sums only fully completed requested waits; elapsed time begins before authentication.Explicit cancellation and deadline precedence
LoopError::Cancelledremains unchanged, with accounting available through the terminal observation. A default-compatibleModelTurn::on_cancelledhook finalizes library-owned post-event cancellation before the driver drops a turn. Cancellation and logical deadlines win ready-completion races, including buffered stream completion; arbitrary dropped futures do not promise terminal delivery.