feat(api): frame /v1/responses stream=true as official SSE events - #627
feat(api): frame /v1/responses stream=true as official SSE events#627cursor[bot] wants to merge 11 commits into
Conversation
…closed otherwise Chat history: message-level audio and legacy function_call are null/empty omit no-ops; non-empty fail closed with named errors (including tools passthrough). Tip substrate from #577 assistant refusal/annotations honesty. Local full unit: 940 passed.
…ed otherwise OpenAI fine-tune style message weight is not applied on this gateway. Accept null/0/1 as honest no-ops; reject other types and values with invalid_message_weight. Tip substrate from #578. Local full unit: 943 passed.
…ion role Reject unsupported message keys with named unknown_message_fields (not silent strip or tools-passthrough smuggle). Reject legacy function role with invalid_message_role migration to tool. Tip substrate from #579. Local full unit: 947 passed.
OpenAI partial-assistant prefix flag is not applied on this gateway. null/false are honest no-ops; true and non-booleans fail closed with invalid_message_prefix. Tip substrate from #580. Local full unit: 950 passed.
…therwise Named invalid_max_tool_calls on /v1/chat/completions instead of opaque unknown_fields. Aligns with Responses max_tool_calls honesty; gateway has no multi-step tool loop.
…losed otherwise Legacy /v1/completions treated max_tool_calls as unknown_fields. Accept the key for named invalid_max_tool_calls (null/empty/whitespace omit-equivalent), matching chat/Responses honesty so SDKs get a clear migration path.
SDK clients often send include_usage/include_obfuscation as JSON null. Drop null flag values before validation so null (and null+false mixes) match omit / all-false no-ops on chat, Completions, and Responses. True flags remain fail-closed with invalid_stream_options.
…or Responses parallel true SDK optional defaults often send function.strict and json_schema.strict as null — treat as omit rather than type errors. Align Responses parallel_tool_calls=true with chat by requiring a non-empty tools array.
Accepting strict: null without removing the key was not omit-equivalent: proxy_completion forwarded "strict": null and providers can 400. Strip the key in place, keep boolean strict, and assert the mock echo. Document the Responses parallel_tool_calls=true + tools contract (OpenAI, 2024). Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Official Responses SDKs send {type, name, parameters, strict} at the tool
root. Chat-shaped tools still work on Responses; chat stays fail-closed on
the native shape. Pop native strict:null before passthrough and accept
named tool_choice {type, name}. Cite OpenAI (2024c, 2024d).
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Official Responses SDKs default to streaming. Frame the completed passthrough JSON as response.created, response.output_text.delta, and response.completed so concatenated deltas equal the non-stream output_text. Cite OpenAI (2024e). Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
There was a problem hiding this comment.
Stale comment
Unique tip
9051edcis framed-from-complete SSE — prefer #628 as the landing vehicleThis PR's unique increment (
9051edc) frames a completed/v1/responsespassthrough as officialresponse.created/response.output_text.delta/response.completedevents. Buyer accuracy holds: concatenated deltas equal the non-streamoutput_text.Do not merge this 146-file stack onto main. Concurrent #628
167f709is the Responses-stream landing vehicle: same officialresponse.*events, plus mockfunction_callreconstruction and live-provider verbatim SSE, on the #617 substrate.Buyer next action: use #628 for
stream=trueon/v1/responses. Cherry-pick9051edconly if #628 is missing a framed-from-complete unit helper you need. Independent non-author APPROVE is still required. This automation will not self-approve.Sent by Cursor Automation: Fix Issues
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
Do not merge this stack onto main.
9051edc turns /v1/responses stream=true into a buffered text/event-stream whose concatenated response.output_text.delta values match the non-stream output_text. Auth, SSRF, and KV-not-env are unchanged. That buyer-accuracy check is necessary and not sufficient for a legal official Responses stream (OpenAI, 2024e).
This review cannot REQUEST_CHANGES on an automation-authored PR. Treat the following as blocking before any merge:
Contract gaps on the unique tip
-
response.createdis not official-shaped (contextual_orchestrator/orchestrator.py,in_progress = dict(payload)). Official created requiressequence_number,status=in_progress,output=[], andusage=null. This shallow-copies the completed passthrough, so created already contains the full assistant text. Clients that init fromcreated.response.outputthen append deltas will double-render. -
Required lifecycle and indices are missing. A legal text stream is
in_progress→output_item.added→content_part.added→output_text.delta*→output_text.done→content_part.done→output_item.done→completed, each withsequence_number. The current loop flattens every part tooutput_index=0/{id}_msgand never emitsfunction_call_arguments.delta. -
Stale fail-closed copy (
contextual_orchestrator/server.pyinvalid_stream_options).stream=trueis implemented, but a trueinclude_usage/include_obfuscationflag still says “stream is not supported”. Official SDKs often sendstream_options.include_usage=truewithstream=True. -
Tests do not lock the official contract (
tests/test_responses_stream_http_honesty.py_parse_sse_events). The parser ignoresevent:lines. Nothing assertssequence_number, empty created output, oroutput_text.done.
What to do next
- Do not land this 146-file honesty stack as the stream vehicle. The Responses-stream landing remains #628. Rebase only the unique framing increment, or fold the contract fixes into that head.
- On created: send empty
output+usage=null+sequence_number. Keep the full object forresponse.completedonly. Assertcreated["response"]["output"] == []. - Walk
payload["output"]per item/part; emit add/delta/done with real item ids and indices. Foldfunction_call_arguments.*into #628. - Name the unsupported
stream_optionsflags in the 400 message. Addstream=true+include_usage=true→400invalid_stream_optionswith the new text. - Parse both
event:anddata:; assert they match; keep the reconstruct-text assertion.
Required CI was still pending at review time. Independent non-author APPROVE is still required after the contract lands. This review will not self-approve.
OpenAI. (2024e). Streaming events. OpenAI API reference. https://platform.openai.com/docs/api-reference/responses-streaming
Sent by Cursor Automation: Fix Issues
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current head9051edc3cabfaa5ce67a149755eba66d6af9b377. -
Head SHA:
9051edc3cabfaa5ce67a149755eba66d6af9b377 -
Workflow run: 32124468263
-
Workflow attempt: 1
Coverage evidence
Coverage evidence job did not run or did not publish coverage evidence.
Changed-File Evidence Map
flowchart LR
Evidence["OpenCode evidence"] --> Review["Current PR review path"]
Review --> Verify["Required checks"]
OpenCode Review Overview
Pull request overviewOpenCode cannot approve yet because required coverage evidence did not pass. Review outcome1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
Coverage evidenceCoverage evidence job did not run or did not publish coverage evidence. Changed-File Evidence Mapflowchart LR
Evidence["OpenCode evidence"] --> Review["Current PR review path"]
Review --> Verify["Required checks"]
|
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current head9051edc3cabfaa5ce67a149755eba66d6af9b377. -
Head SHA:
9051edc3cabfaa5ce67a149755eba66d6af9b377 -
Workflow run: 32129246452
-
Workflow attempt: 1
Coverage evidence
Coverage evidence job did not run or did not publish coverage evidence.
Changed-File Evidence Map
flowchart LR
Evidence["OpenCode evidence"] --> Review["Current PR review path"]
Review --> Verify["Required checks"]


Unique tip
9051edcframes/v1/responsesstream=trueas official Responses SSE (response.created,response.output_text.delta,response.completed). Concatenated deltas equal the non-streamoutput_text. Framed from the completed passthrough (like conduct-mode chat), not live provider token SSE.Buyer next action: send
"stream": trueon/v1/responsesand consumeresponse.output_text.delta.stream=false/ omit stay JSON. Non-booleanstreamremains400invalid_stream.stream_optionstrue flags still fail closed until usage/obfuscation are implemented on this path.Do not merge this stack onto main
This branch sits on the #604 honesty substrate. The unique increment is streaming only. Rebase
9051edconto the current stream-path tip (#606) or the named landing vehicle. Independent non-author APPROVE is required.Tests
References
OpenAI. (2024e). Streaming events. OpenAI API reference. https://platform.openai.com/docs/api-reference/responses-streaming
OpenAI. (2024c). Create a model response. OpenAI API reference. https://platform.openai.com/docs/api-reference/responses/create