mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-28 00:07:33 +00:00
The raw Chat Completions passthrough returned a nil error whenever the upstream
body ended, so an upstream that cut the SSE stream mid-generation surfaced as
HTTP 200 with usage 0/0: the client kept a half-finished answer, the request was
not counted as an SLA failure, and ops saw nothing. Observed against
opencode.ai/zen/go (deepseek-v4-pro): 11 of 1346 streams in 24h recorded a first
token but no final usage, alongside a concurrent `connection reset by peer`
against the upstream edge.
Track whether the upstream ever emitted a terminal signal — [DONE], a usage
chunk, or a finish_reason — and treat a stream that ends without one as an
upstream failure. Matching only [DONE] would misfire on compatible upstreams
that EOF right after their last chunk and would drop billing for tokens that
were actually delivered, so all three count.
- nothing written to the client yet: UpstreamFailoverError, retried on another
account with no client-visible half stream
- bytes already on the wire: typed openAIUpstreamStreamReadError, so the
handler appends an SSE error frame and marks the request an SLA failure
Client cancel/disconnect keeps the previous semantics — there the upstream read
error is indistinguishable from a truncation, so partial usage is still billed
rather than blamed on the account.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>