diff --git a/codex-rs/core/src/analytics_client.rs b/codex-rs/core/src/analytics_client.rs index 5d119ee977..3226b96169 100644 --- a/codex-rs/core/src/analytics_client.rs +++ b/codex-rs/core/src/analytics_client.rs @@ -30,8 +30,8 @@ pub(crate) struct TrackEventsContext { } #[derive(Clone)] -pub(crate) struct TurnMetadata { - pub(crate) turn_type: Option, +pub(crate) struct CodexTurnEvent { + pub(crate) submission_origin: Option, pub(crate) sandbox_policy: SandboxPolicy, pub(crate) reasoning_effort: Option, pub(crate) reasoning_summary: ReasoningSummary, @@ -41,7 +41,7 @@ pub(crate) struct TurnMetadata { #[derive(Clone, Copy, Debug, Serialize)] #[serde(rename_all = "snake_case")] -pub(crate) enum TurnType { +pub(crate) enum SubmissionOrigin { Prompt, PromptQueued, } @@ -54,7 +54,7 @@ pub(crate) enum TurnEventType { } #[derive(Clone, Copy)] -pub(crate) struct UserMessageMetadata { +pub(crate) struct CodexTurnSteerEvent { pub(crate) user_message_type: UserMessageType, } @@ -119,8 +119,8 @@ impl AnalyticsEventsQueue { TrackEventsJob::AppUsed(job) => { send_track_app_used(&auth_manager, job).await; } - TrackEventsJob::TurnStart(job) => { - send_track_turn_start(&auth_manager, job).await; + TrackEventsJob::TurnEvent(job) => { + send_track_turn_event(&auth_manager, job).await; } TrackEventsJob::TurnSteer(job) => { send_track_turn_steer(&auth_manager, job).await; @@ -238,19 +238,23 @@ impl AnalyticsEventsClient { ); } - pub(crate) fn track_turn_start(&self, tracking: TrackEventsContext, turn_start: TurnMetadata) { - track_turn_start( + pub(crate) fn track_turn_event( + &self, + tracking: TrackEventsContext, + turn_event: CodexTurnEvent, + ) { + track_turn_event( &self.queue, Arc::clone(&self.config), Some(tracking), - turn_start, + turn_event, ); } pub(crate) fn track_turn_steer( &self, tracking: TrackEventsContext, - turn_steer: UserMessageMetadata, + turn_steer: CodexTurnSteerEvent, ) { track_turn_steer( &self.queue, @@ -301,7 +305,7 @@ enum TrackEventsJob { SkillInvocations(TrackSkillInvocationsJob), AppMentioned(TrackAppMentionedJob), AppUsed(TrackAppUsedJob), - TurnStart(TrackTurnStartJob), + TurnEvent(TrackTurnEventJob), TurnSteer(TrackTurnSteerJob), PluginUsed(TrackPluginUsedJob), PluginInstalled(TrackPluginManagementJob), @@ -328,16 +332,16 @@ struct TrackAppUsedJob { app: AppInvocation, } -struct TrackTurnStartJob { +struct TrackTurnEventJob { config: Arc, tracking: TrackEventsContext, - turn_start: TurnMetadata, + turn_event: CodexTurnEvent, } struct TrackTurnSteerJob { config: Arc, tracking: TrackEventsContext, - turn_steer: UserMessageMetadata, + turn_steer: CodexTurnSteerEvent, } struct TrackPluginUsedJob { @@ -424,13 +428,13 @@ struct CodexAppUsedEventRequest { } #[derive(Serialize)] -struct CodexTurnEvent { +struct CodexTurnEventParams { thread_id: Option, turn_id: Option, product_client_id: Option, model_slug: Option, turn_event_type: TurnEventType, - turn_type: Option, + submission_origin: Option, user_message_type: Option, sandbox_policy: Option<&'static str>, reasoning_effort: Option, @@ -442,7 +446,7 @@ struct CodexTurnEvent { #[derive(Serialize)] struct CodexTurnEventRequest { event_type: &'static str, - event_params: CodexTurnEvent, + event_params: CodexTurnEventParams, } #[derive(Serialize)] @@ -546,11 +550,11 @@ pub(crate) fn track_app_used( queue.try_send(job); } -pub(crate) fn track_turn_start( +pub(crate) fn track_turn_event( queue: &AnalyticsEventsQueue, config: Arc, tracking: Option, - turn_start: TurnMetadata, + turn_event: CodexTurnEvent, ) { if config.analytics_enabled == Some(false) { return; @@ -558,10 +562,10 @@ pub(crate) fn track_turn_start( let Some(tracking) = tracking else { return; }; - let job = TrackEventsJob::TurnStart(TrackTurnStartJob { + let job = TrackEventsJob::TurnEvent(TrackTurnEventJob { config, tracking, - turn_start, + turn_event, }); queue.try_send(job); } @@ -570,7 +574,7 @@ pub(crate) fn track_turn_steer( queue: &AnalyticsEventsQueue, config: Arc, tracking: Option, - turn_steer: UserMessageMetadata, + turn_steer: CodexTurnSteerEvent, ) { if config.analytics_enabled == Some(false) { return; @@ -711,15 +715,15 @@ async fn send_track_app_used(auth_manager: &AuthManager, job: TrackAppUsedJob) { send_track_events(auth_manager, config, events).await; } -async fn send_track_turn_start(auth_manager: &AuthManager, job: TrackTurnStartJob) { - let TrackTurnStartJob { +async fn send_track_turn_event(auth_manager: &AuthManager, job: TrackTurnEventJob) { + let TrackTurnEventJob { config, tracking, - turn_start, + turn_event, } = job; let events = vec![TrackEventRequest::TurnEvent(CodexTurnEventRequest { event_type: "codex_turn_event", - event_params: codex_turn_start_event(&tracking, turn_start), + event_params: codex_turn_event_params(&tracking, turn_event), })]; send_track_events(auth_manager, config, events).await; @@ -733,7 +737,7 @@ async fn send_track_turn_steer(auth_manager: &AuthManager, job: TrackTurnSteerJo } = job; let events = vec![TrackEventRequest::TurnEvent(CodexTurnEventRequest { event_type: "codex_turn_event", - event_params: codex_turn_steer_event(&tracking, turn_steer), + event_params: codex_turn_steer_event_params(&tracking, turn_steer), })]; send_track_events(auth_manager, config, events).await; @@ -803,37 +807,37 @@ fn codex_app_metadata(tracking: &TrackEventsContext, app: AppInvocation) -> Code } } -fn codex_turn_start_event( +fn codex_turn_event_params( tracking: &TrackEventsContext, - turn_start: TurnMetadata, -) -> CodexTurnEvent { - CodexTurnEvent { + turn_event: CodexTurnEvent, +) -> CodexTurnEventParams { + CodexTurnEventParams { thread_id: Some(tracking.thread_id.clone()), turn_id: Some(tracking.turn_id.clone()), product_client_id: Some(crate::default_client::originator().value), model_slug: Some(tracking.model_slug.clone()), turn_event_type: TurnEventType::Start, - turn_type: turn_start.turn_type, + submission_origin: turn_event.submission_origin, user_message_type: None, - sandbox_policy: Some(sandbox_policy_mode(&turn_start.sandbox_policy)), - reasoning_effort: turn_start.reasoning_effort.map(|value| value.to_string()), - reasoning_summary: Some(turn_start.reasoning_summary.to_string()), - service_tier: turn_start.service_tier.map(|value| value.to_string()), - collaboration_mode: Some(collaboration_mode_mode(turn_start.collaboration_mode)), + sandbox_policy: Some(sandbox_policy_mode(&turn_event.sandbox_policy)), + reasoning_effort: turn_event.reasoning_effort.map(|value| value.to_string()), + reasoning_summary: Some(turn_event.reasoning_summary.to_string()), + service_tier: turn_event.service_tier.map(|value| value.to_string()), + collaboration_mode: Some(collaboration_mode_mode(turn_event.collaboration_mode)), } } -fn codex_turn_steer_event( +fn codex_turn_steer_event_params( tracking: &TrackEventsContext, - turn_steer: UserMessageMetadata, -) -> CodexTurnEvent { - CodexTurnEvent { + turn_steer: CodexTurnSteerEvent, +) -> CodexTurnEventParams { + CodexTurnEventParams { thread_id: Some(tracking.thread_id.clone()), turn_id: Some(tracking.turn_id.clone()), product_client_id: Some(crate::default_client::originator().value), model_slug: Some(tracking.model_slug.clone()), turn_event_type: TurnEventType::Steer, - turn_type: None, + submission_origin: None, user_message_type: Some(turn_steer.user_message_type), sandbox_policy: None, reasoning_effort: None, diff --git a/codex-rs/core/src/analytics_client_tests.rs b/codex-rs/core/src/analytics_client_tests.rs index 05a23164cf..941078936e 100644 --- a/codex-rs/core/src/analytics_client_tests.rs +++ b/codex-rs/core/src/analytics_client_tests.rs @@ -4,20 +4,20 @@ use super::CodexAppMentionedEventRequest; use super::CodexAppUsedEventRequest; use super::CodexPluginEventRequest; use super::CodexPluginUsedEventRequest; +use super::CodexTurnEvent; use super::CodexTurnEventRequest; +use super::CodexTurnSteerEvent; use super::InvocationType; +use super::SubmissionOrigin; use super::TrackEventRequest; use super::TrackEventsContext; use super::TurnEventType; -use super::TurnMetadata; -use super::TurnType; -use super::UserMessageMetadata; use super::UserMessageType; use super::codex_app_metadata; use super::codex_plugin_metadata; use super::codex_plugin_used_metadata; -use super::codex_turn_start_event; -use super::codex_turn_steer_event; +use super::codex_turn_event_params; +use super::codex_turn_steer_event_params; use super::normalize_path_for_skill_id; use crate::plugins::AppConnectorId; use crate::plugins::PluginCapabilitySummary; @@ -199,7 +199,7 @@ fn app_used_dedupe_is_keyed_by_turn_and_connector() { } #[test] -fn turn_start_event_serializes_expected_shape() { +fn turn_event_serializes_expected_shape() { let tracking = TrackEventsContext { model_slug: "gpt-5".to_string(), thread_id: "thread-2".to_string(), @@ -207,10 +207,10 @@ fn turn_start_event_serializes_expected_shape() { }; let event = TrackEventRequest::TurnEvent(CodexTurnEventRequest { event_type: "codex_turn_event", - event_params: codex_turn_start_event( + event_params: codex_turn_event_params( &tracking, - TurnMetadata { - turn_type: Some(TurnType::Prompt), + CodexTurnEvent { + submission_origin: Some(SubmissionOrigin::Prompt), sandbox_policy: SandboxPolicy::new_read_only_policy(), reasoning_effort: Some(ReasoningEffort::High), reasoning_summary: ReasoningSummary::Detailed, @@ -220,7 +220,7 @@ fn turn_start_event_serializes_expected_shape() { ), }); - let payload = serde_json::to_value(&event).expect("serialize turn metadata event"); + let payload = serde_json::to_value(&event).expect("serialize codex turn event"); assert_eq!( payload, @@ -232,7 +232,7 @@ fn turn_start_event_serializes_expected_shape() { "product_client_id": crate::default_client::originator().value, "model_slug": "gpt-5", "turn_event_type": "start", - "turn_type": "prompt", + "submission_origin": "prompt", "user_message_type": null, "sandbox_policy": "read_only", "reasoning_effort": "high", @@ -253,15 +253,15 @@ fn turn_steer_event_serializes_expected_shape() { }; let event = TrackEventRequest::TurnEvent(CodexTurnEventRequest { event_type: "codex_turn_event", - event_params: codex_turn_steer_event( + event_params: codex_turn_steer_event_params( &tracking, - UserMessageMetadata { + CodexTurnSteerEvent { user_message_type: UserMessageType::PromptSteering, }, ), }); - let payload = serde_json::to_value(&event).expect("serialize input message metadata event"); + let payload = serde_json::to_value(&event).expect("serialize codex turn steer event"); assert_eq!( payload, @@ -273,7 +273,7 @@ fn turn_steer_event_serializes_expected_shape() { "product_client_id": crate::default_client::originator().value, "model_slug": "gpt-5", "turn_event_type": "steer", - "turn_type": null, + "submission_origin": null, "user_message_type": "prompt_steering", "sandbox_policy": null, "reasoning_effort": null, diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 25dfeaa109..660b1474f7 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -14,10 +14,10 @@ use crate::agent::AgentStatus; use crate::agent::agent_status_from_event; use crate::analytics_client::AnalyticsEventsClient; use crate::analytics_client::AppInvocation; +use crate::analytics_client::CodexTurnEvent; +use crate::analytics_client::CodexTurnSteerEvent; use crate::analytics_client::InvocationType; -use crate::analytics_client::TurnMetadata; -use crate::analytics_client::TurnType; -use crate::analytics_client::UserMessageMetadata; +use crate::analytics_client::SubmissionOrigin; use crate::analytics_client::build_track_events_context; use crate::apps::render_apps_section; use crate::auth_env_telemetry::collect_auth_env_telemetry; @@ -3940,7 +3940,7 @@ impl Session { if let Some(tracking) = self.active_turn_tracking().await { self.services.analytics_events_client.track_turn_steer( tracking, - UserMessageMetadata { + CodexTurnSteerEvent { user_message_type: SubmittedUserMessageType::PromptSteering, }, ); @@ -5709,26 +5709,6 @@ pub(crate) async fn run_turn( .await; user_prompt_submit_outcome.additional_contexts }; - if !input.is_empty() { - let user_message_type = turn_context - .user_message_type - .unwrap_or(SubmittedUserMessageType::Prompt); - sess.services.analytics_events_client.track_turn_start( - tracking.clone(), - TurnMetadata { - turn_type: match user_message_type { - SubmittedUserMessageType::Prompt => Some(TurnType::Prompt), - SubmittedUserMessageType::PromptQueued => Some(TurnType::PromptQueued), - SubmittedUserMessageType::PromptSteering => None, - }, - sandbox_policy: turn_context.sandbox_policy.get().clone(), - reasoning_effort: turn_context.reasoning_effort, - reasoning_summary: turn_context.reasoning_summary, - service_tier: turn_context.config.service_tier, - collaboration_mode: turn_context.collaboration_mode.mode, - }, - ); - } sess.services .analytics_events_client .track_app_mentioned(tracking.clone(), mentioned_app_invocations); @@ -6042,6 +6022,27 @@ pub(crate) async fn run_turn( } } + if !input.is_empty() { + let user_message_type = turn_context + .user_message_type + .unwrap_or(SubmittedUserMessageType::Prompt); + sess.services.analytics_events_client.track_turn_event( + tracking, + CodexTurnEvent { + submission_origin: match user_message_type { + SubmittedUserMessageType::Prompt => Some(SubmissionOrigin::Prompt), + SubmittedUserMessageType::PromptQueued => Some(SubmissionOrigin::PromptQueued), + SubmittedUserMessageType::PromptSteering => None, + }, + sandbox_policy: turn_context.sandbox_policy.get().clone(), + reasoning_effort: turn_context.reasoning_effort, + reasoning_summary: turn_context.reasoning_summary, + service_tier: turn_context.config.service_tier, + collaboration_mode: turn_context.collaboration_mode.mode, + }, + ); + } + last_agent_message } diff --git a/codex-rs/core/src/codex_tests.rs b/codex-rs/core/src/codex_tests.rs index 5d6769e0ea..e6ea3b91f8 100644 --- a/codex-rs/core/src/codex_tests.rs +++ b/codex-rs/core/src/codex_tests.rs @@ -3037,6 +3037,7 @@ async fn user_turn_updates_approvals_reviewer() { final_output_json_schema: None, collaboration_mode: None, personality: config.personality, + user_message_type: None, }, ) .await; diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index c61631e5bf..5af047ddd2 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -731,6 +731,7 @@ impl TestCodex { service_tier, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/apply_patch_cli.rs b/codex-rs/core/tests/suite/apply_patch_cli.rs index d0cefcb616..ce54a36921 100644 --- a/codex-rs/core/tests/suite/apply_patch_cli.rs +++ b/codex-rs/core/tests/suite/apply_patch_cli.rs @@ -318,6 +318,7 @@ async fn apply_patch_cli_move_without_content_change_has_no_turn_diff( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -928,6 +929,7 @@ async fn apply_patch_shell_command_heredoc_with_cd_emits_turn_diff() -> Result<( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1010,6 +1012,7 @@ async fn apply_patch_shell_command_failure_propagates_error_and_skips_diff() -> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1162,6 +1165,7 @@ async fn apply_patch_emits_turn_diff_event_with_unified_diff( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1227,6 +1231,7 @@ async fn apply_patch_turn_diff_for_rename_with_content_change( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1300,6 +1305,7 @@ async fn apply_patch_aggregates_diff_across_multiple_tool_calls() -> Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1373,6 +1379,7 @@ async fn apply_patch_aggregates_diff_preserves_success_after_failure() -> Result service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/approvals.rs b/codex-rs/core/tests/suite/approvals.rs index 6ec05bedc2..45aca4e673 100644 --- a/codex-rs/core/tests/suite/approvals.rs +++ b/codex-rs/core/tests/suite/approvals.rs @@ -566,6 +566,7 @@ async fn submit_turn( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index 5da71f556b..1616fc10e2 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -1323,6 +1323,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re collaboration_mode: Some(collaboration_mode), final_output_json_schema: None, personality: None, + user_message_type: None, }) .await?; @@ -1437,6 +1438,7 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default() collaboration_mode: None, final_output_json_schema: None, personality: None, + user_message_type: None, }) .await .unwrap(); diff --git a/codex-rs/core/tests/suite/code_mode.rs b/codex-rs/core/tests/suite/code_mode.rs index fa8229ecc3..2823afb997 100644 --- a/codex-rs/core/tests/suite/code_mode.rs +++ b/codex-rs/core/tests/suite/code_mode.rs @@ -2327,6 +2327,7 @@ text( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/collaboration_instructions.rs b/codex-rs/core/tests/suite/collaboration_instructions.rs index 1517d9968c..339213c2ed 100644 --- a/codex-rs/core/tests/suite/collaboration_instructions.rs +++ b/codex-rs/core/tests/suite/collaboration_instructions.rs @@ -191,6 +191,7 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> { collaboration_mode: Some(collaboration_mode), final_output_json_schema: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -307,6 +308,7 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu collaboration_mode: Some(turn_mode), final_output_json_schema: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; diff --git a/codex-rs/core/tests/suite/compact.rs b/codex-rs/core/tests/suite/compact.rs index a54d740111..763b67a987 100644 --- a/codex-rs/core/tests/suite/compact.rs +++ b/codex-rs/core/tests/suite/compact.rs @@ -1666,6 +1666,7 @@ async fn auto_compact_runs_after_resume_when_token_usage_is_over_limit() { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await .unwrap(); @@ -1757,6 +1758,7 @@ async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await .expect("submit first user turn"); @@ -1782,6 +1784,7 @@ async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await .expect("submit second user turn"); @@ -1893,6 +1896,7 @@ async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await .expect("submit pre-resume turn"); @@ -1942,6 +1946,7 @@ async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await .expect("submit resumed user turn"); @@ -3145,6 +3150,7 @@ async fn snapshot_request_shape_pre_turn_compaction_strips_incoming_model_switch service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await .expect("submit first user turn"); @@ -3170,6 +3176,7 @@ async fn snapshot_request_shape_pre_turn_compaction_strips_incoming_model_switch service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await .expect("submit second user turn"); diff --git a/codex-rs/core/tests/suite/exec_policy.rs b/codex-rs/core/tests/suite/exec_policy.rs index fb055c970f..bae7255d79 100644 --- a/codex-rs/core/tests/suite/exec_policy.rs +++ b/codex-rs/core/tests/suite/exec_policy.rs @@ -59,6 +59,7 @@ async fn submit_user_turn( service_tier: None, collaboration_mode, personality: None, + user_message_type: None, }) .await?; Ok(()) @@ -140,6 +141,7 @@ async fn execpolicy_blocks_shell_invocation() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/image_rollout.rs b/codex-rs/core/tests/suite/image_rollout.rs index 1526fe11a2..0020b9e329 100644 --- a/codex-rs/core/tests/suite/image_rollout.rs +++ b/codex-rs/core/tests/suite/image_rollout.rs @@ -130,6 +130,7 @@ async fn copy_paste_local_image_persists_rollout_request_shape() -> anyhow::Resu service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -214,6 +215,7 @@ async fn drag_drop_image_persists_rollout_request_shape() -> anyhow::Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/items.rs b/codex-rs/core/tests/suite/items.rs index 0c1fc4e7de..7bd7c325ee 100644 --- a/codex-rs/core/tests/suite/items.rs +++ b/codex-rs/core/tests/suite/items.rs @@ -163,7 +163,7 @@ async fn user_message_item_is_emitted() -> anyhow::Result<()> { } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn user_turn_tracks_turn_start_analytics() -> anyhow::Result<()> { +async fn user_turn_tracks_turn_event_analytics() -> anyhow::Result<()> { skip_if_no_network!(Ok(())); let server = start_mock_server().await; @@ -210,6 +210,7 @@ async fn user_turn_tracks_turn_start_analytics() -> anyhow::Result<()> { }, }), personality: None, + user_message_type: None, }) .await?; @@ -243,7 +244,7 @@ async fn user_turn_tracks_turn_start_analytics() -> anyhow::Result<()> { let event_params = &event["event_params"]; - assert_eq!(event_params["turn_type"], "prompt"); + assert_eq!(event_params["submission_origin"], "prompt"); assert_eq!(event_params["sandbox_policy"], "read_only"); assert_eq!( event_params["product_client_id"], @@ -261,7 +262,7 @@ async fn user_turn_tracks_turn_start_analytics() -> anyhow::Result<()> { } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn user_turn_tracks_turn_start_prompt_type_analytics() -> anyhow::Result<()> { +async fn user_turn_tracks_turn_event_prompt_type_analytics() -> anyhow::Result<()> { skip_if_no_network!(Ok(())); let server = start_mock_server().await; @@ -308,6 +309,7 @@ async fn user_turn_tracks_turn_start_prompt_type_analytics() -> anyhow::Result<( }, }), personality: None, + user_message_type: None, }) .await?; @@ -315,12 +317,12 @@ async fn user_turn_tracks_turn_start_prompt_type_analytics() -> anyhow::Result<( let event = wait_for_analytics_event(&server, "codex_turn_event", |event| { event["event_params"]["turn_event_type"] == "start" - && event["event_params"]["turn_type"] == "prompt" + && event["event_params"]["submission_origin"] == "prompt" }) .await; let event_params = &event["event_params"]; - assert_eq!(event_params["turn_type"], "prompt"); + assert_eq!(event_params["submission_origin"], "prompt"); assert_eq!( event_params["product_client_id"], serde_json::json!(codex_core::default_client::originator().value) @@ -396,6 +398,7 @@ async fn user_turn_tracks_turn_steer_analytics() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -857,6 +860,7 @@ async fn plan_mode_emits_plan_item_from_proposed_plan_block() -> anyhow::Result< service_tier: None, collaboration_mode: Some(collaboration_mode), personality: None, + user_message_type: None, }) .await?; @@ -934,6 +938,7 @@ async fn plan_mode_strips_plan_from_agent_messages() -> anyhow::Result<()> { service_tier: None, collaboration_mode: Some(collaboration_mode), personality: None, + user_message_type: None, }) .await?; @@ -1043,6 +1048,7 @@ async fn plan_mode_streaming_citations_are_stripped_across_added_deltas_and_done service_tier: None, collaboration_mode: Some(collaboration_mode), personality: None, + user_message_type: None, }) .await?; @@ -1230,6 +1236,7 @@ async fn plan_mode_streaming_proposed_plan_tag_split_across_added_and_delta_is_p service_tier: None, collaboration_mode: Some(collaboration_mode), personality: None, + user_message_type: None, }) .await?; @@ -1344,6 +1351,7 @@ async fn plan_mode_handles_missing_plan_close_tag() -> anyhow::Result<()> { service_tier: None, collaboration_mode: Some(collaboration_mode), personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/json_result.rs b/codex-rs/core/tests/suite/json_result.rs index 3b6f3e3f9c..c3efc4bf6f 100644 --- a/codex-rs/core/tests/suite/json_result.rs +++ b/codex-rs/core/tests/suite/json_result.rs @@ -88,6 +88,7 @@ async fn codex_returns_json_result(model: String) -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/live_reload.rs b/codex-rs/core/tests/suite/live_reload.rs index 663cf47488..135e292184 100644 --- a/codex-rs/core/tests/suite/live_reload.rs +++ b/codex-rs/core/tests/suite/live_reload.rs @@ -69,6 +69,7 @@ async fn submit_skill_turn(test: &TestCodex, skill_path: PathBuf, prompt: &str) service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/model_switching.rs b/codex-rs/core/tests/suite/model_switching.rs index a7c5ceb0d2..b948231a2e 100644 --- a/codex-rs/core/tests/suite/model_switching.rs +++ b/codex-rs/core/tests/suite/model_switching.rs @@ -134,6 +134,7 @@ async fn model_change_appends_model_instructions_developer_message() -> Result<( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -171,6 +172,7 @@ async fn model_change_appends_model_instructions_developer_message() -> Result<( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -231,6 +233,7 @@ async fn model_and_personality_change_only_appends_model_instructions() -> Resul service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -268,6 +271,7 @@ async fn model_and_personality_change_only_appends_model_instructions() -> Resul service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -410,6 +414,7 @@ async fn model_change_from_image_to_text_strips_prior_image_content() -> Result< service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -431,6 +436,7 @@ async fn model_change_from_image_to_text_strips_prior_image_content() -> Result< service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -539,6 +545,7 @@ async fn generated_image_is_replayed_for_image_capable_models() -> Result<()> { summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -560,6 +567,7 @@ async fn generated_image_is_replayed_for_image_capable_models() -> Result<()> { summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -671,6 +679,7 @@ async fn model_change_from_generated_image_to_text_preserves_prior_generated_ima summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -692,6 +701,7 @@ async fn model_change_from_generated_image_to_text_preserves_prior_generated_ima summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -805,6 +815,7 @@ async fn thread_rollback_after_generated_image_drops_entire_image_turn_history() summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -834,6 +845,7 @@ async fn thread_rollback_after_generated_image_drops_entire_image_turn_history() summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -989,6 +1001,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result< service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1048,6 +1061,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result< service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/model_visible_layout.rs b/codex-rs/core/tests/suite/model_visible_layout.rs index 49f635432f..3794c36db7 100644 --- a/codex-rs/core/tests/suite/model_visible_layout.rs +++ b/codex-rs/core/tests/suite/model_visible_layout.rs @@ -129,6 +129,7 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |event| { @@ -153,6 +154,7 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> { service_tier: None, collaboration_mode: None, personality: Some(Personality::Friendly), + user_message_type: None, }) .await?; wait_for_event(&test.codex, |event| { @@ -232,6 +234,7 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |event| { @@ -256,6 +259,7 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |event| { @@ -366,6 +370,7 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul service_tier: None, collaboration_mode: None, personality: Some(Personality::Friendly), + user_message_type: None, }) .await?; wait_for_event(&resumed.codex, |event| { diff --git a/codex-rs/core/tests/suite/models_cache_ttl.rs b/codex-rs/core/tests/suite/models_cache_ttl.rs index 3d5904bd7a..e85da8e65d 100644 --- a/codex-rs/core/tests/suite/models_cache_ttl.rs +++ b/codex-rs/core/tests/suite/models_cache_ttl.rs @@ -104,6 +104,7 @@ async fn renews_cache_ttl_on_matching_models_etag() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/models_etag_responses.rs b/codex-rs/core/tests/suite/models_etag_responses.rs index 272c820caf..2af4ccec2b 100644 --- a/codex-rs/core/tests/suite/models_etag_responses.rs +++ b/codex-rs/core/tests/suite/models_etag_responses.rs @@ -110,6 +110,7 @@ async fn refresh_models_on_models_etag_mismatch_and_avoid_duplicate_models_fetch service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/personality.rs b/codex-rs/core/tests/suite/personality.rs index ed4da07168..d1af8db9c1 100644 --- a/codex-rs/core/tests/suite/personality.rs +++ b/codex-rs/core/tests/suite/personality.rs @@ -111,6 +111,7 @@ async fn user_turn_personality_none_does_not_add_update_message() -> anyhow::Res service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -162,6 +163,7 @@ async fn config_personality_some_sets_instructions_template() -> anyhow::Result< service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -220,6 +222,7 @@ async fn config_personality_none_sends_no_personality() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -284,6 +287,7 @@ async fn default_personality_is_pragmatic_without_config_toml() -> anyhow::Resul service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -336,6 +340,7 @@ async fn user_turn_personality_some_adds_update_message() -> anyhow::Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -374,6 +379,7 @@ async fn user_turn_personality_some_adds_update_message() -> anyhow::Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -441,6 +447,7 @@ async fn user_turn_personality_same_value_does_not_add_update_message() -> anyho service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -479,6 +486,7 @@ async fn user_turn_personality_same_value_does_not_add_update_message() -> anyho service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -559,6 +567,7 @@ async fn user_turn_personality_skips_if_feature_disabled() -> anyhow::Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -597,6 +606,7 @@ async fn user_turn_personality_skips_if_feature_disabled() -> anyhow::Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -714,6 +724,7 @@ async fn remote_model_friendly_personality_instructions_with_feature() -> anyhow service_tier: None, collaboration_mode: None, personality: Some(Personality::Friendly), + user_message_type: None, }) .await?; @@ -833,6 +844,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() - service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -871,6 +883,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() - service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/prompt_caching.rs b/codex-rs/core/tests/suite/prompt_caching.rs index 9be83e6bb0..9a83f437b0 100644 --- a/codex-rs/core/tests/suite/prompt_caching.rs +++ b/codex-rs/core/tests/suite/prompt_caching.rs @@ -712,6 +712,7 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res collaboration_mode: None, final_output_json_schema: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -825,6 +826,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a collaboration_mode: None, final_output_json_schema: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -846,6 +848,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a collaboration_mode: None, final_output_json_schema: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -951,6 +954,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu collaboration_mode: None, final_output_json_schema: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -972,6 +976,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu collaboration_mode: None, final_output_json_schema: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; diff --git a/codex-rs/core/tests/suite/remote_models.rs b/codex-rs/core/tests/suite/remote_models.rs index 83d911533d..8a2611a6da 100644 --- a/codex-rs/core/tests/suite/remote_models.rs +++ b/codex-rs/core/tests/suite/remote_models.rs @@ -181,6 +181,7 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -244,6 +245,7 @@ async fn namespaced_model_slug_uses_catalog_metadata_without_fallback_warning() service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -404,6 +406,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -623,6 +626,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/request_permissions.rs b/codex-rs/core/tests/suite/request_permissions.rs index 7c16599bf0..395ef0d952 100644 --- a/codex-rs/core/tests/suite/request_permissions.rs +++ b/codex-rs/core/tests/suite/request_permissions.rs @@ -201,6 +201,7 @@ async fn submit_turn( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; Ok(()) diff --git a/codex-rs/core/tests/suite/request_permissions_tool.rs b/codex-rs/core/tests/suite/request_permissions_tool.rs index 14506f4a41..545bdabf5b 100644 --- a/codex-rs/core/tests/suite/request_permissions_tool.rs +++ b/codex-rs/core/tests/suite/request_permissions_tool.rs @@ -153,6 +153,7 @@ async fn submit_turn( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; Ok(()) diff --git a/codex-rs/core/tests/suite/request_user_input.rs b/codex-rs/core/tests/suite/request_user_input.rs index 8e30b37c21..59f59500bd 100644 --- a/codex-rs/core/tests/suite/request_user_input.rs +++ b/codex-rs/core/tests/suite/request_user_input.rs @@ -153,6 +153,7 @@ async fn request_user_input_round_trip_for_mode(mode: ModeKind) -> anyhow::Resul }, }), personality: None, + user_message_type: None, }) .await?; @@ -264,6 +265,7 @@ where service_tier: None, collaboration_mode: Some(collaboration_mode), personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index 6cbf9521ba..d85b00bb88 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -137,6 +137,7 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -307,6 +308,7 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -511,6 +513,7 @@ async fn stdio_image_responses_are_sanitized_for_text_only_model() -> anyhow::Re service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -626,6 +629,7 @@ async fn stdio_server_propagates_whitelisted_env_vars() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -788,6 +792,7 @@ async fn streamable_http_tool_call_round_trip() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1035,6 +1040,7 @@ async fn streamable_http_with_oauth_round_trip_impl() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/safety_check_downgrade.rs b/codex-rs/core/tests/suite/safety_check_downgrade.rs index 51a88ef16a..65fcc5b9e0 100644 --- a/codex-rs/core/tests/suite/safety_check_downgrade.rs +++ b/codex-rs/core/tests/suite/safety_check_downgrade.rs @@ -53,6 +53,7 @@ async fn openai_model_header_mismatch_emits_warning_event_and_warning_item() -> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -152,6 +153,7 @@ async fn response_model_field_mismatch_emits_warning_when_header_matches_request service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -238,6 +240,7 @@ async fn openai_model_header_mismatch_only_emits_one_warning_per_turn() -> Resul service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -288,6 +291,7 @@ async fn openai_model_header_casing_only_mismatch_does_not_warn() -> Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/shell_snapshot.rs b/codex-rs/core/tests/suite/shell_snapshot.rs index 55bb0ac284..31d3eef0d8 100644 --- a/codex-rs/core/tests/suite/shell_snapshot.rs +++ b/codex-rs/core/tests/suite/shell_snapshot.rs @@ -172,6 +172,7 @@ async fn run_snapshot_command_with_options( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -263,6 +264,7 @@ async fn run_shell_command_snapshot_with_options( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -334,6 +336,7 @@ async fn run_tool_turn_on_harness( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -566,6 +569,7 @@ async fn shell_command_snapshot_still_intercepts_apply_patch() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/skill_approval.rs b/codex-rs/core/tests/suite/skill_approval.rs index 5a50e09cee..e34ee0d23c 100644 --- a/codex-rs/core/tests/suite/skill_approval.rs +++ b/codex-rs/core/tests/suite/skill_approval.rs @@ -73,6 +73,7 @@ async fn submit_turn_with_policies( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; Ok(()) diff --git a/codex-rs/core/tests/suite/skills.rs b/codex-rs/core/tests/suite/skills.rs index 388618b56a..070ef0f40d 100644 --- a/codex-rs/core/tests/suite/skills.rs +++ b/codex-rs/core/tests/suite/skills.rs @@ -82,6 +82,7 @@ async fn user_turn_includes_skill_instructions() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/sqlite_state.rs b/codex-rs/core/tests/suite/sqlite_state.rs index 2df92dbf95..29350c938f 100644 --- a/codex-rs/core/tests/suite/sqlite_state.rs +++ b/codex-rs/core/tests/suite/sqlite_state.rs @@ -403,6 +403,7 @@ async fn mcp_call_marks_thread_memory_mode_polluted_when_configured() -> Result< service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; wait_for_event(&test.codex, |event| { diff --git a/codex-rs/core/tests/suite/tool_harness.rs b/codex-rs/core/tests/suite/tool_harness.rs index 9594195a5b..978671d304 100644 --- a/codex-rs/core/tests/suite/tool_harness.rs +++ b/codex-rs/core/tests/suite/tool_harness.rs @@ -93,6 +93,7 @@ async fn shell_tool_executes_command_and_streams_output() -> anyhow::Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -164,6 +165,7 @@ async fn update_plan_tool_emits_plan_update_event() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -245,6 +247,7 @@ async fn update_plan_tool_rejects_malformed_payload() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -341,6 +344,7 @@ async fn apply_patch_tool_executes_and_emits_patch_events() -> anyhow::Result<() service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -445,6 +449,7 @@ async fn apply_patch_reports_parse_diagnostics() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/tool_parallelism.rs b/codex-rs/core/tests/suite/tool_parallelism.rs index faff0b2e09..37e2a1ca83 100644 --- a/codex-rs/core/tests/suite/tool_parallelism.rs +++ b/codex-rs/core/tests/suite/tool_parallelism.rs @@ -50,6 +50,7 @@ async fn run_turn(test: &TestCodex, prompt: &str) -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -367,6 +368,7 @@ async fn shell_tools_start_before_response_completed_when_stream_delayed() -> an service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/truncation.rs b/codex-rs/core/tests/suite/truncation.rs index f10567de24..3b47a952df 100644 --- a/codex-rs/core/tests/suite/truncation.rs +++ b/codex-rs/core/tests/suite/truncation.rs @@ -494,6 +494,7 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/unified_exec.rs b/codex-rs/core/tests/suite/unified_exec.rs index c07fd20e5e..52b282ad8c 100644 --- a/codex-rs/core/tests/suite/unified_exec.rs +++ b/codex-rs/core/tests/suite/unified_exec.rs @@ -200,6 +200,7 @@ async fn unified_exec_intercepts_apply_patch_exec_command() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -334,6 +335,7 @@ async fn unified_exec_emits_exec_command_begin_event() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -417,6 +419,7 @@ async fn unified_exec_resolves_relative_workdir() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -503,6 +506,7 @@ async fn unified_exec_respects_workdir_override() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -601,6 +605,7 @@ async fn unified_exec_emits_exec_command_end_event() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -681,6 +686,7 @@ async fn unified_exec_emits_output_delta_for_exec_command() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -762,6 +768,7 @@ async fn unified_exec_full_lifecycle_with_background_end_event() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -897,6 +904,7 @@ async fn unified_exec_emits_terminal_interaction_for_write_stdin() -> Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1039,6 +1047,7 @@ async fn unified_exec_terminal_interaction_captures_delayed_output() -> Result<( service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1204,6 +1213,7 @@ async fn unified_exec_emits_one_begin_and_one_end_event() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1307,6 +1317,7 @@ async fn exec_command_reports_chunk_and_exit_metadata() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1430,6 +1441,7 @@ async fn unified_exec_defaults_to_pipe() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1525,6 +1537,7 @@ async fn unified_exec_can_enable_tty() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1611,6 +1624,7 @@ async fn unified_exec_respects_early_exit_notifications() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1747,6 +1761,7 @@ async fn write_stdin_returns_exit_metadata_and_clears_session() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1920,6 +1935,7 @@ async fn unified_exec_emits_end_event_when_session_dies_via_stdin() -> Result<() service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -2002,6 +2018,7 @@ async fn unified_exec_keeps_long_running_session_after_turn_end() -> Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -2095,6 +2112,7 @@ async fn unified_exec_interrupt_preserves_long_running_session() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -2204,6 +2222,7 @@ async fn unified_exec_reuses_session_via_stdin() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -2344,6 +2363,7 @@ PY service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; // This is a worst case scenario for the truncate logic. @@ -2463,6 +2483,7 @@ async fn unified_exec_timeout_and_followup_poll() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -2564,6 +2585,7 @@ PY service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -2665,6 +2687,7 @@ async fn unified_exec_runs_under_sandbox() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -2774,6 +2797,7 @@ async fn unified_exec_python_prompt_under_seatbelt() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -2874,6 +2898,7 @@ async fn unified_exec_runs_on_all_platforms() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -3014,6 +3039,7 @@ async fn unified_exec_prunes_exited_sessions_first() -> Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/user_shell_cmd.rs b/codex-rs/core/tests/suite/user_shell_cmd.rs index 801ff76274..52f7314b30 100644 --- a/codex-rs/core/tests/suite/user_shell_cmd.rs +++ b/codex-rs/core/tests/suite/user_shell_cmd.rs @@ -184,6 +184,7 @@ async fn user_shell_command_does_not_replace_active_turn() -> anyhow::Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/view_image.rs b/codex-rs/core/tests/suite/view_image.rs index 732d6b29eb..906cb33b75 100644 --- a/codex-rs/core/tests/suite/view_image.rs +++ b/codex-rs/core/tests/suite/view_image.rs @@ -178,6 +178,7 @@ async fn user_turn_with_local_image_attaches_image() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -287,6 +288,7 @@ async fn view_image_tool_attaches_local_image() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -428,6 +430,7 @@ async fn view_image_tool_can_preserve_original_resolution_when_requested_on_gpt5 summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -527,6 +530,7 @@ async fn view_image_tool_errors_clearly_for_unsupported_detail_values() -> anyho summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -619,6 +623,7 @@ async fn view_image_tool_treats_null_detail_as_omitted() -> anyhow::Result<()> { summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -719,6 +724,7 @@ async fn view_image_tool_resizes_when_model_lacks_original_detail_support() -> a summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -830,6 +836,7 @@ async fn view_image_tool_does_not_force_original_resolution_with_capability_feat summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -932,6 +939,7 @@ await codex.emitImage(out); service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1052,6 +1060,7 @@ console.log(out.type); summary: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1145,6 +1154,7 @@ async fn view_image_tool_errors_when_path_is_directory() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1221,6 +1231,7 @@ async fn view_image_tool_errors_for_non_image_files() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1302,6 +1313,7 @@ async fn view_image_tool_errors_when_file_missing() -> anyhow::Result<()> { service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1425,6 +1437,7 @@ async fn view_image_tool_returns_unsupported_message_for_text_only_model() -> an service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; @@ -1500,6 +1513,7 @@ async fn replaces_invalid_local_image_after_bad_request() -> anyhow::Result<()> service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/core/tests/suite/websocket_fallback.rs b/codex-rs/core/tests/suite/websocket_fallback.rs index e7f33df148..e9ec81f984 100644 --- a/codex-rs/core/tests/suite/websocket_fallback.rs +++ b/codex-rs/core/tests/suite/websocket_fallback.rs @@ -164,6 +164,7 @@ async fn websocket_fallback_hides_first_websocket_retry_stream_error() -> Result service_tier: None, collaboration_mode: None, personality: None, + user_message_type: None, }) .await?; diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index ade9235b40..dfe78ef785 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -5269,6 +5269,7 @@ impl ChatWidget { final_output_json_schema: None, collaboration_mode, personality, + user_message_type: None, }; if !self.submit_op(op) {