Conversation
…gh parsers The Responses API and Speech passthrough translators only recognised "\n\n" as the SSE event boundary, so a compliant upstream using CRLF line endings never had its response.created / response.completed events observed by the gateway. The bytes were still forwarded to the client, but usage metrics, access logs and tracing lost the token counts and resolved model. Add cutSSEEvent and sseLines helpers that split on any spec-allowed line ending (LF, CRLF, CR), keeping a trailing lone CR buffered since it may be the first byte of a CRLF split across chunks, and use them in both parsers. Signed-off-by: Kamil Dokumaci <dok@tuta.com>
✅ Deploy Preview for theagentrouter canceled.
|
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.
Description
The OpenAI Responses passthrough translator (and the Speech translator, which has the identical loop) only recognised
\n\nas the SSE event boundary. SSE also permits CRLF (\r\n\r\n) and CR line endings. For a compliant upstream using CRLF, the parser kept every event buffered, so the gateway never observedresponse.created/response.completedand lost the resolved model and token usage for metrics, access logs and tracing, even though the bytes were still forwarded to the client unchanged.The optional space after
data:mentioned in the issue is already handled onmainbycutSSEDataPrefix; this PR covers the remaining line-ending half.Changes:
cutSSEEventinutil.go: splits the buffer at the first empty line, accepting LF, CRLF or CR line endings. A trailing lone\rstays buffered because it may be the first byte of a CRLF that is split across two response body chunks.sseLines: splits an event into lines on any of those endings, sodata:lines no longer carry a trailing\r.openai_responses.goandopenai_speech.goin place of the hard-coded\n\n/\nhandling.event:-prefixed streams for the Responses parser, a CRLF boundary split across twoResponseBodycalls with the\rat the chunk edge, and a CRLF case for the Speech span recorder.The Anthropic-format stream parsers in
anthropic_helper.go/openai_helper.goalso split on\n\n; I left them out to keep this focused on the passthrough parsers from the issue, but happy to switch them to the same helper here or in a follow-up.Fixes #2463
Notes
make precommitandgo test ./internal/translator/...pass locally.