Skip to content

Commit 0ace38a

Browse files
lidge-junclaude
andcommitted
fix(usage): detect SSE stream when upstream omits Content-Type header
The chatgpt backend returns SSE responses without a Content-Type header. This caused isEventStream to be false, skipping the tee/inspection pump entirely — so usage was never extracted from the response.completed event and all entries showed usageStatus: "unreported" with tokens=0. Fall back to treating a 200 response with a body as SSE when the caller requested streaming and no Content-Type is present. Also ensure the downstream response has text/event-stream set so clients detect SSE correctly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b0571c9 commit 0ace38a

1 file changed

Lines changed: 6 additions & 1 deletion

File tree

src/server.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,11 @@ async function handleResponses(
462462
const upstreamContentType = upstreamResponse.headers.get("content-type");
463463
if (upstreamContentType) logCtx.usageDebugContentType = upstreamContentType;
464464
}
465-
const isEventStream = headers.get("content-type")?.toLowerCase().includes("text/event-stream") ?? false;
465+
// The chatgpt backend may omit Content-Type on SSE responses. Fall back to
466+
// treating a successful body as SSE when the caller requested streaming.
467+
const passthroughCt = headers.get("content-type")?.toLowerCase();
468+
const isEventStream = passthroughCt?.includes("text/event-stream")
469+
|| (upstreamResponse.ok && !!upstreamResponse.body && !passthroughCt && parsed.stream);
466470
const terminalRecorder = codexForwardTerminalOutcomeRecorder(config, authCtx, route.provider);
467471
const terminalBodyWillRecord = !!terminalRecorder && upstreamResponse.ok && isEventStream;
468472
// Capture quota from upstream response for multi-account tracking
@@ -522,6 +526,7 @@ async function handleResponses(
522526
} else {
523527
consumeForResponseLogMetadata(inspectBody, logCtx, turnAc.signal, () => unregisterTurn(turnAc));
524528
}
529+
if (!headers.has("content-type")) headers.set("content-type", "text/event-stream");
525530
return markNativePassthroughSseResponse(new Response(nativeBody, {
526531
status: upstreamResponse.status,
527532
headers,

0 commit comments

Comments
 (0)