-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Add item streaming events #5546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Introduce AgentMessageContentDeltaEvent, ReasoningContentDeltaEvent, and ReasoningRawContentDeltaEvent with thread_id, turn_id, and item_id, emitted during streaming, alongside legacy events for compatibility. - Refactor output delta handling to associate deltas with active items and emit item-specific delta events. - Move legacy event emission via new HasLegacyEvent trait for simpler event compatibility. - Update parse_agent_message to use
# Conflicts: # codex-rs/core/src/codex.rs
…egacy event for ItemStartedEvent - Move `error_or_panic` from conversation_history.rs to util.rs and update all usage sites accordingly. - Use `error_or_panic` in codex.rs to handle error conditions on various response events instead of directly logging with `error!`. - Implement `HasLegacyEvent` for `ItemStartedEvent` in protocol.rs to emit a WebSearchBegin legacy event
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let item = ResponseItem::Message { | ||
| id: None, | ||
| role: "assistant".to_string(), | ||
| content: vec![], | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Emit stable IDs for streamed assistant items
When an assistant delta arrives in chat completions, append_assistant_text builds a ResponseItem::Message with id: None. Downstream, parse_turn_item assigns a fresh UUID whenever an item lacks an ID, so ItemStarted, AgentMessageContentDelta, and ItemCompleted events for the same streamed message use different generated IDs. Clients can’t correlate deltas with their corresponding completion and tests only pass because the mock SSE events already provide IDs. Assign a concrete ID when the item is first constructed and reuse it for all subsequent events so the identifier stays consistent.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems potentially legit feedback?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok so the feedback is legit but it always worked this way.
@pakrym-oai how big of a deal is this? either way, addressing this seems out of scope for this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as we don't emit Item events with different item id (which I don't think we do based on active.id()) we should be good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall lgtm! just a comment about the web search call
|
|
||
| #[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)] | ||
| pub struct AgentMessageContentDeltaEvent { | ||
| pub thread_id: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decided to add these to all the events? nice!
| let item = ResponseItem::Message { | ||
| id: None, | ||
| role: "assistant".to_string(), | ||
| content: vec![], | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems potentially legit feedback?
| .and_then(|v| v.as_str()) | ||
| .unwrap_or("") | ||
| .to_string(); | ||
| let ev = ResponseEvent::WebSearchCallBegin { call_id }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed we delete the WebSearchCall event in various places - what's the plan for that one?
Are we planning to support some translation of https://platform.openai.com/docs/api-reference/responses-streaming/response/web_search_call or just dropping it entirely?
My guess is Responses API does something like this for a web search call:
response.output_item.added
response.web_search_call.in_progress
response.web_search_call.searching
response.web_search_call.completed
response.output_item.done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't actually need to handle web_search_call events specifically and we can emit EventMsg::WebSearchBegin and EventMsg::WebSearchEnd based on response.output_item.added response.output_item.done
Here's a trace of an actual request:
�[2m2025-10-24T16:10:55.257490Z�[0m �[35mTRACE�[0m SSE event: {"type":"response.output_item.added","sequence_number":203,"output_index":1,"item":{"id":"ws_0bb4a7dd4caece510168fba50f3a788190a16bcfee2fcef85a","type":"web_search_call","status":"in_progress"}}
�[2m2025-10-24T16:10:55.267924Z�[0m �[35mTRACE�[0m SSE event: {"type":"response.web_search_call.in_progress","sequence_number":204,"output_index":1,"item_id":"ws_0bb4a7dd4caece510168fba50f3a788190a16bcfee2fcef85a"}
�[2m2025-10-24T16:10:56.830551Z�[0m �[35mTRACE�[0m SSE event: {"type":"response.web_search_call.searching","sequence_number":205,"output_index":1,"item_id":"ws_0bb4a7dd4caece510168fba50f3a788190a16bcfee2fcef85a"}
�[2m2025-10-24T16:11:02.043478Z�[0m �[35mTRACE�[0m SSE event: {"type":"response.web_search_call.completed","sequence_number":206,"output_index":1,"item_id":"ws_0bb4a7dd4caece510168fba50f3a788190a16bcfee2fcef85a"}
�[2m2025-10-24T16:11:02.046008Z�[0m �[35mTRACE�[0m SSE event: {"type":"response.output_item.done","sequence_number":207,"output_index":1,"item":{"id":"ws_0bb4a7dd4caece510168fba50f3a788190a16bcfee2fcef85a","type":"web_search_call","status":"completed","action":{"type":"search","query":"top news headlines October 24, 2025 Reuters"}}}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So Codex would do this client-side? i.e. Codex would inspect the output_item when it's added, and if it's a web search call, emit the EventMsg::WebSearchBegin event? I think that'd work but why not just translate the server events? Seems cleaner that way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So Codex would do this client-side?
We already do this. see https://github.com/openai/codex/pull/5546/files#diff-6d2d1446867cf2e611597ebbf293689be55ad7cd32c1081cdab6de2358dccb91R539
If end goal is to have codex level item_starter/item_completed event and we can do it for all item types consistently by listening to item.added/item.completed from Responses API, why not do it? The end result is the same and the logic is simpler for us. We use the same code path for WebSearch, Agent Messages and Reasoning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok sounds good. do we plan to keep exposing WebSearchCall events in the stable app-server API too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, only ItemStarted with a WebSearch item type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh i see, then it makes a lot of sense to do it client-side. ty for the explanation! 🚢
a08f260 to
8658848
Compare
| EventMsg::ItemCompleted(ItemCompletedEvent { | ||
| item: TurnItem::AgentMessage(_), | ||
| .. | ||
| }) => {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aibrahim-oai @pakrym-oai is this fix legit? trying to make sense of the review sub-codex delegation flow. codex helped me generate this fix, otherwise review_does_not_emit_agent_message_on_structured_output fails
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, reasonable
Adds AgentMessageContentDelta, ReasoningContentDelta, ReasoningRawContentDelta item streaming events while maintaining compatibility for old events.