diff --git a/codex-rs/app-server-test-client/src/main.rs b/codex-rs/app-server-test-client/src/main.rs index 64577a5539b..283a01b2c3a 100644 --- a/codex-rs/app-server-test-client/src/main.rs +++ b/codex-rs/app-server-test-client/src/main.rs @@ -545,7 +545,7 @@ impl CodexClient { print!("{}", event.delta); std::io::stdout().flush().ok(); } - EventMsg::TaskComplete(event) => { + EventMsg::TurnComplete(event) => { println!("\n[task complete: {event:?}]"); break; } diff --git a/codex-rs/app-server/src/bespoke_event_handling.rs b/codex-rs/app-server/src/bespoke_event_handling.rs index d18a7878f47..0870191ec8f 100644 --- a/codex-rs/app-server/src/bespoke_event_handling.rs +++ b/codex-rs/app-server/src/bespoke_event_handling.rs @@ -106,7 +106,7 @@ pub(crate) async fn apply_bespoke_event_handling( msg, } = event; match msg { - EventMsg::TaskComplete(_ev) => { + EventMsg::TurnComplete(_ev) => { handle_turn_complete( conversation_id, event_turn_id, diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index 92a1a67f87b..125b3233130 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -3573,7 +3573,11 @@ impl CodexMessageProcessor { // JSON-serializing the `Event` as-is, but these should // be migrated to be variants of `ServerNotification` // instead. - let method = format!("codex/event/{}", event.msg); + let event_formatted = match &event.msg { + EventMsg::TurnStarted(_) => "task_started", + EventMsg::TurnComplete(_) => "task_complete", + _ => &event.msg.to_string(), + }; let mut params = match serde_json::to_value(event.clone()) { Ok(serde_json::Value::Object(map)) => map, Ok(_) => { @@ -3592,7 +3596,7 @@ impl CodexMessageProcessor { outgoing_for_task .send_notification(OutgoingNotification { - method, + method: format!("codex/event/{event_formatted}"), params: Some(params.into()), }) .await; diff --git a/codex-rs/app-server/tests/suite/codex_message_processor_flow.rs b/codex-rs/app-server/tests/suite/codex_message_processor_flow.rs index f902b11263f..456206af896 100644 --- a/codex-rs/app-server/tests/suite/codex_message_processor_flow.rs +++ b/codex-rs/app-server/tests/suite/codex_message_processor_flow.rs @@ -283,7 +283,7 @@ async fn test_send_user_turn_changes_approval_policy_behavior() -> Result<()> { ) .await?; - // Wait for first TaskComplete + // Wait for first TurnComplete let _ = timeout( DEFAULT_READ_TIMEOUT, mcp.read_stream_until_notification_message("codex/event/task_complete"), diff --git a/codex-rs/core/src/agent/control.rs b/codex-rs/core/src/agent/control.rs index 201bb4e0ff6..22b6ae343b6 100644 --- a/codex-rs/core/src/agent/control.rs +++ b/codex-rs/core/src/agent/control.rs @@ -116,10 +116,10 @@ mod tests { use super::*; use crate::agent::agent_status_from_event; use codex_protocol::protocol::ErrorEvent; - use codex_protocol::protocol::TaskCompleteEvent; - use codex_protocol::protocol::TaskStartedEvent; use codex_protocol::protocol::TurnAbortReason; use codex_protocol::protocol::TurnAbortedEvent; + use codex_protocol::protocol::TurnCompleteEvent; + use codex_protocol::protocol::TurnStartedEvent; use pretty_assertions::assert_eq; #[tokio::test] @@ -144,7 +144,7 @@ mod tests { #[tokio::test] async fn on_event_updates_status_from_task_started() { - let status = agent_status_from_event(&EventMsg::TaskStarted(TaskStartedEvent { + let status = agent_status_from_event(&EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, })); assert_eq!(status, Some(AgentStatus::Running)); @@ -152,7 +152,7 @@ mod tests { #[tokio::test] async fn on_event_updates_status_from_task_complete() { - let status = agent_status_from_event(&EventMsg::TaskComplete(TaskCompleteEvent { + let status = agent_status_from_event(&EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message: Some("done".to_string()), })); let expected = AgentStatus::Completed(Some("done".to_string())); diff --git a/codex-rs/core/src/agent/status.rs b/codex-rs/core/src/agent/status.rs index f5345a29105..4f99e99aae1 100644 --- a/codex-rs/core/src/agent/status.rs +++ b/codex-rs/core/src/agent/status.rs @@ -5,8 +5,8 @@ use codex_protocol::protocol::EventMsg; /// Returns `None` when the event does not affect status tracking. pub(crate) fn agent_status_from_event(msg: &EventMsg) -> Option { match msg { - EventMsg::TaskStarted(_) => Some(AgentStatus::Running), - EventMsg::TaskComplete(ev) => Some(AgentStatus::Completed(ev.last_agent_message.clone())), + EventMsg::TurnStarted(_) => Some(AgentStatus::Running), + EventMsg::TurnComplete(ev) => Some(AgentStatus::Completed(ev.last_agent_message.clone())), EventMsg::TurnAborted(ev) => Some(AgentStatus::Errored(format!("{:?}", ev.reason))), EventMsg::Error(ev) => Some(AgentStatus::Errored(ev.message.clone())), EventMsg::ShutdownComplete => Some(AgentStatus::Shutdown), diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 96e90c5cfa6..923cd621a7b 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -44,9 +44,9 @@ use codex_protocol::protocol::RawResponseItemEvent; use codex_protocol::protocol::ReviewRequest; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::SessionSource; -use codex_protocol::protocol::TaskStartedEvent; use codex_protocol::protocol::TurnAbortReason; use codex_protocol::protocol::TurnContextItem; +use codex_protocol::protocol::TurnStartedEvent; use codex_rmcp_client::ElicitationResponse; use futures::future::BoxFuture; use futures::prelude::*; @@ -2324,9 +2324,9 @@ fn errors_to_info(errors: &[SkillError]) -> Vec { /// - If the model requests a function call, we execute it and send the output /// back to the model in the next turn. /// - If the model sends only an assistant message, we record it in the -/// conversation history and consider the task complete. +/// conversation history and consider the turn complete. /// -pub(crate) async fn run_task( +pub(crate) async fn run_turn( sess: Arc, turn_context: Arc, input: Vec, @@ -2342,7 +2342,7 @@ pub(crate) async fn run_task( if total_usage_tokens >= auto_compact_limit { run_auto_compact(&sess, &turn_context).await; } - let event = EventMsg::TaskStarted(TaskStartedEvent { + let event = EventMsg::TurnStarted(TurnStartedEvent { model_context_window: turn_context.client.get_model_context_window(), }); sess.send_event(&turn_context, event).await; @@ -2407,7 +2407,7 @@ pub(crate) async fn run_task( }) .map(|user_message| user_message.message()) .collect::>(); - match run_turn( + match run_model_turn( Arc::clone(&sess), Arc::clone(&turn_context), Arc::clone(&turn_diff_tracker), @@ -2484,7 +2484,7 @@ async fn run_auto_compact(sess: &Arc, turn_context: &Arc) cwd = %turn_context.cwd.display() ) )] -async fn run_turn( +async fn run_model_turn( sess: Arc, turn_context: Arc, turn_diff_tracker: SharedTurnDiffTracker, diff --git a/codex-rs/core/src/codex_delegate.rs b/codex-rs/core/src/codex_delegate.rs index 72c2911bfe8..869c18d555a 100644 --- a/codex-rs/core/src/codex_delegate.rs +++ b/codex-rs/core/src/codex_delegate.rs @@ -135,7 +135,7 @@ pub(crate) async fn run_codex_thread_one_shot( while let Ok(event) = io_for_bridge.next_event().await { let should_shutdown = matches!( event.msg, - EventMsg::TaskComplete(_) | EventMsg::TurnAborted(_) + EventMsg::TurnComplete(_) | EventMsg::TurnAborted(_) ); let _ = tx_bridge.send(event).await; if should_shutdown { @@ -253,7 +253,7 @@ async fn shutdown_delegate(codex: &Codex) { while let Ok(event) = codex.next_event().await { if matches!( event.msg, - EventMsg::TurnAborted(_) | EventMsg::TaskComplete(_) + EventMsg::TurnAborted(_) | EventMsg::TurnComplete(_) ) { break; } diff --git a/codex-rs/core/src/compact.rs b/codex-rs/core/src/compact.rs index a452e3e67ee..c8509cc5c54 100644 --- a/codex-rs/core/src/compact.rs +++ b/codex-rs/core/src/compact.rs @@ -12,8 +12,8 @@ use crate::features::Feature; use crate::protocol::CompactedItem; use crate::protocol::ContextCompactedEvent; use crate::protocol::EventMsg; -use crate::protocol::TaskStartedEvent; use crate::protocol::TurnContextItem; +use crate::protocol::TurnStartedEvent; use crate::protocol::WarningEvent; use crate::truncate::TruncationPolicy; use crate::truncate::approx_token_count; @@ -54,7 +54,7 @@ pub(crate) async fn run_compact_task( turn_context: Arc, input: Vec, ) { - let start_event = EventMsg::TaskStarted(TaskStartedEvent { + let start_event = EventMsg::TurnStarted(TurnStartedEvent { model_context_window: turn_context.client.get_model_context_window(), }); sess.send_event(&turn_context, start_event).await; diff --git a/codex-rs/core/src/compact_remote.rs b/codex-rs/core/src/compact_remote.rs index 694dcd25428..dd038c52871 100644 --- a/codex-rs/core/src/compact_remote.rs +++ b/codex-rs/core/src/compact_remote.rs @@ -8,7 +8,7 @@ use crate::protocol::CompactedItem; use crate::protocol::ContextCompactedEvent; use crate::protocol::EventMsg; use crate::protocol::RolloutItem; -use crate::protocol::TaskStartedEvent; +use crate::protocol::TurnStartedEvent; use codex_protocol::models::ResponseItem; pub(crate) async fn run_inline_remote_auto_compact_task( @@ -19,7 +19,7 @@ pub(crate) async fn run_inline_remote_auto_compact_task( } pub(crate) async fn run_remote_compact_task(sess: Arc, turn_context: Arc) { - let start_event = EventMsg::TaskStarted(TaskStartedEvent { + let start_event = EventMsg::TurnStarted(TurnStartedEvent { model_context_window: turn_context.client.get_model_context_window(), }); sess.send_event(&turn_context, start_event).await; diff --git a/codex-rs/core/src/rollout/policy.rs b/codex-rs/core/src/rollout/policy.rs index 6c02ad09425..224e45dc525 100644 --- a/codex-rs/core/src/rollout/policy.rs +++ b/codex-rs/core/src/rollout/policy.rs @@ -50,8 +50,8 @@ pub(crate) fn should_persist_event_msg(ev: &EventMsg) -> bool { | EventMsg::TurnAborted(_) => true, EventMsg::Error(_) | EventMsg::Warning(_) - | EventMsg::TaskStarted(_) - | EventMsg::TaskComplete(_) + | EventMsg::TurnStarted(_) + | EventMsg::TurnComplete(_) | EventMsg::AgentMessageDelta(_) | EventMsg::AgentReasoningDelta(_) | EventMsg::AgentReasoningRawContentDelta(_) diff --git a/codex-rs/core/src/tasks/mod.rs b/codex-rs/core/src/tasks/mod.rs index a817d51cd6e..d6754c23c8a 100644 --- a/codex-rs/core/src/tasks/mod.rs +++ b/codex-rs/core/src/tasks/mod.rs @@ -21,9 +21,9 @@ use crate::codex::Session; use crate::codex::TurnContext; use crate::models_manager::manager::ModelsManager; use crate::protocol::EventMsg; -use crate::protocol::TaskCompleteEvent; use crate::protocol::TurnAbortReason; use crate::protocol::TurnAbortedEvent; +use crate::protocol::TurnCompleteEvent; use crate::state::ActiveTurn; use crate::state::RunningTask; use crate::state::TaskKind; @@ -180,7 +180,7 @@ impl Session { if should_close_processes { self.close_unified_exec_processes().await; } - let event = EventMsg::TaskComplete(TaskCompleteEvent { last_agent_message }); + let event = EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message }); self.send_event(turn_context.as_ref(), event).await; } diff --git a/codex-rs/core/src/tasks/regular.rs b/codex-rs/core/src/tasks/regular.rs index 56c46ffbc9a..69d2d960ac1 100644 --- a/codex-rs/core/src/tasks/regular.rs +++ b/codex-rs/core/src/tasks/regular.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use crate::codex::TurnContext; -use crate::codex::run_task; +use crate::codex::run_turn; use crate::state::TaskKind; use async_trait::async_trait; use codex_protocol::user_input::UserInput; @@ -29,10 +29,10 @@ impl SessionTask for RegularTask { cancellation_token: CancellationToken, ) -> Option { let sess = session.clone_session(); - let run_task_span = - trace_span!(parent: sess.services.otel_manager.current_span(), "run_task"); - run_task(sess, ctx, input, cancellation_token) - .instrument(run_task_span) + let run_turn_span = + trace_span!(parent: sess.services.otel_manager.current_span(), "run_turn"); + run_turn(sess, ctx, input, cancellation_token) + .instrument(run_turn_span) .await } } diff --git a/codex-rs/core/src/tasks/review.rs b/codex-rs/core/src/tasks/review.rs index 6a54f27d691..61cc81d0b8d 100644 --- a/codex-rs/core/src/tasks/review.rs +++ b/codex-rs/core/src/tasks/review.rs @@ -134,7 +134,7 @@ async fn process_review_events( }) | EventMsg::AgentMessageDelta(AgentMessageDeltaEvent { .. }) | EventMsg::AgentMessageContentDelta(AgentMessageContentDeltaEvent { .. }) => {} - EventMsg::TaskComplete(task_complete) => { + EventMsg::TurnComplete(task_complete) => { // Parse review output from the last agent message (if present). let out = task_complete .last_agent_message @@ -154,7 +154,7 @@ async fn process_review_events( } } } - // Channel closed without TaskComplete: treat as interrupted. + // Channel closed without TurnComplete: treat as interrupted. None } diff --git a/codex-rs/core/src/tasks/user_shell.rs b/codex-rs/core/src/tasks/user_shell.rs index e76f70253ec..2b7ae53d0c3 100644 --- a/codex-rs/core/src/tasks/user_shell.rs +++ b/codex-rs/core/src/tasks/user_shell.rs @@ -22,7 +22,7 @@ use crate::protocol::ExecCommandBeginEvent; use crate::protocol::ExecCommandEndEvent; use crate::protocol::ExecCommandSource; use crate::protocol::SandboxPolicy; -use crate::protocol::TaskStartedEvent; +use crate::protocol::TurnStartedEvent; use crate::sandboxing::ExecEnv; use crate::sandboxing::SandboxPermissions; use crate::state::TaskKind; @@ -64,7 +64,7 @@ impl SessionTask for UserShellCommandTask { .otel_manager .counter("codex.task.user_shell", 1, &[]); - let event = EventMsg::TaskStarted(TaskStartedEvent { + let event = EventMsg::TurnStarted(TurnStartedEvent { model_context_window: turn_context.client.get_model_context_window(), }); let session = session.clone_session(); diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index d0b37f2d615..7aaa096c395 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -265,7 +265,7 @@ impl TestCodex { .await?; wait_for_event(&self.codex, |event| { - matches!(event, EventMsg::TaskComplete(_)) + matches!(event, EventMsg::TurnComplete(_)) }) .await; Ok(()) diff --git a/codex-rs/core/tests/suite/abort_tasks.rs b/codex-rs/core/tests/suite/abort_tasks.rs index 53d32e140d0..094c10c7786 100644 --- a/codex-rs/core/tests/suite/abort_tasks.rs +++ b/codex-rs/core/tests/suite/abort_tasks.rs @@ -124,7 +124,7 @@ async fn interrupt_tool_records_history_entries() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let requests = response_mock.requests(); assert!( diff --git a/codex-rs/core/tests/suite/apply_patch_cli.rs b/codex-rs/core/tests/suite/apply_patch_cli.rs index 1f99c846afd..f4515a9631e 100644 --- a/codex-rs/core/tests/suite/apply_patch_cli.rs +++ b/codex-rs/core/tests/suite/apply_patch_cli.rs @@ -319,7 +319,7 @@ async fn apply_patch_cli_move_without_content_change_has_no_turn_diff( saw_turn_diff = true; false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -917,7 +917,7 @@ async fn apply_patch_shell_command_heredoc_with_cd_emits_turn_diff() -> Result<( saw_turn_diff = Some(ev.unified_diff.clone()); false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -982,7 +982,7 @@ async fn apply_patch_shell_command_failure_propagates_error_and_skips_diff() -> saw_turn_diff = true; false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -1129,7 +1129,7 @@ async fn apply_patch_emits_turn_diff_event_with_unified_diff( saw_turn_diff = Some(ev.unified_diff.clone()); false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -1189,7 +1189,7 @@ async fn apply_patch_turn_diff_for_rename_with_content_change( last_diff = Some(ev.unified_diff.clone()); false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -1257,7 +1257,7 @@ async fn apply_patch_aggregates_diff_across_multiple_tool_calls() -> Result<()> last_diff = Some(ev.unified_diff.clone()); false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -1325,7 +1325,7 @@ async fn apply_patch_aggregates_diff_preserves_success_after_failure() -> Result last_diff = Some(ev.unified_diff.clone()); false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; diff --git a/codex-rs/core/tests/suite/approvals.rs b/codex-rs/core/tests/suite/approvals.rs index ff8eca6f997..51f1c31f17b 100644 --- a/codex-rs/core/tests/suite/approvals.rs +++ b/codex-rs/core/tests/suite/approvals.rs @@ -553,7 +553,7 @@ async fn expect_exec_approval( let event = wait_for_event(&test.codex, |event| { matches!( event, - EventMsg::ExecApprovalRequest(_) | EventMsg::TaskComplete(_) + EventMsg::ExecApprovalRequest(_) | EventMsg::TurnComplete(_) ) }) .await; @@ -568,7 +568,7 @@ async fn expect_exec_approval( assert_eq!(last_arg, expected_command); approval } - EventMsg::TaskComplete(_) => panic!("expected approval request before completion"), + EventMsg::TurnComplete(_) => panic!("expected approval request before completion"), other => panic!("unexpected event: {other:?}"), } } @@ -580,7 +580,7 @@ async fn expect_patch_approval( let event = wait_for_event(&test.codex, |event| { matches!( event, - EventMsg::ApplyPatchApprovalRequest(_) | EventMsg::TaskComplete(_) + EventMsg::ApplyPatchApprovalRequest(_) | EventMsg::TurnComplete(_) ) }) .await; @@ -590,7 +590,7 @@ async fn expect_patch_approval( assert_eq!(approval.call_id, expected_call_id); approval } - EventMsg::TaskComplete(_) => panic!("expected patch approval request before completion"), + EventMsg::TurnComplete(_) => panic!("expected patch approval request before completion"), other => panic!("unexpected event: {other:?}"), } } @@ -599,13 +599,13 @@ async fn wait_for_completion_without_approval(test: &TestCodex) { let event = wait_for_event(&test.codex, |event| { matches!( event, - EventMsg::ExecApprovalRequest(_) | EventMsg::TaskComplete(_) + EventMsg::ExecApprovalRequest(_) | EventMsg::TurnComplete(_) ) }) .await; match event { - EventMsg::TaskComplete(_) => {} + EventMsg::TurnComplete(_) => {} EventMsg::ExecApprovalRequest(event) => { panic!("unexpected approval request: {:?}", event.command) } @@ -615,7 +615,7 @@ async fn wait_for_completion_without_approval(test: &TestCodex) { async fn wait_for_completion(test: &TestCodex) { wait_for_event(&test.codex, |event| { - matches!(event, EventMsg::TaskComplete(_)) + matches!(event, EventMsg::TurnComplete(_)) }) .await; } @@ -1660,12 +1660,12 @@ async fn approving_apply_patch_for_session_skips_future_prompts_for_same_file() let event = wait_for_event(&test.codex, |event| { matches!( event, - EventMsg::ApplyPatchApprovalRequest(_) | EventMsg::TaskComplete(_) + EventMsg::ApplyPatchApprovalRequest(_) | EventMsg::TurnComplete(_) ) }) .await; match event { - EventMsg::TaskComplete(_) => {} + EventMsg::TurnComplete(_) => {} EventMsg::ApplyPatchApprovalRequest(event) => { panic!("unexpected patch approval request: {:?}", event.call_id) } diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index 5a5205966bc..06846c46aba 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -294,7 +294,7 @@ async fn resume_includes_initial_messages_and_sends_prior_items() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -362,7 +362,7 @@ async fn includes_conversation_id_and_model_headers_in_request() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); assert_eq!(request.path(), "/v1/responses"); @@ -417,7 +417,7 @@ async fn includes_base_instructions_override_in_request() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -473,7 +473,7 @@ async fn chatgpt_auth_sends_correct_request() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); assert_eq!(request.path(), "/api/codex/responses"); @@ -566,7 +566,7 @@ async fn prefers_apikey_when_config_prefers_apikey_even_with_chatgpt_tokens() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -607,7 +607,7 @@ async fn includes_user_instructions_message_in_request() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -677,7 +677,7 @@ async fn skills_append_to_instructions() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -727,7 +727,7 @@ async fn includes_configured_effort_in_request() -> anyhow::Result<()> { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -764,7 +764,7 @@ async fn includes_no_effort_in_request() -> anyhow::Result<()> { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -799,7 +799,7 @@ async fn includes_default_reasoning_effort_in_request_when_defined_by_model_info .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -838,7 +838,7 @@ async fn configured_reasoning_summary_is_sent() -> anyhow::Result<()> { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -877,7 +877,7 @@ async fn reasoning_summary_is_omitted_when_disabled() -> anyhow::Result<()> { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -910,7 +910,7 @@ async fn includes_default_verbosity_in_request() -> anyhow::Result<()> { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -950,7 +950,7 @@ async fn configured_verbosity_not_sent_for_models_without_support() -> anyhow::R .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -989,7 +989,7 @@ async fn configured_verbosity_is_sent() -> anyhow::Result<()> { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -1044,7 +1044,7 @@ async fn includes_developer_instructions_message_in_request() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = resp_mock.single_request(); let request_body = request.body_json(); @@ -1381,7 +1381,7 @@ async fn token_count_includes_rate_limits_snapshot() { Some(1704069000) ); - wait_for_event(&codex, |msg| matches!(msg, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |msg| matches!(msg, EventMsg::TurnComplete(_))).await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -1509,7 +1509,7 @@ async fn context_window_error_sets_total_tokens_to_model_window() -> anyhow::Res }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -1556,7 +1556,7 @@ async fn context_window_error_sets_total_tokens_to_model_window() -> anyhow::Res "expected context window error; got {error_event:?}" ); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; Ok(()) } @@ -1641,7 +1641,7 @@ async fn azure_overrides_assign_properties_used_for_responses_url() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -1724,7 +1724,7 @@ async fn env_var_overrides_loaded_auth() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; } fn create_dummy_codex_auth() -> CodexAuth { @@ -1795,7 +1795,7 @@ async fn history_dedupes_streamed_and_final_messages_across_turns() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Turn 2: user sends U2; wait for completion. codex @@ -1805,7 +1805,7 @@ async fn history_dedupes_streamed_and_final_messages_across_turns() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Turn 3: user sends U3; wait for completion. codex @@ -1815,7 +1815,7 @@ async fn history_dedupes_streamed_and_final_messages_across_turns() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Inspect the three captured requests. let requests = request_log.requests(); diff --git a/codex-rs/core/tests/suite/codex_delegate.rs b/codex-rs/core/tests/suite/codex_delegate.rs index b5cd4186a45..c524234c803 100644 --- a/codex-rs/core/tests/suite/codex_delegate.rs +++ b/codex-rs/core/tests/suite/codex_delegate.rs @@ -80,7 +80,7 @@ async fn codex_delegate_forwards_exec_approval_and_proceeds_on_approval() { .await .expect("submit review"); - // Lifecycle: Entered -> ExecApprovalRequest -> Exited(Some) -> TaskComplete. + // Lifecycle: Entered -> ExecApprovalRequest -> Exited(Some) -> TurnComplete. wait_for_event(&test.codex, |ev| { matches!(ev, EventMsg::EnteredReviewMode(_)) }) @@ -105,7 +105,7 @@ async fn codex_delegate_forwards_exec_approval_and_proceeds_on_approval() { matches!(ev, EventMsg::ExitedReviewMode(_)) }) .await; - wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; } /// Delegate should surface ApplyPatchApprovalRequest and honor parent decision @@ -179,7 +179,7 @@ async fn codex_delegate_forwards_patch_approval_and_proceeds_on_decision() { matches!(ev, EventMsg::ExitedReviewMode(_)) }) .await; - wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -221,7 +221,7 @@ async fn codex_delegate_ignores_legacy_deltas() { match ev { EventMsg::ReasoningContentDelta(_) => reasoning_delta_count += 1, EventMsg::AgentReasoningDelta(_) => legacy_reasoning_delta_count += 1, - EventMsg::TaskComplete(_) => break, + EventMsg::TurnComplete(_) => break, _ => {} } } diff --git a/codex-rs/core/tests/suite/compact.rs b/codex-rs/core/tests/suite/compact.rs index 9e678a4c3b6..ee583997086 100644 --- a/codex-rs/core/tests/suite/compact.rs +++ b/codex-rs/core/tests/suite/compact.rs @@ -164,7 +164,7 @@ async fn summarize_context_three_requests_and_instructions() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // 2) Summarize – second hit should include the summarization prompt. codex.submit(Op::Compact).await.unwrap(); @@ -173,7 +173,7 @@ async fn summarize_context_three_requests_and_instructions() { panic!("expected warning event after compact"); }; assert_eq!(message, COMPACT_WARNING_MESSAGE); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // 3) Next user input – third hit; history should include only the summary. codex @@ -185,7 +185,7 @@ async fn summarize_context_three_requests_and_instructions() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Inspect the three captured requests. let requests = request_log.requests(); @@ -355,7 +355,7 @@ async fn manual_compact_uses_custom_prompt() { panic!("expected warning event after compact"); }; assert_eq!(message, COMPACT_WARNING_MESSAGE); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let body = response_mock.single_request().body_json(); @@ -445,7 +445,7 @@ async fn manual_compact_emits_api_and_local_token_usage_events() { .await; // Ensure the compact task itself completes. - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; assert_eq!( first, 0, @@ -578,7 +578,7 @@ async fn multiple_auto_compact_per_task_runs_after_token_limit_hit() { }) .await .expect("submit user input"); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // collect the requests payloads from the model let requests_payloads = request_log.requests(); @@ -1049,7 +1049,7 @@ async fn auto_compact_runs_after_token_limit_hit() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -1061,7 +1061,7 @@ async fn auto_compact_runs_after_token_limit_hit() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -1073,7 +1073,7 @@ async fn auto_compact_runs_after_token_limit_hit() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); let request_bodies: Vec = requests @@ -1284,7 +1284,7 @@ async fn auto_compact_runs_after_resume_when_token_usage_is_over_limit() { }) .await; wait_for_event(&resumed.codex, |event| { - matches!(event, EventMsg::TaskComplete(_)) + matches!(event, EventMsg::TurnComplete(_)) }) .await; @@ -1381,7 +1381,7 @@ async fn auto_compact_persists_rollout_entries() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -1392,7 +1392,7 @@ async fn auto_compact_persists_rollout_entries() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -1403,7 +1403,7 @@ async fn auto_compact_persists_rollout_entries() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex.submit(Op::Shutdown).await.unwrap(); wait_for_event(&codex, |ev| matches!(ev, EventMsg::ShutdownComplete)).await; @@ -1495,7 +1495,7 @@ async fn manual_compact_retries_after_context_window_error() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex.submit(Op::Compact).await.unwrap(); let EventMsg::BackgroundEvent(event) = @@ -1513,7 +1513,7 @@ async fn manual_compact_retries_after_context_window_error() { panic!("expected warning event after compact retry"); }; assert_eq!(message, COMPACT_WARNING_MESSAGE); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert_eq!( @@ -1628,10 +1628,10 @@ async fn manual_compact_twice_preserves_latest_user_messages() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex.submit(Op::Compact).await.unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -1642,10 +1642,10 @@ async fn manual_compact_twice_preserves_latest_user_messages() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex.submit(Op::Compact).await.unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -1656,7 +1656,7 @@ async fn manual_compact_twice_preserves_latest_user_messages() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let requests = responses_mock.requests(); assert_eq!( @@ -1838,13 +1838,13 @@ async fn auto_compact_allows_multiple_attempts_when_interleaved_with_other_turn_ if event.id.starts_with("auto-compact-") && matches!( event.msg, - EventMsg::TaskStarted(_) | EventMsg::TaskComplete(_) + EventMsg::TurnStarted(_) | EventMsg::TurnComplete(_) ) { auto_compact_lifecycle_events.push(event); continue; } - if let EventMsg::TaskComplete(_) = &event.msg + if let EventMsg::TurnComplete(_) = &event.msg && !event.id.starts_with("auto-compact-") { break; @@ -1946,7 +1946,7 @@ async fn auto_compact_triggers_after_function_call_over_95_percent_usage() { .await .unwrap(); - wait_for_event(&codex, |msg| matches!(msg, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |msg| matches!(msg, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -1958,7 +1958,7 @@ async fn auto_compact_triggers_after_function_call_over_95_percent_usage() { .await .unwrap(); - wait_for_event(&codex, |msg| matches!(msg, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |msg| matches!(msg, EventMsg::TurnComplete(_))).await; // Assert first request captured expected user message that triggers function call. let first_request = first_turn_mock.single_request().input(); @@ -2072,7 +2072,7 @@ async fn auto_compact_counts_encrypted_reasoning_before_last_user() { }) .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; if idx < 2 { assert!( diff --git a/codex-rs/core/tests/suite/compact_remote.rs b/codex-rs/core/tests/suite/compact_remote.rs index 5a2fb54530e..1c598a9ab6e 100644 --- a/codex-rs/core/tests/suite/compact_remote.rs +++ b/codex-rs/core/tests/suite/compact_remote.rs @@ -77,10 +77,10 @@ async fn remote_compact_replaces_history_for_followups() -> Result<()> { final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex.submit(Op::Compact).await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -90,7 +90,7 @@ async fn remote_compact_replaces_history_for_followups() -> Result<()> { final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let compact_request = compact_mock.single_request(); assert_eq!(compact_request.path(), "/v1/responses/compact"); @@ -201,7 +201,7 @@ async fn remote_compact_runs_automatically() -> Result<()> { _ => None, }) .await; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; assert!(message); assert_eq!(compact_mock.requests().len(), 1); @@ -269,10 +269,10 @@ async fn remote_compact_persists_replacement_history_in_rollout() -> Result<()> final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex.submit(Op::Compact).await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex.submit(Op::Shutdown).await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::ShutdownComplete)).await; diff --git a/codex-rs/core/tests/suite/compact_resume_fork.rs b/codex-rs/core/tests/suite/compact_resume_fork.rs index 51b3eb94246..ad2e0e65ad6 100644 --- a/codex-rs/core/tests/suite/compact_resume_fork.rs +++ b/codex-rs/core/tests/suite/compact_resume_fork.rs @@ -896,7 +896,7 @@ async fn user_turn(conversation: &Arc, text: &str) { }) .await .expect("submit user turn"); - wait_for_event(conversation, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(conversation, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; } async fn compact_conversation(conversation: &Arc) { @@ -909,7 +909,7 @@ async fn compact_conversation(conversation: &Arc) { panic!("expected warning event after compact"); }; assert_eq!(message, COMPACT_WARNING_MESSAGE); - wait_for_event(conversation, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(conversation, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; } async fn fetch_conversation_path(conversation: &Arc) -> std::path::PathBuf { diff --git a/codex-rs/core/tests/suite/exec_policy.rs b/codex-rs/core/tests/suite/exec_policy.rs index c31df5036f4..48471e45798 100644 --- a/codex-rs/core/tests/suite/exec_policy.rs +++ b/codex-rs/core/tests/suite/exec_policy.rs @@ -91,7 +91,7 @@ async fn execpolicy_blocks_shell_invocation() -> Result<()> { unreachable!() }; wait_for_event(&test.codex, |event| { - matches!(event, EventMsg::TaskComplete(_)) + matches!(event, EventMsg::TurnComplete(_)) }) .await; diff --git a/codex-rs/core/tests/suite/fork_thread.rs b/codex-rs/core/tests/suite/fork_thread.rs index b0b3f722620..98f1dafd5b1 100644 --- a/codex-rs/core/tests/suite/fork_thread.rs +++ b/codex-rs/core/tests/suite/fork_thread.rs @@ -75,7 +75,7 @@ async fn fork_thread_twice_drops_to_first_message() { }) .await .unwrap(); - let _ = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _ = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; } // Request history from the base conversation to obtain rollout path. diff --git a/codex-rs/core/tests/suite/models_etag_responses.rs b/codex-rs/core/tests/suite/models_etag_responses.rs index 24f0655cecb..a733800cb00 100644 --- a/codex-rs/core/tests/suite/models_etag_responses.rs +++ b/codex-rs/core/tests/suite/models_etag_responses.rs @@ -111,7 +111,7 @@ async fn refresh_models_on_models_etag_mismatch_and_avoid_duplicate_models_fetch }) .await?; - let _ = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _ = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Assert /models was refreshed exactly once after the X-Models-Etag mismatch. assert_eq!(refresh_models_mock.requests().len(), 1); diff --git a/codex-rs/core/tests/suite/otel.rs b/codex-rs/core/tests/suite/otel.rs index 4fa45f01087..ed7c8fb04fc 100644 --- a/codex-rs/core/tests/suite/otel.rs +++ b/codex-rs/core/tests/suite/otel.rs @@ -51,7 +51,7 @@ async fn responses_api_emits_api_request_event() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(|lines: &[&str]| { lines @@ -93,7 +93,7 @@ async fn process_sse_emits_tracing_for_output_item() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(|lines: &[&str]| { lines @@ -132,7 +132,7 @@ async fn process_sse_emits_failed_event_on_parse_error() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(|lines: &[&str]| { lines @@ -172,7 +172,7 @@ async fn process_sse_records_failed_event_when_stream_closes_without_completed() .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(|lines: &[&str]| { lines @@ -232,7 +232,7 @@ async fn process_sse_failed_event_records_response_error_message() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(|lines: &[&str]| { lines @@ -290,7 +290,7 @@ async fn process_sse_failed_event_logs_parse_error() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(|lines: &[&str]| { lines @@ -335,7 +335,7 @@ async fn process_sse_failed_event_logs_missing_error() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(|lines: &[&str]| { lines @@ -389,7 +389,7 @@ async fn process_sse_failed_event_logs_response_completed_parse_error() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(|lines: &[&str]| { lines @@ -440,7 +440,7 @@ async fn process_sse_emits_completed_telemetry() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(|lines: &[&str]| { lines @@ -508,7 +508,7 @@ async fn handle_responses_span_records_response_kind_and_tool_name() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let logs = String::from_utf8(buffer.lock().unwrap().clone()).unwrap(); @@ -573,7 +573,7 @@ async fn record_responses_sets_span_fields_for_response_events() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let logs = String::from_utf8(buffer.lock().unwrap().clone()).unwrap(); @@ -966,7 +966,7 @@ async fn handle_container_exec_autoapprove_from_config_records_tool_decision() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; logs_assert(tool_decision_assertion( "auto_config_call", diff --git a/codex-rs/core/tests/suite/prompt_caching.rs b/codex-rs/core/tests/suite/prompt_caching.rs index 9622332cadf..160b623c6b7 100644 --- a/codex-rs/core/tests/suite/prompt_caching.rs +++ b/codex-rs/core/tests/suite/prompt_caching.rs @@ -106,7 +106,7 @@ async fn prompt_tools_are_consistent_across_requests() -> anyhow::Result<()> { final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -116,7 +116,7 @@ async fn prompt_tools_are_consistent_across_requests() -> anyhow::Result<()> { final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let expected_tools_names = vec![ "shell_command", @@ -178,7 +178,7 @@ async fn codex_mini_latest_tools() -> anyhow::Result<()> { }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { items: vec![UserInput::Text { @@ -188,7 +188,7 @@ async fn codex_mini_latest_tools() -> anyhow::Result<()> { }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let expected_instructions = [BASE_INSTRUCTIONS, APPLY_PATCH_TOOL_INSTRUCTIONS].join("\n"); @@ -238,7 +238,7 @@ async fn prefixes_context_and_instructions_once_and_consistently_across_requests final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserInput { @@ -248,7 +248,7 @@ async fn prefixes_context_and_instructions_once_and_consistently_across_requests final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let body1 = req1.single_request().body_json(); let input1 = body1["input"].as_array().expect("input array"); @@ -309,7 +309,7 @@ async fn overrides_turn_context_but_keeps_cached_prefix_and_key_constant() -> an final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let writable = TempDir::new().unwrap(); codex @@ -337,7 +337,7 @@ async fn overrides_turn_context_but_keeps_cached_prefix_and_key_constant() -> an final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let body1 = req1.single_request().body_json(); let body2 = req2.single_request().body_json(); @@ -417,7 +417,7 @@ async fn override_before_first_turn_emits_environment_context() -> anyhow::Resul }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let body = req.single_request().body_json(); let input = body["input"] @@ -509,7 +509,7 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Second turn using per-turn overrides via UserTurn let new_cwd = TempDir::new().unwrap(); @@ -533,7 +533,7 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let body1 = req1.single_request().body_json(); let body2 = req2.single_request().body_json(); @@ -627,7 +627,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserTurn { @@ -643,7 +643,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let body1 = req1.single_request().body_json(); let body2 = req2.single_request().body_json(); @@ -717,7 +717,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex .submit(Op::UserTurn { @@ -733,7 +733,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let body1 = req1.single_request().body_json(); let body2 = req2.single_request().body_json(); diff --git a/codex-rs/core/tests/suite/quota_exceeded.rs b/codex-rs/core/tests/suite/quota_exceeded.rs index e7ccd538478..17fc50614fe 100644 --- a/codex-rs/core/tests/suite/quota_exceeded.rs +++ b/codex-rs/core/tests/suite/quota_exceeded.rs @@ -62,7 +62,7 @@ async fn quota_exceeded_emits_single_error_event() -> Result<()> { "Quota exceeded. Check your plan and billing details." ); } - EventMsg::TaskComplete(_) => break, + EventMsg::TurnComplete(_) => break, _ => {} } } diff --git a/codex-rs/core/tests/suite/remote_models.rs b/codex-rs/core/tests/suite/remote_models.rs index 6dfdc4467aa..1085fe3b892 100644 --- a/codex-rs/core/tests/suite/remote_models.rs +++ b/codex-rs/core/tests/suite/remote_models.rs @@ -184,7 +184,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> { assert_eq!(begin_event.source, ExecCommandSource::UnifiedExecStartup); - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; Ok(()) } @@ -378,7 +378,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let body = response_mock.single_request().body_json(); let instructions = body["instructions"].as_str().unwrap(); diff --git a/codex-rs/core/tests/suite/request_compression.rs b/codex-rs/core/tests/suite/request_compression.rs index 36f7c7dd86d..50e3fd92107 100644 --- a/codex-rs/core/tests/suite/request_compression.rs +++ b/codex-rs/core/tests/suite/request_compression.rs @@ -45,7 +45,7 @@ async fn request_body_is_zstd_compressed_for_codex_backend_when_enabled() -> any .await?; // Wait until the task completes so the request definitely hit the server. - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = request_log.single_request(); assert_eq!(request.header("content-encoding").as_deref(), Some("zstd")); @@ -87,7 +87,7 @@ async fn request_body_is_not_compressed_for_api_key_auth_even_when_enabled() -> }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let request = request_log.single_request(); assert!( diff --git a/codex-rs/core/tests/suite/resume.rs b/codex-rs/core/tests/suite/resume.rs index 1fee3858e2f..442075a6fc0 100644 --- a/codex-rs/core/tests/suite/resume.rs +++ b/codex-rs/core/tests/suite/resume.rs @@ -41,7 +41,7 @@ async fn resume_includes_initial_messages_from_rollout_events() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let resumed = builder.resume(&server, home, rollout_path).await?; let initial_messages = resumed @@ -94,7 +94,7 @@ async fn resume_includes_initial_messages_from_reasoning_events() -> Result<()> }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let resumed = builder.resume(&server, home, rollout_path).await?; let initial_messages = resumed diff --git a/codex-rs/core/tests/suite/resume_warning.rs b/codex-rs/core/tests/suite/resume_warning.rs index 5b38ce4b8d7..df0534bf40d 100644 --- a/codex-rs/core/tests/suite/resume_warning.rs +++ b/codex-rs/core/tests/suite/resume_warning.rs @@ -79,7 +79,7 @@ async fn emits_warning_when_resumed_model_differs() { assert!(message.contains("previous-model")); assert!(message.contains("current-model")); - // Drain the TaskComplete/Shutdown window to avoid leaking tasks between tests. + // Drain the TurnComplete/Shutdown window to avoid leaking tasks between tests. // The warning is emitted during initialization, so a short sleep is sufficient. tokio::time::sleep(Duration::from_millis(50)).await; } diff --git a/codex-rs/core/tests/suite/review.rs b/codex-rs/core/tests/suite/review.rs index 3c52d4c5a44..8ca727dd6b3 100644 --- a/codex-rs/core/tests/suite/review.rs +++ b/codex-rs/core/tests/suite/review.rs @@ -36,7 +36,7 @@ use uuid::Uuid; use wiremock::MockServer; /// Verify that submitting `Op::Review` spawns a child task and emits -/// EnteredReviewMode -> ExitedReviewMode(None) -> TaskComplete +/// EnteredReviewMode -> ExitedReviewMode(None) -> TurnComplete /// in that order when the model returns a structured review JSON payload. #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn review_op_emits_lifecycle_and_review_output() { @@ -89,7 +89,7 @@ async fn review_op_emits_lifecycle_and_review_output() { .await .unwrap(); - // Verify lifecycle: Entered -> Exited(Some(review)) -> TaskComplete. + // Verify lifecycle: Entered -> Exited(Some(review)) -> TurnComplete. let _entered = wait_for_event(&codex, |ev| matches!(ev, EventMsg::EnteredReviewMode(_))).await; let closed = wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExitedReviewMode(_))).await; let review = match closed { @@ -116,7 +116,7 @@ async fn review_op_emits_lifecycle_and_review_output() { overall_confidence_score: 0.8, }; assert_eq!(expected, review); - let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Also verify that a user message with the header and a formatted finding // was recorded back in the parent session's rollout. @@ -224,7 +224,7 @@ async fn review_op_with_plain_text_emits_review_fallback() { ..Default::default() }; assert_eq!(expected, review); - let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; server.verify().await; } @@ -272,9 +272,9 @@ async fn review_filters_agent_message_related_events() { let mut saw_entered = false; let mut saw_exited = false; - // Drain until TaskComplete; assert streaming-related events never surface. + // Drain until TurnComplete; assert streaming-related events never surface. wait_for_event(&codex, |event| match event { - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, EventMsg::EnteredReviewMode(_) => { saw_entered = true; false @@ -350,13 +350,13 @@ async fn review_does_not_emit_agent_message_on_structured_output() { .await .unwrap(); - // Drain events until TaskComplete; ensure we only see a final + // Drain events until TurnComplete; ensure we only see a final // AgentMessage (no streaming assistant messages). let mut saw_entered = false; let mut saw_exited = false; let mut agent_messages = 0; wait_for_event(&codex, |event| match event { - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, EventMsg::AgentMessage(_) => { agent_messages += 1; false @@ -420,7 +420,7 @@ async fn review_uses_custom_review_model_from_config() { ) }) .await; - let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Assert the request body model equals the configured review model let request = request_log.single_request(); @@ -539,7 +539,7 @@ async fn review_input_isolated_from_parent_history() { ) }) .await; - let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Assert the request `input` contains the environment context followed by the user review prompt. let request = request_log.single_request(); @@ -649,7 +649,7 @@ async fn review_history_surfaces_in_parent_session() { ) }) .await; - let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // 2) Continue in the parent session; request input must not include any review items. let followup = "back to parent".to_string(); @@ -662,7 +662,7 @@ async fn review_history_surfaces_in_parent_session() { }) .await .unwrap(); - let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Inspect the second request (parent turn) input contents. // Parent turns include session initial messages (user_instructions, environment_context). @@ -786,7 +786,7 @@ async fn review_uses_overridden_cwd_for_base_branch_merge_base() { .unwrap(); let _entered = wait_for_event(&codex, |ev| matches!(ev, EventMsg::EnteredReviewMode(_))).await; - let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _complete = wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert_eq!(requests.len(), 1); diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index 92743699678..dc6d47fe710 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -161,7 +161,7 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> { .expect("env snapshot inserted"); assert_eq!(env_value, expected_env_value); - wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; server.verify().await; @@ -296,7 +296,7 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> { other => panic!("expected image content, got {other:?}"), } - wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let output_item = final_mock.single_request().function_call_output(call_id); assert_eq!( @@ -462,7 +462,7 @@ async fn stdio_image_completions_round_trip() -> anyhow::Result<()> { }; assert!(end.result.as_ref().is_ok(), "tool call should succeed"); - wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // Chat Completions assertion: the second POST should include a tool role message // with an array `content` containing an item with the expected data URL. @@ -618,7 +618,7 @@ async fn stdio_server_propagates_whitelisted_env_vars() -> anyhow::Result<()> { .expect("env snapshot inserted"); assert_eq!(env_value, expected_env_value); - wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; server.verify().await; @@ -760,7 +760,7 @@ async fn streamable_http_tool_call_round_trip() -> anyhow::Result<()> { .expect("env snapshot inserted"); assert_eq!(env_value, expected_env_value); - wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; server.verify().await; @@ -934,7 +934,7 @@ async fn streamable_http_with_oauth_round_trip() -> anyhow::Result<()> { .expect("env snapshot inserted"); assert_eq!(env_value, expected_env_value); - wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; server.verify().await; diff --git a/codex-rs/core/tests/suite/shell_snapshot.rs b/codex-rs/core/tests/suite/shell_snapshot.rs index 8357fb8a95a..39f2b3a33e5 100644 --- a/codex-rs/core/tests/suite/shell_snapshot.rs +++ b/codex-rs/core/tests/suite/shell_snapshot.rs @@ -101,7 +101,7 @@ async fn run_snapshot_command(command: &str) -> Result { }) .await; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; Ok(SnapshotRun { begin, @@ -177,7 +177,7 @@ async fn run_shell_command_snapshot(command: &str) -> Result { }) .await; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; Ok(SnapshotRun { begin, @@ -295,7 +295,7 @@ async fn shell_command_snapshot_still_intercepts_apply_patch() -> Result<()> { }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; assert_eq!(fs::read_to_string(&target).await?, "hello from snapshot\n"); diff --git a/codex-rs/core/tests/suite/skills.rs b/codex-rs/core/tests/suite/skills.rs index 8e9266ee868..ee93435880c 100644 --- a/codex-rs/core/tests/suite/skills.rs +++ b/codex-rs/core/tests/suite/skills.rs @@ -81,7 +81,7 @@ async fn user_turn_includes_skill_instructions() -> Result<()> { .await?; core_test_support::wait_for_event(test.codex.as_ref(), |event| { - matches!(event, codex_core::protocol::EventMsg::TaskComplete(_)) + matches!(event, codex_core::protocol::EventMsg::TurnComplete(_)) }) .await; diff --git a/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs b/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs index 65313072dc3..b17bb632096 100644 --- a/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs +++ b/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs @@ -94,10 +94,10 @@ async fn continue_after_stream_error() { .await .unwrap(); - // Expect an Error followed by TaskComplete so the session is released. + // Expect an Error followed by TurnComplete so the session is released. wait_for_event(&codex, |ev| matches!(ev, EventMsg::Error(_))).await; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // 2) Second turn: now send another prompt that should succeed using the // mock server SSE stream. If the agent failed to clear the running task on @@ -112,5 +112,5 @@ async fn continue_after_stream_error() { .await .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; } diff --git a/codex-rs/core/tests/suite/stream_no_completed.rs b/codex-rs/core/tests/suite/stream_no_completed.rs index 830c0917b51..f82aaceaf55 100644 --- a/codex-rs/core/tests/suite/stream_no_completed.rs +++ b/codex-rs/core/tests/suite/stream_no_completed.rs @@ -101,6 +101,6 @@ async fn retries_on_early_close() { .await .unwrap(); - // Wait until TaskComplete (should succeed after retry). - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + // Wait until TurnComplete (should succeed after retry). + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; } diff --git a/codex-rs/core/tests/suite/tool_harness.rs b/codex-rs/core/tests/suite/tool_harness.rs index a36ab03a41f..e7cd43ca678 100644 --- a/codex-rs/core/tests/suite/tool_harness.rs +++ b/codex-rs/core/tests/suite/tool_harness.rs @@ -93,7 +93,7 @@ async fn shell_tool_executes_command_and_streams_output() -> anyhow::Result<()> }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let req = second_mock.single_request(); let (output_text, _) = call_output(&req, call_id); @@ -171,7 +171,7 @@ async fn update_plan_tool_emits_plan_update_event() -> anyhow::Result<()> { assert_matches!(update.plan[1].status, StepStatus::Pending); false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -241,7 +241,7 @@ async fn update_plan_tool_rejects_malformed_payload() -> anyhow::Result<()> { saw_plan_update = true; false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -336,7 +336,7 @@ async fn apply_patch_tool_executes_and_emits_patch_events() -> anyhow::Result<() patch_end_success = Some(end.success); false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -419,7 +419,7 @@ async fn apply_patch_reports_parse_diagnostics() -> anyhow::Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let req = second_mock.single_request(); let (output_text, success_flag) = call_output(&req, call_id); diff --git a/codex-rs/core/tests/suite/tool_parallelism.rs b/codex-rs/core/tests/suite/tool_parallelism.rs index 71a6031fe83..7661cb42368 100644 --- a/codex-rs/core/tests/suite/tool_parallelism.rs +++ b/codex-rs/core/tests/suite/tool_parallelism.rs @@ -49,7 +49,7 @@ async fn run_turn(test: &TestCodex, prompt: &str) -> anyhow::Result<()> { }) .await?; - wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; Ok(()) } @@ -388,7 +388,7 @@ async fn shell_tools_start_before_response_completed_when_stream_delayed() -> an .await??; let _ = completion_gate_tx.send(()); - wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let mut completion_iter = completion_receivers.into_iter(); let completed_at = completion_iter diff --git a/codex-rs/core/tests/suite/truncation.rs b/codex-rs/core/tests/suite/truncation.rs index 0176f8cde39..c2bbd2d53c8 100644 --- a/codex-rs/core/tests/suite/truncation.rs +++ b/codex-rs/core/tests/suite/truncation.rs @@ -538,7 +538,7 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> { .await?; // Wait for completion to ensure the outbound request is captured. - wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&fixture.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let output_item = final_mock.single_request().function_call_output(call_id); // Expect exactly one array element: the image item; and no trailing summary text. let output = output_item.get("output").expect("output"); diff --git a/codex-rs/core/tests/suite/unified_exec.rs b/codex-rs/core/tests/suite/unified_exec.rs index a640daacc88..2e2fd34e67e 100644 --- a/codex-rs/core/tests/suite/unified_exec.rs +++ b/codex-rs/core/tests/suite/unified_exec.rs @@ -238,7 +238,7 @@ async fn unified_exec_intercepts_apply_patch_exec_command() -> Result<()> { saw_exec_end = true; false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }) .await; @@ -346,7 +346,7 @@ async fn unified_exec_emits_exec_command_begin_event() -> Result<()> { assert_eq!(begin_event.cwd, cwd.path()); - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; Ok(()) } @@ -423,7 +423,7 @@ async fn unified_exec_resolves_relative_workdir() -> Result<()> { "exec_command cwd should resolve relative workdir against turn cwd", ); - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; Ok(()) } @@ -500,7 +500,7 @@ async fn unified_exec_respects_workdir_override() -> Result<()> { "exec_command cwd should reflect the requested workdir override" ); - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert!(!requests.is_empty(), "expected at least one POST request"); @@ -591,7 +591,7 @@ async fn unified_exec_emits_exec_command_end_event() -> Result<()> { "expected aggregated output to contain marker" ); - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; Ok(()) } @@ -663,7 +663,7 @@ async fn unified_exec_emits_output_delta_for_exec_command() -> Result<()> { "delta chunk missing expected text: {text:?}", ); - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; Ok(()) } @@ -742,7 +742,7 @@ async fn unified_exec_full_lifecycle_with_background_end_event() -> Result<()> { break; } } - EventMsg::TaskComplete(_) => { + EventMsg::TurnComplete(_) => { task_completed = true; if task_completed && end_event.is_some() { break; @@ -858,7 +858,7 @@ async fn unified_exec_emits_terminal_interaction_for_write_stdin() -> Result<()> EventMsg::TerminalInteraction(ev) if ev.call_id == open_call_id => { terminal_interaction = Some(ev); } - EventMsg::TaskComplete(_) => break, + EventMsg::TurnComplete(_) => break, _ => {} } } @@ -1005,7 +1005,7 @@ async fn unified_exec_terminal_interaction_captures_delayed_output() -> Result<( EventMsg::ExecCommandEnd(ev) if ev.call_id == open_call_id => { end_event = Some(ev); } - EventMsg::TaskComplete(_) => { + EventMsg::TurnComplete(_) => { task_completed = true; } _ => {} @@ -1147,7 +1147,7 @@ async fn unified_exec_emits_one_begin_and_one_end_event() -> Result<()> { match event_msg { EventMsg::ExecCommandBegin(event) => begin_events.push(event), EventMsg::ExecCommandEnd(event) => end_events.push(event), - EventMsg::TaskComplete(_) => break, + EventMsg::TurnComplete(_) => break, _ => {} } } @@ -1235,7 +1235,7 @@ async fn exec_command_reports_chunk_and_exit_metadata() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert!(!requests.is_empty(), "expected at least one POST request"); @@ -1341,7 +1341,7 @@ async fn unified_exec_respects_early_exit_notifications() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert!(!requests.is_empty(), "expected at least one POST request"); @@ -1468,7 +1468,7 @@ async fn write_stdin_returns_exit_metadata_and_clears_session() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert!(!requests.is_empty(), "expected at least one POST request"); @@ -1641,7 +1641,7 @@ async fn unified_exec_emits_end_event_when_session_dies_via_stdin() -> Result<() assert_eq!(end_event.exit_code, 0); - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; Ok(()) } @@ -1729,7 +1729,7 @@ async fn unified_exec_closes_long_running_session_at_turn_end() -> Result<()> { let msg = wait_for_event(&codex, |_| true).await; match msg { EventMsg::ExecCommandEnd(ev) if ev.call_id == call_id => end_event = Some(ev), - EventMsg::TaskComplete(_) => task_complete = true, + EventMsg::TurnComplete(_) => task_complete = true, _ => {} } if task_complete && end_event.is_some() { @@ -1824,7 +1824,7 @@ async fn unified_exec_reuses_session_via_stdin() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert!(!requests.is_empty(), "expected at least one POST request"); @@ -1957,7 +1957,7 @@ PY // This is a worst case scenario for the truncate logic. wait_for_event_with_timeout( &codex, - |event| matches!(event, EventMsg::TaskComplete(_)), + |event| matches!(event, EventMsg::TurnComplete(_)), Duration::from_secs(10), ) .await; @@ -2068,7 +2068,7 @@ async fn unified_exec_timeout_and_followup_poll() -> Result<()> { loop { let event = codex.next_event().await.expect("event"); - if matches!(event.msg, EventMsg::TaskComplete(_)) { + if matches!(event.msg, EventMsg::TurnComplete(_)) { break; } } @@ -2159,7 +2159,7 @@ PY }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert!(!requests.is_empty(), "expected at least one POST request"); @@ -2238,7 +2238,7 @@ async fn unified_exec_runs_under_sandbox() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert!(!requests.is_empty(), "expected at least one POST request"); @@ -2338,7 +2338,7 @@ async fn unified_exec_python_prompt_under_seatbelt() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert!(!requests.is_empty(), "expected at least one POST request"); @@ -2430,7 +2430,7 @@ async fn unified_exec_runs_on_all_platforms() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = request_log.requests(); assert!(!requests.is_empty(), "expected at least one POST request"); @@ -2560,7 +2560,7 @@ async fn unified_exec_prunes_exited_sessions_first() -> Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let requests = response_mock.requests(); assert!( diff --git a/codex-rs/core/tests/suite/user_notification.rs b/codex-rs/core/tests/suite/user_notification.rs index a3289b87f71..06172582334 100644 --- a/codex-rs/core/tests/suite/user_notification.rs +++ b/codex-rs/core/tests/suite/user_notification.rs @@ -64,7 +64,7 @@ echo -n "${@: -1}" > $(dirname "${0}")/notify.txt"#, final_output_json_schema: None, }) .await?; - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; // We fork the notify script, so we need to wait for it to write to the file. fs_wait::wait_for_path_exists(¬ify_file, Duration::from_secs(5)).await?; diff --git a/codex-rs/core/tests/suite/user_shell_cmd.rs b/codex-rs/core/tests/suite/user_shell_cmd.rs index d6818c0c54d..91e9f35f382 100644 --- a/codex-rs/core/tests/suite/user_shell_cmd.rs +++ b/codex-rs/core/tests/suite/user_shell_cmd.rs @@ -175,7 +175,7 @@ async fn user_shell_command_history_is_persisted_and_shared_with_model() -> anyh assert_eq!(end_event.exit_code, 0); assert_eq!(end_event.stdout.trim(), "not-set"); - let _ = wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _ = wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let responses = vec![responses::sse(vec![ responses::ev_response_created("resp-1"), @@ -233,7 +233,7 @@ async fn user_shell_command_output_is_truncated_in_history() -> anyhow::Result<( .await; assert_eq!(end_event.exit_code, 0); - let _ = wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; + let _ = wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; let responses = vec![responses::sse(vec![ responses::ev_response_created("resp-1"), diff --git a/codex-rs/core/tests/suite/view_image.rs b/codex-rs/core/tests/suite/view_image.rs index 8d506dc36b9..eedc524592e 100644 --- a/codex-rs/core/tests/suite/view_image.rs +++ b/codex-rs/core/tests/suite/view_image.rs @@ -91,7 +91,7 @@ async fn user_turn_with_local_image_attaches_image() -> anyhow::Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let body = mock.single_request().body_json(); let image_message = @@ -190,7 +190,7 @@ async fn view_image_tool_attaches_local_image() -> anyhow::Result<()> { tool_event = Some(event.clone()); false } - EventMsg::TaskComplete(_) => true, + EventMsg::TurnComplete(_) => true, _ => false, }, // Empirically, we have seen this run slow when run under @@ -298,7 +298,7 @@ async fn view_image_tool_errors_when_path_is_directory() -> anyhow::Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let req = mock.single_request(); let body_with_tool_output = req.body_json(); @@ -370,7 +370,7 @@ async fn view_image_tool_placeholder_for_non_image_files() -> anyhow::Result<()> }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let request = mock.single_request(); assert!( @@ -461,7 +461,7 @@ async fn view_image_tool_errors_when_file_missing() -> anyhow::Result<()> { }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let req = mock.single_request(); let body_with_tool_output = req.body_json(); @@ -542,7 +542,7 @@ async fn replaces_invalid_local_image_after_bad_request() -> anyhow::Result<()> }) .await?; - wait_for_event(&codex, |event| matches!(event, EventMsg::TaskComplete(_))).await; + wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; let first_body = invalid_image_mock.single_request().body_json(); assert!( diff --git a/codex-rs/docs/protocol_v1.md b/codex-rs/docs/protocol_v1.md index 805abb0ea8c..0e4e1ddde32 100644 --- a/codex-rs/docs/protocol_v1.md +++ b/codex-rs/docs/protocol_v1.md @@ -65,20 +65,22 @@ Since only 1 `Task` can be run at a time, for parallel tasks it is recommended t For complete documentation of the `Op` and `EventMsg` variants, refer to [protocol.rs](../core/src/protocol.rs). Some example payload types: - `Op` - - `Op::UserInput` – Any input from the user to kick off a `Task` - - `Op::Interrupt` – Interrupts a running task + - `Op::UserInput` – Any input from the user to kick off a `Turn` + - `Op::Interrupt` – Interrupts a running turn - `Op::ExecApproval` – Approve or deny code execution - `Op::ListSkills` – Request skills for one or more cwd values (optionally `force_reload`) - `EventMsg` - `EventMsg::AgentMessage` – Messages from the `Model` - `EventMsg::ExecApprovalRequest` – Request approval from user to execute a command - - `EventMsg::TaskComplete` – A task completed successfully - - `EventMsg::Error` – A task stopped with an error + - `EventMsg::TurnComplete` – A turn completed successfully + - `EventMsg::Error` – A turn stopped with an error - `EventMsg::Warning` – A non-fatal warning that the client should surface to the user - - `EventMsg::TurnComplete` – Contains a `response_id` bookmark for last `response_id` executed by the task. This can be used to continue the task at a later point in time, perhaps with additional user input. + - `EventMsg::TurnComplete` – Contains a `response_id` bookmark for last `response_id` executed by the turn. This can be used to continue the turn at a later point in time, perhaps with additional user input. - `EventMsg::ListSkillsResponse` – Response payload with per-cwd skill entries (`cwd`, `skills`, `errors`) -The `response_id` returned from each task matches the OpenAI `response_id` stored in the API's `/responses` endpoint. It can be stored and used in future `Sessions` to resume threads of work. +Note: For v1 wire compatibility, `EventMsg::TurnStarted` and `EventMsg::TurnComplete` serialize as `task_started` / `task_complete`. The deserializer accepts both `task_*` and `turn_*` tags. + +The `response_id` returned from each turn matches the OpenAI `response_id` stored in the API's `/responses` endpoint. It can be stored and used in future `Sessions` to resume threads of work. ## Transport @@ -112,7 +114,7 @@ sequenceDiagram codex->>user: Event::SessionConfigured user->>session: Op::UserInput session-->>+task: start task - task->>user: Event::TaskStarted + task->>user: Event::TurnStarted task->>agent: prompt agent->>task: response (exec) task->>-user: Event::ExecApprovalRequest @@ -128,7 +130,7 @@ sequenceDiagram agent->>task: response
(msg + completed) task->>user: Event::AgentMessage task->>user: Event::TurnComplete - task->>-user: Event::TaskComplete + task->>-user: Event::TurnComplete ``` ### Task Interrupt @@ -150,7 +152,7 @@ sequenceDiagram end user->>session: Op::UserInput session-->>+task1: start task - task1->>user: Event::TaskStarted + task1->>user: Event::TurnStarted task1->>agent: prompt agent->>task1: response (exec) task1->>task1: exec (auto-approved) @@ -162,14 +164,14 @@ sequenceDiagram task1->>-user: Event::Error("interrupted") user->>session: Op::UserInput w/ last_response_id session-->>+task2: start task - task2->>user: Event::TaskStarted + task2->>user: Event::TurnStarted task2->>agent: prompt + Task1 last_response_id agent->>task2: response (exec) task2->>task2: exec (auto-approve) - task2->>user: Event::TurnCompleted + task2->>user: Event::TurnComplete task2->>agent: stdout agent->>task2: msg + completed task2->>user: Event::AgentMessage - task2->>user: Event::TurnCompleted - task2->>-user: Event::TaskCompleted + task2->>user: Event::TurnComplete + task2->>-user: Event::TurnComplete ``` diff --git a/codex-rs/exec/src/event_processor_with_human_output.rs b/codex-rs/exec/src/event_processor_with_human_output.rs index ba6d99c5a82..f1cba0b9f7e 100644 --- a/codex-rs/exec/src/event_processor_with_human_output.rs +++ b/codex-rs/exec/src/event_processor_with_human_output.rs @@ -18,8 +18,8 @@ use codex_core::protocol::PatchApplyBeginEvent; use codex_core::protocol::PatchApplyEndEvent; use codex_core::protocol::SessionConfiguredEvent; use codex_core::protocol::StreamErrorEvent; -use codex_core::protocol::TaskCompleteEvent; use codex_core::protocol::TurnAbortReason; +use codex_core::protocol::TurnCompleteEvent; use codex_core::protocol::TurnDiffEvent; use codex_core::protocol::WarningEvent; use codex_core::protocol::WebSearchEndEvent; @@ -233,7 +233,7 @@ impl EventProcessor for EventProcessorWithHumanOutput { }; ts_msg!(self, "{}", message.style(self.dimmed)); } - EventMsg::TaskStarted(_) => { + EventMsg::TurnStarted(_) => { // Ignore. } EventMsg::ElicitationRequest(ev) => { @@ -249,7 +249,7 @@ impl EventProcessor for EventProcessorWithHumanOutput { "auto-cancelling (not supported in exec mode)".style(self.dimmed) ); } - EventMsg::TaskComplete(TaskCompleteEvent { last_agent_message }) => { + EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message }) => { let last_message = last_agent_message.as_deref(); if let Some(output_file) = self.last_message_path.as_deref() { handle_last_message(last_message, output_file); diff --git a/codex-rs/exec/src/event_processor_with_jsonl_output.rs b/codex-rs/exec/src/event_processor_with_jsonl_output.rs index 0b2df544559..3679b573806 100644 --- a/codex-rs/exec/src/event_processor_with_jsonl_output.rs +++ b/codex-rs/exec/src/event_processor_with_jsonl_output.rs @@ -34,22 +34,7 @@ use crate::exec_events::TurnStartedEvent; use crate::exec_events::Usage; use crate::exec_events::WebSearchItem; use codex_core::config::Config; -use codex_core::protocol::AgentMessageEvent; -use codex_core::protocol::AgentReasoningEvent; -use codex_core::protocol::Event; -use codex_core::protocol::EventMsg; -use codex_core::protocol::ExecCommandBeginEvent; -use codex_core::protocol::ExecCommandEndEvent; -use codex_core::protocol::FileChange; -use codex_core::protocol::McpToolCallBeginEvent; -use codex_core::protocol::McpToolCallEndEvent; -use codex_core::protocol::PatchApplyBeginEvent; -use codex_core::protocol::PatchApplyEndEvent; -use codex_core::protocol::SessionConfiguredEvent; -use codex_core::protocol::TaskCompleteEvent; -use codex_core::protocol::TaskStartedEvent; -use codex_core::protocol::TerminalInteractionEvent; -use codex_core::protocol::WebSearchEndEvent; +use codex_core::protocol; use codex_protocol::plan_tool::StepStatus; use codex_protocol::plan_tool::UpdatePlanArgs; use serde_json::Value as JsonValue; @@ -61,7 +46,7 @@ pub struct EventProcessorWithJsonOutput { next_event_id: AtomicU64, // Tracks running commands by call_id, including the associated item id. running_commands: HashMap, - running_patch_applies: HashMap, + running_patch_applies: HashMap, // Tracks the todo list for the current turn (at most one per turn). running_todo_list: Option, last_total_token_usage: Option, @@ -104,39 +89,39 @@ impl EventProcessorWithJsonOutput { } } - pub fn collect_thread_events(&mut self, event: &Event) -> Vec { + pub fn collect_thread_events(&mut self, event: &protocol::Event) -> Vec { match &event.msg { - EventMsg::SessionConfigured(ev) => self.handle_session_configured(ev), - EventMsg::AgentMessage(ev) => self.handle_agent_message(ev), - EventMsg::AgentReasoning(ev) => self.handle_reasoning_event(ev), - EventMsg::ExecCommandBegin(ev) => self.handle_exec_command_begin(ev), - EventMsg::ExecCommandEnd(ev) => self.handle_exec_command_end(ev), - EventMsg::TerminalInteraction(ev) => self.handle_terminal_interaction(ev), - EventMsg::ExecCommandOutputDelta(ev) => { + protocol::EventMsg::SessionConfigured(ev) => self.handle_session_configured(ev), + protocol::EventMsg::AgentMessage(ev) => self.handle_agent_message(ev), + protocol::EventMsg::AgentReasoning(ev) => self.handle_reasoning_event(ev), + protocol::EventMsg::ExecCommandBegin(ev) => self.handle_exec_command_begin(ev), + protocol::EventMsg::ExecCommandEnd(ev) => self.handle_exec_command_end(ev), + protocol::EventMsg::TerminalInteraction(ev) => self.handle_terminal_interaction(ev), + protocol::EventMsg::ExecCommandOutputDelta(ev) => { self.handle_output_chunk(&ev.call_id, &ev.chunk) } - EventMsg::McpToolCallBegin(ev) => self.handle_mcp_tool_call_begin(ev), - EventMsg::McpToolCallEnd(ev) => self.handle_mcp_tool_call_end(ev), - EventMsg::PatchApplyBegin(ev) => self.handle_patch_apply_begin(ev), - EventMsg::PatchApplyEnd(ev) => self.handle_patch_apply_end(ev), - EventMsg::WebSearchBegin(_) => Vec::new(), - EventMsg::WebSearchEnd(ev) => self.handle_web_search_end(ev), - EventMsg::TokenCount(ev) => { + protocol::EventMsg::McpToolCallBegin(ev) => self.handle_mcp_tool_call_begin(ev), + protocol::EventMsg::McpToolCallEnd(ev) => self.handle_mcp_tool_call_end(ev), + protocol::EventMsg::PatchApplyBegin(ev) => self.handle_patch_apply_begin(ev), + protocol::EventMsg::PatchApplyEnd(ev) => self.handle_patch_apply_end(ev), + protocol::EventMsg::WebSearchBegin(_) => Vec::new(), + protocol::EventMsg::WebSearchEnd(ev) => self.handle_web_search_end(ev), + protocol::EventMsg::TokenCount(ev) => { if let Some(info) = &ev.info { self.last_total_token_usage = Some(info.total_token_usage.clone()); } Vec::new() } - EventMsg::TaskStarted(ev) => self.handle_task_started(ev), - EventMsg::TaskComplete(_) => self.handle_task_complete(), - EventMsg::Error(ev) => { + protocol::EventMsg::TurnStarted(ev) => self.handle_task_started(ev), + protocol::EventMsg::TurnComplete(_) => self.handle_task_complete(), + protocol::EventMsg::Error(ev) => { let error = ThreadErrorEvent { message: ev.message.clone(), }; self.last_critical_error = Some(error.clone()); vec![ThreadEvent::Error(error)] } - EventMsg::Warning(ev) => { + protocol::EventMsg::Warning(ev) => { let item = ThreadItem { id: self.get_next_item_id(), details: ThreadItemDetails::Error(ErrorItem { @@ -145,7 +130,7 @@ impl EventProcessorWithJsonOutput { }; vec![ThreadEvent::ItemCompleted(ItemCompletedEvent { item })] } - EventMsg::StreamError(ev) => { + protocol::EventMsg::StreamError(ev) => { let message = match &ev.additional_details { Some(details) if !details.trim().is_empty() => { format!("{} ({})", ev.message, details) @@ -154,7 +139,7 @@ impl EventProcessorWithJsonOutput { }; vec![ThreadEvent::Error(ThreadErrorEvent { message })] } - EventMsg::PlanUpdate(ev) => self.handle_plan_update(ev), + protocol::EventMsg::PlanUpdate(ev) => self.handle_plan_update(ev), _ => Vec::new(), } } @@ -167,13 +152,16 @@ impl EventProcessorWithJsonOutput { ) } - fn handle_session_configured(&self, payload: &SessionConfiguredEvent) -> Vec { + fn handle_session_configured( + &self, + payload: &protocol::SessionConfiguredEvent, + ) -> Vec { vec![ThreadEvent::ThreadStarted(ThreadStartedEvent { thread_id: payload.session_id.to_string(), })] } - fn handle_web_search_end(&self, ev: &WebSearchEndEvent) -> Vec { + fn handle_web_search_end(&self, ev: &protocol::WebSearchEndEvent) -> Vec { let item = ThreadItem { id: self.get_next_item_id(), details: ThreadItemDetails::WebSearch(WebSearchItem { @@ -189,12 +177,15 @@ impl EventProcessorWithJsonOutput { vec![] } - fn handle_terminal_interaction(&mut self, _ev: &TerminalInteractionEvent) -> Vec { + fn handle_terminal_interaction( + &mut self, + _ev: &protocol::TerminalInteractionEvent, + ) -> Vec { //TODO see how we want to process them vec![] } - fn handle_agent_message(&self, payload: &AgentMessageEvent) -> Vec { + fn handle_agent_message(&self, payload: &protocol::AgentMessageEvent) -> Vec { let item = ThreadItem { id: self.get_next_item_id(), @@ -206,7 +197,7 @@ impl EventProcessorWithJsonOutput { vec![ThreadEvent::ItemCompleted(ItemCompletedEvent { item })] } - fn handle_reasoning_event(&self, ev: &AgentReasoningEvent) -> Vec { + fn handle_reasoning_event(&self, ev: &protocol::AgentReasoningEvent) -> Vec { let item = ThreadItem { id: self.get_next_item_id(), @@ -217,7 +208,10 @@ impl EventProcessorWithJsonOutput { vec![ThreadEvent::ItemCompleted(ItemCompletedEvent { item })] } - fn handle_exec_command_begin(&mut self, ev: &ExecCommandBeginEvent) -> Vec { + fn handle_exec_command_begin( + &mut self, + ev: &protocol::ExecCommandBeginEvent, + ) -> Vec { let item_id = self.get_next_item_id(); let command_string = match shlex::try_join(ev.command.iter().map(String::as_str)) { @@ -253,7 +247,10 @@ impl EventProcessorWithJsonOutput { vec![ThreadEvent::ItemStarted(ItemStartedEvent { item })] } - fn handle_mcp_tool_call_begin(&mut self, ev: &McpToolCallBeginEvent) -> Vec { + fn handle_mcp_tool_call_begin( + &mut self, + ev: &protocol::McpToolCallBeginEvent, + ) -> Vec { let item_id = self.get_next_item_id(); let server = ev.invocation.server.clone(); let tool = ev.invocation.tool.clone(); @@ -284,7 +281,7 @@ impl EventProcessorWithJsonOutput { vec![ThreadEvent::ItemStarted(ItemStartedEvent { item })] } - fn handle_mcp_tool_call_end(&mut self, ev: &McpToolCallEndEvent) -> Vec { + fn handle_mcp_tool_call_end(&mut self, ev: &protocol::McpToolCallEndEvent) -> Vec { let status = if ev.is_success() { McpToolCallStatus::Completed } else { @@ -344,22 +341,25 @@ impl EventProcessorWithJsonOutput { vec![ThreadEvent::ItemCompleted(ItemCompletedEvent { item })] } - fn handle_patch_apply_begin(&mut self, ev: &PatchApplyBeginEvent) -> Vec { + fn handle_patch_apply_begin( + &mut self, + ev: &protocol::PatchApplyBeginEvent, + ) -> Vec { self.running_patch_applies .insert(ev.call_id.clone(), ev.clone()); Vec::new() } - fn map_change_kind(&self, kind: &FileChange) -> PatchChangeKind { + fn map_change_kind(&self, kind: &protocol::FileChange) -> PatchChangeKind { match kind { - FileChange::Add { .. } => PatchChangeKind::Add, - FileChange::Delete { .. } => PatchChangeKind::Delete, - FileChange::Update { .. } => PatchChangeKind::Update, + protocol::FileChange::Add { .. } => PatchChangeKind::Add, + protocol::FileChange::Delete { .. } => PatchChangeKind::Delete, + protocol::FileChange::Update { .. } => PatchChangeKind::Update, } } - fn handle_patch_apply_end(&mut self, ev: &PatchApplyEndEvent) -> Vec { + fn handle_patch_apply_end(&mut self, ev: &protocol::PatchApplyEndEvent) -> Vec { if let Some(running_patch_apply) = self.running_patch_applies.remove(&ev.call_id) { let status = if ev.success { PatchApplyStatus::Completed @@ -388,7 +388,7 @@ impl EventProcessorWithJsonOutput { Vec::new() } - fn handle_exec_command_end(&mut self, ev: &ExecCommandEndEvent) -> Vec { + fn handle_exec_command_end(&mut self, ev: &protocol::ExecCommandEndEvent) -> Vec { let Some(RunningCommand { command, item_id, @@ -459,7 +459,7 @@ impl EventProcessorWithJsonOutput { vec![ThreadEvent::ItemStarted(ItemStartedEvent { item })] } - fn handle_task_started(&mut self, _: &TaskStartedEvent) -> Vec { + fn handle_task_started(&mut self, _: &protocol::TurnStartedEvent) -> Vec { self.last_critical_error = None; vec![ThreadEvent::TurnStarted(TurnStartedEvent {})] } @@ -513,15 +513,15 @@ impl EventProcessorWithJsonOutput { } impl EventProcessor for EventProcessorWithJsonOutput { - fn print_config_summary(&mut self, _: &Config, _: &str, ev: &SessionConfiguredEvent) { - self.process_event(Event { + fn print_config_summary(&mut self, _: &Config, _: &str, ev: &protocol::SessionConfiguredEvent) { + self.process_event(protocol::Event { id: "".to_string(), - msg: EventMsg::SessionConfigured(ev.clone()), + msg: protocol::EventMsg::SessionConfigured(ev.clone()), }); } #[allow(clippy::print_stdout)] - fn process_event(&mut self, event: Event) -> CodexStatus { + fn process_event(&mut self, event: protocol::Event) -> CodexStatus { let aggregated = self.collect_thread_events(&event); for conv_event in aggregated { match serde_json::to_string(&conv_event) { @@ -534,9 +534,12 @@ impl EventProcessor for EventProcessorWithJsonOutput { } } - let Event { msg, .. } = event; + let protocol::Event { msg, .. } = event; - if let EventMsg::TaskComplete(TaskCompleteEvent { last_agent_message }) = msg { + if let protocol::EventMsg::TurnComplete(protocol::TurnCompleteEvent { + last_agent_message, + }) = msg + { if let Some(output_file) = self.last_message_path.as_deref() { handle_last_message(last_agent_message.as_deref(), output_file); } diff --git a/codex-rs/exec/tests/event_processor_with_json_output.rs b/codex-rs/exec/tests/event_processor_with_json_output.rs index a3e23181655..e60fcba8e80 100644 --- a/codex-rs/exec/tests/event_processor_with_json_output.rs +++ b/codex-rs/exec/tests/event_processor_with_json_output.rs @@ -101,7 +101,7 @@ fn task_started_produces_turn_started_event() { let mut ep = EventProcessorWithJsonOutput::new(None); let out = ep.collect_thread_events(&event( "t1", - EventMsg::TaskStarted(codex_core::protocol::TaskStartedEvent { + EventMsg::TurnStarted(codex_core::protocol::TurnStartedEvent { model_context_window: Some(32_000), }), )); @@ -217,7 +217,7 @@ fn plan_update_emits_todo_list_started_updated_and_completed() { // Task completes => item.completed (same id, latest state) let complete = event( "p3", - EventMsg::TaskComplete(codex_core::protocol::TaskCompleteEvent { + EventMsg::TurnComplete(codex_core::protocol::TurnCompleteEvent { last_agent_message: None, }), ); @@ -461,7 +461,7 @@ fn plan_update_after_complete_starts_new_todo_list_with_new_id() { let _ = ep.collect_thread_events(&start); let complete = event( "t2", - EventMsg::TaskComplete(codex_core::protocol::TaskCompleteEvent { + EventMsg::TurnComplete(codex_core::protocol::TurnCompleteEvent { last_agent_message: None, }), ); @@ -613,7 +613,7 @@ fn error_followed_by_task_complete_produces_turn_failed() { let complete_event = event( "e2", - EventMsg::TaskComplete(codex_core::protocol::TaskCompleteEvent { + EventMsg::TurnComplete(codex_core::protocol::TurnCompleteEvent { last_agent_message: None, }), ); @@ -1057,10 +1057,10 @@ fn task_complete_produces_turn_completed_with_usage() { ); assert!(ep.collect_thread_events(&token_count_event).is_empty()); - // Then TaskComplete should produce turn.completed with the captured usage. + // Then TurnComplete should produce turn.completed with the captured usage. let complete_event = event( "e2", - EventMsg::TaskComplete(codex_core::protocol::TaskCompleteEvent { + EventMsg::TurnComplete(codex_core::protocol::TurnCompleteEvent { last_agent_message: Some("done".to_string()), }), ); diff --git a/codex-rs/mcp-server/src/codex_tool_runner.rs b/codex-rs/mcp-server/src/codex_tool_runner.rs index 73b75dcbf83..1ee4cbd7f6f 100644 --- a/codex-rs/mcp-server/src/codex_tool_runner.rs +++ b/codex-rs/mcp-server/src/codex_tool_runner.rs @@ -20,7 +20,7 @@ use codex_core::protocol::EventMsg; use codex_core::protocol::ExecApprovalRequestEvent; use codex_core::protocol::Op; use codex_core::protocol::Submission; -use codex_core::protocol::TaskCompleteEvent; +use codex_core::protocol::TurnCompleteEvent; use codex_protocol::ThreadId; use codex_protocol::user_input::UserInput; use mcp_types::CallToolResult; @@ -228,7 +228,7 @@ async fn run_codex_tool_session_inner( .await; continue; } - EventMsg::TaskComplete(TaskCompleteEvent { last_agent_message }) => { + EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message }) => { let text = match last_agent_message { Some(msg) => msg, None => "".to_string(), @@ -267,7 +267,7 @@ async fn run_codex_tool_session_inner( } EventMsg::AgentReasoningRawContent(_) | EventMsg::AgentReasoningRawContentDelta(_) - | EventMsg::TaskStarted(_) + | EventMsg::TurnStarted(_) | EventMsg::TokenCount(_) | EventMsg::AgentReasoning(_) | EventMsg::AgentReasoningSectionBreak(_) diff --git a/codex-rs/mcp-server/tests/common/mcp_process.rs b/codex-rs/mcp-server/tests/common/mcp_process.rs index 56e134b223a..7e447533d0f 100644 --- a/codex-rs/mcp-server/tests/common/mcp_process.rs +++ b/codex-rs/mcp-server/tests/common/mcp_process.rs @@ -291,7 +291,7 @@ impl McpProcess { } } - /// Reads notifications until a legacy TaskComplete event is observed: + /// Reads notifications until a legacy TurnComplete event is observed: /// Method "codex/event" with params.msg.type == "task_complete". pub async fn read_stream_until_legacy_task_complete_notification( &mut self, diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index e3748bafc6b..32999c99856 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -226,7 +226,7 @@ pub enum Op { /// /// The command string is executed using the user's default shell and may /// include shell syntax (pipes, redirects, etc.). Output is streamed via - /// `ExecCommand*` events and the UI regains control upon `TaskComplete`. + /// `ExecCommand*` events and the UI regains control upon `TurnComplete`. RunUserShellCommand { /// The raw command string after '!' command: String, @@ -541,7 +541,7 @@ pub enum EventMsg { Error(ErrorEvent), /// Warning issued while processing a submission. Unlike `Error`, this - /// indicates the task continued but the user should still be notified. + /// indicates the turn continued but the user should still be notified. Warning(WarningEvent), /// Conversation history was compacted (either automatically or manually). @@ -550,11 +550,15 @@ pub enum EventMsg { /// Conversation history was rolled back by dropping the last N user turns. ThreadRolledBack(ThreadRolledBackEvent), - /// Agent has started a task - TaskStarted(TaskStartedEvent), + /// Agent has started a turn. + /// v1 wire format uses `task_started`; accept `turn_started` for v2 interop. + #[serde(rename = "task_started", alias = "turn_started")] + TurnStarted(TurnStartedEvent), - /// Agent has completed all actions - TaskComplete(TaskCompleteEvent), + /// Agent has completed all actions. + /// v1 wire format uses `task_complete`; accept `turn_complete` for v2 interop. + #[serde(rename = "task_complete", alias = "turn_complete")] + TurnComplete(TurnCompleteEvent), /// Usage update for the current session, including totals and last turn. /// Optional means unknown — UIs should not display when `None`. @@ -868,12 +872,12 @@ pub struct WarningEvent { pub struct ContextCompactedEvent; #[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)] -pub struct TaskCompleteEvent { +pub struct TurnCompleteEvent { pub last_agent_message: Option, } #[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)] -pub struct TaskStartedEvent { +pub struct TurnStartedEvent { // TODO(aibrahim): make this not optional pub model_context_window: Option, } diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index bd0ba788b2b..64b38e06bae 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -49,11 +49,11 @@ use codex_core::protocol::ReviewRequest; use codex_core::protocol::ReviewTarget; use codex_core::protocol::SkillsListEntry; use codex_core::protocol::StreamErrorEvent; -use codex_core::protocol::TaskCompleteEvent; use codex_core::protocol::TerminalInteractionEvent; use codex_core::protocol::TokenUsage; use codex_core::protocol::TokenUsageInfo; use codex_core::protocol::TurnAbortReason; +use codex_core::protocol::TurnCompleteEvent; use codex_core::protocol::TurnDiffEvent; use codex_core::protocol::UndoCompletedEvent; use codex_core::protocol::UndoStartedEvent; @@ -2106,8 +2106,8 @@ impl ChatWidget { self.on_agent_reasoning_final(); } EventMsg::AgentReasoningSectionBreak(_) => self.on_reasoning_section_break(), - EventMsg::TaskStarted(_) => self.on_task_started(), - EventMsg::TaskComplete(TaskCompleteEvent { last_agent_message }) => { + EventMsg::TurnStarted(_) => self.on_task_started(), + EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message }) => { self.on_task_complete(last_agent_message) } EventMsg::TokenCount(ev) => { diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index 1b9723ec54e..3ec8f9e2fba 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -39,12 +39,12 @@ use codex_core::protocol::RateLimitWindow; use codex_core::protocol::ReviewRequest; use codex_core::protocol::ReviewTarget; use codex_core::protocol::StreamErrorEvent; -use codex_core::protocol::TaskCompleteEvent; -use codex_core::protocol::TaskStartedEvent; use codex_core::protocol::TerminalInteractionEvent; use codex_core::protocol::TokenCountEvent; use codex_core::protocol::TokenUsage; use codex_core::protocol::TokenUsageInfo; +use codex_core::protocol::TurnCompleteEvent; +use codex_core::protocol::TurnStartedEvent; use codex_core::protocol::UndoCompletedEvent; use codex_core::protocol::UndoStartedEvent; use codex_core::protocol::ViewImageToolCallEvent; @@ -1320,7 +1320,7 @@ async fn unified_exec_waiting_multiple_empty_snapshots() { chat.handle_codex_event(Event { id: "turn-wait-1".into(), - msg: EventMsg::TaskComplete(TaskCompleteEvent { + msg: EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message: None, }), }); @@ -1369,7 +1369,7 @@ async fn unified_exec_non_empty_then_empty_snapshots() { chat.handle_codex_event(Event { id: "turn-wait-3".into(), - msg: EventMsg::TaskComplete(TaskCompleteEvent { + msg: EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message: None, }), }); @@ -1763,7 +1763,7 @@ async fn interrupted_turn_error_message_snapshot() { // Simulate an in-progress task so the widget is in a running state. chat.handle_codex_event(Event { id: "task-1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -2756,7 +2756,7 @@ async fn ui_snapshots_small_heights_task_running() { // Activate status line chat.handle_codex_event(Event { id: "task-1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -2787,7 +2787,7 @@ async fn status_widget_and_approval_modal_snapshot() { // Begin a running task so the status indicator would be active. chat.handle_codex_event(Event { id: "task-1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -2839,7 +2839,7 @@ async fn status_widget_active_snapshot() { // Activate the status indicator by simulating a task start. chat.handle_codex_event(Event { id: "task-1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3418,7 +3418,7 @@ async fn stream_recovery_restores_previous_status_header() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; chat.handle_codex_event(Event { id: "task".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3455,7 +3455,7 @@ async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() { // Begin turn chat.handle_codex_event(Event { id: "s1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3479,7 +3479,7 @@ async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() { // End turn chat.handle_codex_event(Event { id: "s1".into(), - msg: EventMsg::TaskComplete(TaskCompleteEvent { + msg: EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message: None, }), }); @@ -3649,7 +3649,7 @@ async fn chatwidget_exec_and_status_layout_vt100_snapshot() { }); chat.handle_codex_event(Event { id: "t1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3693,7 +3693,7 @@ async fn chatwidget_markdown_code_blocks_vt100_snapshot() { chat.handle_codex_event(Event { id: "t1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3764,7 +3764,7 @@ printf 'fenced within fenced\n' // Finalize the stream without sending a final AgentMessage, to flush any tail. chat.handle_codex_event(Event { id: "t1".into(), - msg: EventMsg::TaskComplete(TaskCompleteEvent { + msg: EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message: None, }), }); @@ -3781,7 +3781,7 @@ async fn chatwidget_tall() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; chat.handle_codex_event(Event { id: "t1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); diff --git a/codex-rs/tui2/src/chatwidget.rs b/codex-rs/tui2/src/chatwidget.rs index df5acb442a0..52e96f3d5c7 100644 --- a/codex-rs/tui2/src/chatwidget.rs +++ b/codex-rs/tui2/src/chatwidget.rs @@ -48,11 +48,11 @@ use codex_core::protocol::ReviewRequest; use codex_core::protocol::ReviewTarget; use codex_core::protocol::SkillsListEntry; use codex_core::protocol::StreamErrorEvent; -use codex_core::protocol::TaskCompleteEvent; use codex_core::protocol::TerminalInteractionEvent; use codex_core::protocol::TokenUsage; use codex_core::protocol::TokenUsageInfo; use codex_core::protocol::TurnAbortReason; +use codex_core::protocol::TurnCompleteEvent; use codex_core::protocol::TurnDiffEvent; use codex_core::protocol::UndoCompletedEvent; use codex_core::protocol::UndoStartedEvent; @@ -1912,8 +1912,8 @@ impl ChatWidget { self.on_agent_reasoning_final(); } EventMsg::AgentReasoningSectionBreak(_) => self.on_reasoning_section_break(), - EventMsg::TaskStarted(_) => self.on_task_started(), - EventMsg::TaskComplete(TaskCompleteEvent { last_agent_message }) => { + EventMsg::TurnStarted(_) => self.on_task_started(), + EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message }) => { self.on_task_complete(last_agent_message) } EventMsg::TokenCount(ev) => { diff --git a/codex-rs/tui2/src/chatwidget/tests.rs b/codex-rs/tui2/src/chatwidget/tests.rs index 9978911186e..45a4247f635 100644 --- a/codex-rs/tui2/src/chatwidget/tests.rs +++ b/codex-rs/tui2/src/chatwidget/tests.rs @@ -38,11 +38,11 @@ use codex_core::protocol::RateLimitWindow; use codex_core::protocol::ReviewRequest; use codex_core::protocol::ReviewTarget; use codex_core::protocol::StreamErrorEvent; -use codex_core::protocol::TaskCompleteEvent; -use codex_core::protocol::TaskStartedEvent; use codex_core::protocol::TokenCountEvent; use codex_core::protocol::TokenUsage; use codex_core::protocol::TokenUsageInfo; +use codex_core::protocol::TurnCompleteEvent; +use codex_core::protocol::TurnStartedEvent; use codex_core::protocol::UndoCompletedEvent; use codex_core::protocol::UndoStartedEvent; use codex_core::protocol::ViewImageToolCallEvent; @@ -1589,7 +1589,7 @@ async fn interrupted_turn_error_message_snapshot() { // Simulate an in-progress task so the widget is in a running state. chat.handle_codex_event(Event { id: "task-1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -2383,7 +2383,7 @@ async fn ui_snapshots_small_heights_task_running() { // Activate status line chat.handle_codex_event(Event { id: "task-1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -2414,7 +2414,7 @@ async fn status_widget_and_approval_modal_snapshot() { // Begin a running task so the status indicator would be active. chat.handle_codex_event(Event { id: "task-1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -2466,7 +2466,7 @@ async fn status_widget_active_snapshot() { // Activate the status indicator by simulating a task start. chat.handle_codex_event(Event { id: "task-1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3041,7 +3041,7 @@ async fn stream_recovery_restores_previous_status_header() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; chat.handle_codex_event(Event { id: "task".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3078,7 +3078,7 @@ async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() { // Begin turn chat.handle_codex_event(Event { id: "s1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3102,7 +3102,7 @@ async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() { // End turn chat.handle_codex_event(Event { id: "s1".into(), - msg: EventMsg::TaskComplete(TaskCompleteEvent { + msg: EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message: None, }), }); @@ -3272,7 +3272,7 @@ async fn chatwidget_exec_and_status_layout_vt100_snapshot() { }); chat.handle_codex_event(Event { id: "t1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3316,7 +3316,7 @@ async fn chatwidget_markdown_code_blocks_vt100_snapshot() { chat.handle_codex_event(Event { id: "t1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), }); @@ -3387,7 +3387,7 @@ printf 'fenced within fenced\n' // Finalize the stream without sending a final AgentMessage, to flush any tail. chat.handle_codex_event(Event { id: "t1".into(), - msg: EventMsg::TaskComplete(TaskCompleteEvent { + msg: EventMsg::TurnComplete(TurnCompleteEvent { last_agent_message: None, }), }); @@ -3404,7 +3404,7 @@ async fn chatwidget_tall() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await; chat.handle_codex_event(Event { id: "t1".into(), - msg: EventMsg::TaskStarted(TaskStartedEvent { + msg: EventMsg::TurnStarted(TurnStartedEvent { model_context_window: None, }), });