Repository navigation
fix(responses): emit a spec-valid response.in_progress keepalive (#17825) - #18197
Merged
diegosouzapw merged 2 commits intoOct 26, 2026
Merged
Conversation
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.
Closes #17825
Root cause
open-sse/utils/sseHeartbeat.tsbuilt the syntheticresponse.in_progresskeepalive once, as a module constant with a stub response ({id, status}). The same stub was used for the early/startup keepalive (src/app/api/v1/responses/route.ts) and for mid-stream heartbeats. Spec-validating clients (Vercel AI SDK@ai-sdk/openai) requireresponse.id,response.created_atandresponse.modelonresponse.in_progressand abort the whole stream withAI_TypeValidationError.Fix
open-sse/utils/responsesKeepaliveFrame.ts:buildResponsesInProgressFrame()builds a complete Response (object,created_at,model,output,error,incomplete_details,background,parallel_tool_calls,tool_choice,tools), pluscreateResponsesInProgressTracker().sseHeartbeat.ts:OPENAI_RESPONSES_IN_PROGRESS_FRAMEis now the complete fallback frame (neutral model). For the Responses shape the transform tracksid/created_at/model/sequence_numberfrom passingresponse.created/response.in_progresslines (substring guard, split-chunk tolerant, never throws) and heartbeats reuse them.responses/route.ts: per-request startup and application keepalive frame (uniqueresp_keepalive_<uuid>, request-timecreated_at, requestmodel).Regression test
tests/unit/responses-keepalive-spec-valid-17825.test.ts(4 cases).RED on unfixed code:
GREEN after the fix: all cases in the file pass. Old tests that pinned the stub byte-for-byte (
sse-heartbeat,early-stream-keepalive,sseHeartbeat,responses-route-early-keepalive-wiring) were realigned to the complete shape without removing assertions (the route wiring test now matches the per-requestkeepaliveFrame).Gates
eslint (with suppressions), prettier,
typecheck:core,check:open-sse-typecheck,check-file-size,check-complexity,check-cognitive-complexity,check-changelog-integrityall OK. Pre-commit hooks passed.Note:
sseHeartbeat.test.tsandterminal-heartbeat-cleanup-16258.test.tsuse real 10-35 ms timers and flaked intermittently on the base as well while the host was at load average 50-100.