feat(gateway): keep the last response on a Responses WebSocket - #56
Merged
Merged
Conversation
OpenAI's socket mode keeps the connection's most recent response, so a turn can name it in previous_response_id with store: false, which is how Codex runs. Each turn here is a separate upstream request, possibly to an upstream in another format with no such store, so that failed. The connection now keeps its most recent response as the conversation so far: the turn's full input plus the output items of its response.completed (without their store ids). A turn naming it goes upstream with that history in input and no previous_response_id, valid against any upstream and billed as what it is. A previous_response_id naming anything else goes upstream as sent. A failed turn leaves the chain where it was. Co-Authored-By: Claude Opus 5.5 <[email protected]>
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.
Closes the
previous_response_idgap in the Responses WebSocket bridge (#43).The gap, and the options
OpenAI's socket mode keeps the connection's most recent response in memory, so a turn can continue from it with
previous_response_ideven withstore: false— which is how Codex runs. The desktop gateway gets that for free: it pipes the whole socket to one upstream socket, and the upstream keeps the state. This bridge runs eachresponse.createas its own request through the HTTP pipeline, so the upstream had no connection and astore: falsecontinuation failed.Options considered:
What it does
The connection keeps its most recent response as the conversation so far: the input the turn went upstream with, plus the output items of its
response.completed(with the upstream's storeid/statusremoved — they would be looked up and not found;call_idstays, it ties tool results to calls). A turn whoseprevious_response_idnames it goes upstream with that history ininputand noprevious_response_id, which any upstream accepts and which is billed for what it actually sends. Like OpenAI, only the most recent response is kept; aprevious_response_idnaming anything else goes upstream as sent (for an upstream that stored it). A failed or cancelled turn leaves the chain where it was.Tests
store: false, the second naming the first's id, against a Chat upstream: the second upstream request carries user "one", the assistant's answer, user "two". Fails on the old code, passes now.--all-targets,--lib), 690 unit tests, the WebSocket integration file.🤖 Generated with Claude Code