fix(relay): handle Codex Responses terminal events - #685
Conversation
|
|
已处理 原 review comment 中的两项问题:
修复提交: 现象与根因
修复范围
验证
备注:仓库根 部署建议
|
|
|
已处理 本轮 review comment 的两项问题。
修复提交: 修复
验证
部署建议
|
|
|
Follow-up cleanup addressing the review discussion in comment 1 and comment 2.
I pushed commit 5c43b27 with a behavior-preserving consolidation:
Scope and behavior remain unchanged: Codex channels only; pre-commit failures stay retry-policy controlled; post-commit failures skip retry; partial usage is settled; failed settlement does not emit consume records; fallback buffering remains capped at 1 MiB; existing error mapping is preserved. Validation:
|
|
Resolved in c73a4f1, following up on the reported compatibility-path audit gap:
The fix keeps both public signatures unchanged ( This is multi-node safe: the status is derived directly from the same DB-backed settlement operation; no process-local coordination or shared mutable cache is introduced. Regression coverage now verifies:
Validation:
The broad |
Problem / background
Codex channels can terminate native streaming
/v1/responsesrequests withresponse.doneorresponse.failed. The shared Responses stream handler only recognizedresponse.completedandresponse.incompleteas terminal events.This caused successful Codex requests ending with
response.doneto settle with zero token usage, whileresponse.failedcould be treated as a successful HTTP 200 stream.Evidence
Production request
202608110724223116292048268d9d6GBb22Z6zcompleted with HTTP 200 and EOF but recorded zero prompt and completion tokens. A production sample showed the same pattern across multiple Codex channels, so the issue was not isolated to one channel configuration.Root cause
OaiResponsesStreamHandlerforwarded all SSE events but extracted terminal usage only fromresponse.completedandresponse.incomplete. Codex-specific terminal event names were therefore ignored.Scope / design
The behavior change is gated by
ChannelTypeCodex:response.done.response.failedinto a relay error.Impact and risks
This changes native Responses streaming, retry behavior, and billing settlement for Codex channels only. The shared handler is used by other providers, so regression coverage explicitly verifies non-Codex isolation.
Production is multi-node, but the change is request-local and introduces no process-local coordination or persistent state.
Validation
go test ./relay/channel/openai ./relay/channel/codex ./relay -run "TestOaiResponsesStreamHandler|TestRelayChatOverCodex|TestResponses" -count=1go vet ./relay/channel/openai ./relay/channel/codexgit diff --check origin/main...HEADThe broader
go test ./relay/...suite has unrelated pre-existing failures in BlockRun initialization, Claude file-content assertions, and Codex image settings. Race testing also exposes an existing race inrelay/helper/stream_scanner.go; neither is introduced by this change.Deployment recommendation
/v1/responsesrelay streaming, retry decisions, and usage settlement.newapi-console,newapi-web, Terraform, and Cloudflare are not required.response.doneand oneresponse.failedpath before production rollout.Review follow-up
Code review identified two retry-state issues in the initial implementation:
response.failedattempt had already installed SSE/Codex response headers, so an exhausted retry could return a JSON error labeledtext/event-stream, and another provider retry could inherit stale headers.Follow-up commit
702918e4ffixes both while remaining Codex-only:event_stream_headers_setstate before returning a retryable failure.response.failed, re-arming the next attempt's watchdog.The new failure/retry tests and RelayInfo reset test passed 100 consecutive runs. Independent follow-up review approved the amended diff with no remaining findings.