Skip to content

Fix duplicate streaming requests, cancellation and SSE framing - #201

Open
memoryttt wants to merge 1 commit into
jamesrochabrun:mainfrom
memoryttt:codex/fix-stream-transport
Open

memoryttt wants to merge 1 commit into
jamesrochabrun:mainfrom
memoryttt:codex/fix-stream-transport

Conversation

@memoryttt

Copy link
Copy Markdown

Streaming HTTP failures currently send the same request twice: the error branch calls data(for:) after bytes(for:) to obtain diagnostics. On Apple platforms, cancelling a stream consumer also leaves the URLSession request running, and AsyncBytes.lines removes the blank lines needed to delimit SSE events. The shared parser decodes each data: line separately and continues past [DONE].

This change reads the original error body for Responses, Chat Completions and Assistants, retaining the existing APIError.responseUnsuccessful status and message contract. The Apple adapter reuses HTTPLineDecoder and cancels only the producer and URLSessionTask belonging to that request. The Responses/Chat Completions parser joins data fields per event, ignores SSE control fields, and stops at [DONE]. Malformed payloads still fail; the existing final-line-at-EOF behavior is preserved.

Validation:

  • Reproduced against unmodified 4.6.2 (c757e0b): all 15 HTTP status/endpoint combinations repeated the request and reported the second response's message; multiline SSE and DONE assertions failed. A loopback server also confirmed dropped blank lines and continued network activity after cancellation.
  • All 101 existing XCTest tests and 11 new Swift Testing methods pass. Parameterized cases cover HTTP 400/401/403/429/500, raw-byte and line error bodies, and non-JSON fallback diagnostics.
  • Native integration tests verify CR/LF, UTF-8, multiline Responses events, and two concurrent requests sharing one session: cancelling one closes its server connection while the other continues; cancelling both leaves no URLSession tasks.
  • Full repository SwiftFormat lint and the iOS 18 simulator SDK build pass. New Swift Testing files are guarded for Swift 6 so older compilers can continue running the existing XCTest suite.

Related implementation history: #160 added the repeated error-body request; #6 added earlier stream cancellation support; #200 introduced the line decoder for Linux. This PR does not change the Linux adapter or the successful Assistants event parser. Validation uses synthetic responses and a loopback server, without API credentials or model calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant