diff --git a/codex-rs/app-server-protocol/src/protocol/v2.rs b/codex-rs/app-server-protocol/src/protocol/v2.rs index 71d38a3dd..fd148b256 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2.rs @@ -1232,6 +1232,7 @@ pub struct TurnCompletedNotification { /// Notification that the turn-level unified diff has changed. /// Contains the latest aggregated diff across all file changes in the turn. pub struct TurnDiffUpdatedNotification { + pub thread_id: String, pub turn_id: String, pub diff: String, } @@ -1304,6 +1305,8 @@ pub struct ItemCompletedNotification { #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct AgentMessageDeltaNotification { + pub thread_id: String, + pub turn_id: String, pub item_id: String, pub delta: String, } @@ -1312,6 +1315,8 @@ pub struct AgentMessageDeltaNotification { #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ReasoningSummaryTextDeltaNotification { + pub thread_id: String, + pub turn_id: String, pub item_id: String, pub delta: String, pub summary_index: i64, @@ -1321,6 +1326,8 @@ pub struct ReasoningSummaryTextDeltaNotification { #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ReasoningSummaryPartAddedNotification { + pub thread_id: String, + pub turn_id: String, pub item_id: String, pub summary_index: i64, } @@ -1329,6 +1336,8 @@ pub struct ReasoningSummaryPartAddedNotification { #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct ReasoningTextDeltaNotification { + pub thread_id: String, + pub turn_id: String, pub item_id: String, pub delta: String, pub content_index: i64, @@ -1338,6 +1347,8 @@ pub struct ReasoningTextDeltaNotification { #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct CommandExecutionOutputDeltaNotification { + pub thread_id: String, + pub turn_id: String, pub item_id: String, pub delta: String, } @@ -1346,6 +1357,8 @@ pub struct CommandExecutionOutputDeltaNotification { #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] pub struct McpToolCallProgressNotification { + pub thread_id: String, + pub turn_id: String, pub item_id: String, pub message: String, } diff --git a/codex-rs/app-server/src/bespoke_event_handling.rs b/codex-rs/app-server/src/bespoke_event_handling.rs index a32a855b9..c34c7b281 100644 --- a/codex-rs/app-server/src/bespoke_event_handling.rs +++ b/codex-rs/app-server/src/bespoke_event_handling.rs @@ -260,6 +260,8 @@ pub(crate) async fn apply_bespoke_event_handling( } EventMsg::AgentMessageContentDelta(event) => { let notification = AgentMessageDeltaNotification { + thread_id: conversation_id.to_string(), + turn_id: event_turn_id.clone(), item_id: event.item_id, delta: event.delta, }; @@ -278,6 +280,8 @@ pub(crate) async fn apply_bespoke_event_handling( } EventMsg::ReasoningContentDelta(event) => { let notification = ReasoningSummaryTextDeltaNotification { + thread_id: conversation_id.to_string(), + turn_id: event_turn_id.clone(), item_id: event.item_id, delta: event.delta, summary_index: event.summary_index, @@ -290,6 +294,8 @@ pub(crate) async fn apply_bespoke_event_handling( } EventMsg::ReasoningRawContentDelta(event) => { let notification = ReasoningTextDeltaNotification { + thread_id: conversation_id.to_string(), + turn_id: event_turn_id.clone(), item_id: event.item_id, delta: event.delta, content_index: event.content_index, @@ -300,6 +306,8 @@ pub(crate) async fn apply_bespoke_event_handling( } EventMsg::AgentReasoningSectionBreak(event) => { let notification = ReasoningSummaryPartAddedNotification { + thread_id: conversation_id.to_string(), + turn_id: event_turn_id.clone(), item_id: event.item_id, summary_index: event.summary_index, }; @@ -494,6 +502,8 @@ pub(crate) async fn apply_bespoke_event_handling( } EventMsg::ExecCommandOutputDelta(exec_command_output_delta_event) => { let notification = CommandExecutionOutputDeltaNotification { + thread_id: conversation_id.to_string(), + turn_id: event_turn_id.clone(), item_id: exec_command_output_delta_event.call_id.clone(), delta: String::from_utf8_lossy(&exec_command_output_delta_event.chunk).to_string(), }; @@ -588,6 +598,7 @@ pub(crate) async fn apply_bespoke_event_handling( } EventMsg::TurnDiff(turn_diff_event) => { handle_turn_diff( + conversation_id, &event_turn_id, turn_diff_event, api_version, @@ -610,6 +621,7 @@ pub(crate) async fn apply_bespoke_event_handling( } async fn handle_turn_diff( + conversation_id: ConversationId, event_turn_id: &str, turn_diff_event: TurnDiffEvent, api_version: ApiVersion, @@ -617,6 +629,7 @@ async fn handle_turn_diff( ) { if let ApiVersion::V2 = api_version { let notification = TurnDiffUpdatedNotification { + thread_id: conversation_id.to_string(), turn_id: event_turn_id.to_string(), diff: turn_diff_event.unified_diff, }; @@ -1774,8 +1787,10 @@ mod tests { let (tx, mut rx) = mpsc::channel(CHANNEL_CAPACITY); let outgoing = OutgoingMessageSender::new(tx); let unified_diff = "--- a\n+++ b\n".to_string(); + let conversation_id = ConversationId::new(); handle_turn_diff( + conversation_id, "turn-1", TurnDiffEvent { unified_diff: unified_diff.clone(), @@ -1793,6 +1808,7 @@ mod tests { OutgoingMessage::AppServerNotification(ServerNotification::TurnDiffUpdated( notification, )) => { + assert_eq!(notification.thread_id, conversation_id.to_string()); assert_eq!(notification.turn_id, "turn-1"); assert_eq!(notification.diff, unified_diff); } @@ -1806,8 +1822,10 @@ mod tests { async fn test_handle_turn_diff_is_noop_for_v1() -> Result<()> { let (tx, mut rx) = mpsc::channel(CHANNEL_CAPACITY); let outgoing = OutgoingMessageSender::new(tx); + let conversation_id = ConversationId::new(); handle_turn_diff( + conversation_id, "turn-1", TurnDiffEvent { unified_diff: "diff".to_string(),