[codex] Support sequential cutoff reasoning summaries (#31306)

## Summary

When enabled for the OpenAI provider, Codex sends
`stream_options.reasoning_summary_delivery = "sequential_cutoff"` on
HTTP and
WebSocket requests, including prewarm, and renders completed summary
sections
from `reasoning_summary_text.done`. Flag-off and non-OpenAI behavior is
unchanged.

## Expected rollout

```text
reasoning 0 added
summary 0 done
summary 1 done
summary 2 starts
summary 2 cancelled / incomplete
reasoning 0 done  <-- cancel summary 2 work and mark it incomplete
message 1 added
message 1 text streams
message 1 completed
```

Depends on
[openai/openai#1096660](https://github.com/openai/openai/pull/1096660).
This commit is contained in:
ashwinnathan-openai authored and GitHub committed 2026-07-06 23:23:56 -04:00
1 parent 831c14fc39
commit 775ef7dcc7
20 files changed
+352 -6

No files matched your search

+38
View File
@@ -167,6 +167,7 @@ pub struct ResponsesStreamEvent {
item_id: Option<String>,
call_id: Option<String>,
delta: Option<String>,
text: Option<String>,
summary_index: Option<i64>,
content_index: Option<i64>,
safety_buffering: Option<Value>,
@@ -358,6 +359,17 @@ pub fn process_responses_event(
}));
}
}
"response.reasoning_summary_text.done" => {
if let (Some(item_id), Some(text), Some(summary_index)) =
(event.item_id, event.text, event.summary_index)
{
return Ok(Some(ResponseEvent::ReasoningSummaryDone {
item_id,
text,
summary_index,
}));
}
}
"response.reasoning_text.delta" => {
if let (Some(delta), Some(content_index)) = (event.delta, event.content_index) {
return Ok(Some(ResponseEvent::ReasoningContentDelta {
@@ -796,6 +808,32 @@ mod tests {
}
}
#[tokio::test]
async fn parses_reasoning_summary_done() {
let events = run_sse(vec![
json!({
"type": "response.reasoning_summary_text.done",
"item_id": "reasoning-1",
"summary_index": 0,
"text": "Checking",
}),
json!({
"type": "response.completed",
"response": { "id": "resp1" },
}),
])
.await;
assert_matches!(
&events[0],
ResponseEvent::ReasoningSummaryDone {
item_id,
text,
summary_index: 0,
} if item_id == "reasoning-1" && text == "Checking"
);
}
#[tokio::test]
async fn error_when_missing_completed() {
let item1 = json!({