From e811234484d8a6b07c4c1018de0a91661ef01841 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 18 May 2026 19:41:33 -0700 Subject: [PATCH 1/2] [2 of 7] Remove UserInputWithTurnContext (#23081) **Stack position:** [2 of 7] ## Summary This PR removes the overlapping `Op::UserInputWithTurnContext` variant now that `Op::UserInput` can carry thread settings overrides directly. ## Stack 1. [1 of 7] [Add thread settings to UserInput](https://github.com/openai/codex/pull/23080) 2. [2 of 7] [Remove UserInputWithTurnContext](https://github.com/openai/codex/pull/23081) (this PR) 3. [3 of 7] [Remove UserTurn](https://github.com/openai/codex/pull/23075) 4. [4 of 7] [Placeholder for OverrideTurnContext cleanup](https://github.com/openai/codex/pull/23087) 5. [5 of 7] [Replace OverrideTurnContext with ThreadSettings](https://github.com/openai/codex/pull/22508) 6. [6 of 7] [Add app-server thread settings API](https://github.com/openai/codex/pull/22509) 7. [7 of 7] [Sync TUI thread settings](https://github.com/openai/codex/pull/22510) --- .../src/request_processors/turn_processor.rs | 54 +++++------ codex-rs/core/src/session/handlers.rs | 50 +---------- codex-rs/core/src/session/tests.rs | 25 ------ codex-rs/protocol/src/protocol.rs | 90 ------------------- 4 files changed, 25 insertions(+), 194 deletions(-) diff --git a/codex-rs/app-server/src/request_processors/turn_processor.rs b/codex-rs/app-server/src/request_processors/turn_processor.rs index 3de4ebbcc3..d383f64d4e 100644 --- a/codex-rs/app-server/src/request_processors/turn_processor.rs +++ b/codex-rs/app-server/src/request_processors/turn_processor.rs @@ -502,37 +502,31 @@ impl TurnRequestProcessor { })?; } + let thread_settings = codex_protocol::protocol::ThreadSettingsOverrides { + cwd, + workspace_roots: runtime_workspace_roots, + profile_workspace_roots, + approval_policy, + approvals_reviewer, + sandbox_policy, + permission_profile, + active_permission_profile, + windows_sandbox_level: None, + model, + effort, + summary, + service_tier, + collaboration_mode, + personality, + }; + // Start the turn by submitting the user input. Return its submission id as turn_id. - let turn_op = if has_any_overrides { - Op::UserInputWithTurnContext { - items: mapped_items, - environments: environment_selections, - final_output_json_schema: params.output_schema, - responsesapi_client_metadata: params.responsesapi_client_metadata, - cwd, - workspace_roots: runtime_workspace_roots, - profile_workspace_roots, - approval_policy, - approvals_reviewer, - sandbox_policy, - permission_profile, - active_permission_profile, - windows_sandbox_level: None, - model, - effort, - summary, - service_tier, - collaboration_mode, - personality, - } - } else { - Op::UserInput { - items: mapped_items, - environments: environment_selections, - final_output_json_schema: params.output_schema, - responsesapi_client_metadata: params.responsesapi_client_metadata, - thread_settings: Default::default(), - } + let turn_op = Op::UserInput { + items: mapped_items, + environments: environment_selections, + final_output_json_schema: params.output_schema, + responsesapi_client_metadata: params.responsesapi_client_metadata, + thread_settings, }; let turn_id = self .submit_core_op(&request_id, thread.as_ref(), turn_op) diff --git a/codex-rs/core/src/session/handlers.rs b/codex-rs/core/src/session/handlers.rs index e684ae6f3b..f8a4fa2920 100644 --- a/codex-rs/core/src/session/handlers.rs +++ b/codex-rs/core/src/session/handlers.rs @@ -164,52 +164,6 @@ pub(super) async fn user_input_or_turn_inner( None, ) } - Op::UserInputWithTurnContext { - cwd, - workspace_roots, - profile_workspace_roots, - approval_policy, - approvals_reviewer, - sandbox_policy, - permission_profile, - active_permission_profile, - windows_sandbox_level, - model, - effort, - summary, - service_tier, - final_output_json_schema, - items, - responsesapi_client_metadata, - collaboration_mode, - personality, - environments, - } => { - let mut updates = thread_settings_update( - sess, - ThreadSettingsOverrides { - cwd, - workspace_roots, - profile_workspace_roots, - approval_policy, - approvals_reviewer, - sandbox_policy, - permission_profile, - active_permission_profile, - windows_sandbox_level, - model, - effort, - summary, - service_tier, - collaboration_mode, - personality, - }, - ) - .await; - updates.final_output_json_schema = Some(final_output_json_schema); - updates.environments = environments; - (items, updates, responsesapi_client_metadata) - } Op::UserInput { items, environments, @@ -872,9 +826,7 @@ pub(super) async fn submission_loop( .await; false } - Op::UserInput { .. } - | Op::UserInputWithTurnContext { .. } - | Op::UserTurn { .. } => { + Op::UserInput { .. } | Op::UserTurn { .. } => { user_input_or_turn(&sess, sub.id.clone(), sub.op).await; false } diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index 46e93b16f4..a6d82e211d 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -5227,31 +5227,6 @@ fn op_kind_distinguishes_turn_ops() { .kind(), "user_input" ); - assert_eq!( - Op::UserInputWithTurnContext { - environments: None, - items: vec![], - final_output_json_schema: None, - responsesapi_client_metadata: None, - cwd: None, - workspace_roots: None, - profile_workspace_roots: None, - approval_policy: None, - approvals_reviewer: None, - sandbox_policy: None, - permission_profile: None, - active_permission_profile: None, - windows_sandbox_level: None, - model: None, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, - } - .kind(), - "user_input_with_turn_context" - ); } #[tokio::test] diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index cd9078a85c..77d862086c 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -518,95 +518,6 @@ pub enum Op { thread_settings: ThreadSettingsOverrides, }, - /// Similar to [`Op::UserInput`], but first applies persistent thread-settings - /// overrides in the same queued operation. This preserves submission order - /// and prevents the input from starting if the overrides are rejected. - UserInputWithTurnContext { - /// User input items, see `InputItem` - items: Vec, - /// Optional turn-scoped environment selections. - #[serde(default, skip_serializing_if = "Option::is_none")] - environments: Option>, - /// Optional JSON Schema used to constrain the final assistant message for this turn. - #[serde(skip_serializing_if = "Option::is_none")] - final_output_json_schema: Option, - /// Optional turn-scoped Responses API `client_metadata`. - #[serde(default, skip_serializing_if = "Option::is_none")] - responsesapi_client_metadata: Option>, - - /// Updated `cwd` for sandbox/tool calls. - #[serde(skip_serializing_if = "Option::is_none")] - cwd: Option, - - /// Updated runtime workspace roots used to materialize symbolic - /// `:workspace_roots` filesystem permissions. - #[serde(skip_serializing_if = "Option::is_none")] - workspace_roots: Option>, - - /// Updated profile-defined workspace roots for status summaries and - /// per-turn config reconstruction. - #[serde(skip_serializing_if = "Option::is_none")] - profile_workspace_roots: Option>, - - /// Updated command approval policy. - #[serde(skip_serializing_if = "Option::is_none")] - approval_policy: Option, - - /// Updated approval reviewer for future approval prompts. - #[serde(skip_serializing_if = "Option::is_none")] - approvals_reviewer: Option, - - /// Updated sandbox policy for tool calls. - #[serde(skip_serializing_if = "Option::is_none")] - sandbox_policy: Option, - - /// Updated permissions profile for tool calls. - #[serde(skip_serializing_if = "Option::is_none")] - permission_profile: Option, - - /// Named or built-in profile that produced `permission_profile`, if - /// the update selected a profile rather than supplying raw - /// permissions. - #[serde(skip_serializing_if = "Option::is_none")] - active_permission_profile: Option, - - /// Updated Windows sandbox mode for tool execution. - #[serde(skip_serializing_if = "Option::is_none")] - windows_sandbox_level: Option, - - /// Updated model slug. When set, the model info is derived - /// automatically. - #[serde(skip_serializing_if = "Option::is_none")] - model: Option, - - /// Updated reasoning effort (honored only for reasoning-capable models). - /// - /// Use `Some(Some(_))` to set a specific effort, `Some(None)` to clear - /// the effort, or `None` to leave the existing value unchanged. - #[serde(skip_serializing_if = "Option::is_none")] - effort: Option>, - - /// Updated reasoning summary preference (honored only for reasoning-capable models). - #[serde(skip_serializing_if = "Option::is_none")] - summary: Option, - - /// Updated service tier preference for future turns. - /// - /// Use `Some(Some(_))` to set a specific tier, `Some(None)` to clear the - /// preference, or `None` to leave the existing value unchanged. - #[serde(skip_serializing_if = "Option::is_none")] - service_tier: Option>, - - /// EXPERIMENTAL - set a pre-set collaboration mode. - /// Takes precedence over model, effort, and developer instructions if set. - #[serde(skip_serializing_if = "Option::is_none")] - collaboration_mode: Option, - - /// Updated personality preference. - #[serde(skip_serializing_if = "Option::is_none")] - personality: Option, - }, - /// Similar to [`Op::UserInput`], but contains additional context required /// for a turn of a [`crate::codex_thread::CodexThread`]. UserTurn { @@ -932,7 +843,6 @@ impl Op { Self::RealtimeConversationClose => "realtime_conversation_close", Self::RealtimeConversationListVoices => "realtime_conversation_list_voices", Self::UserInput { .. } => "user_input", - Self::UserInputWithTurnContext { .. } => "user_input_with_turn_context", Self::UserTurn { .. } => "user_turn", Self::InterAgentCommunication { .. } => "inter_agent_communication", Self::OverrideTurnContext { .. } => "override_turn_context", From e940365cc802823a41e1a95714ad9053ede97a5d Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 18 May 2026 19:43:44 -0700 Subject: [PATCH 2/2] Remove UserTurn op --- codex-rs/core/src/guardian/review_session.rs | 35 +-- codex-rs/core/src/session/handlers.rs | 55 +---- codex-rs/core/src/session/tests.rs | 35 +-- codex-rs/core/tests/common/test_codex.rs | 42 ++-- codex-rs/core/tests/suite/apply_patch_cli.rs | 31 +-- codex-rs/core/tests/suite/approvals.rs | 63 ++--- codex-rs/core/tests/suite/client.rs | 70 +++--- codex-rs/core/tests/suite/code_mode.rs | 31 +-- .../tests/suite/collaboration_instructions.rs | 96 ++++---- codex-rs/core/tests/suite/compact.rs | 31 +-- codex-rs/core/tests/suite/exec_policy.rs | 64 ++--- codex-rs/core/tests/suite/image_rollout.rs | 62 ++--- codex-rs/core/tests/suite/items.rs | 26 +-- codex-rs/core/tests/suite/json_result.rs | 31 +-- .../core/tests/suite/mcp_turn_metadata.rs | 34 +-- codex-rs/core/tests/suite/model_switching.rs | 31 +-- .../core/tests/suite/model_visible_layout.rs | 157 +++++++------ codex-rs/core/tests/suite/models_cache_ttl.rs | 31 +-- .../core/tests/suite/models_etag_responses.rs | 31 +-- codex-rs/core/tests/suite/pending_input.rs | 31 +-- codex-rs/core/tests/suite/personality.rs | 32 +-- codex-rs/core/tests/suite/prompt_caching.rs | 153 ++++++------ codex-rs/core/tests/suite/remote_env.rs | 31 +-- codex-rs/core/tests/suite/remote_models.rs | 157 ++++--------- .../core/tests/suite/request_permissions.rs | 32 +-- .../tests/suite/request_permissions_tool.rs | 32 +-- .../core/tests/suite/request_user_input.rs | 101 ++++---- .../suite/responses_api_proxy_headers.rs | 31 +-- codex-rs/core/tests/suite/rmcp_client.rs | 31 +-- .../tests/suite/safety_check_downgrade.rs | 31 +-- codex-rs/core/tests/suite/shell_snapshot.rs | 124 +++++----- codex-rs/core/tests/suite/skill_approval.rs | 31 +-- codex-rs/core/tests/suite/skills.rs | 31 +-- codex-rs/core/tests/suite/sqlite_state.rs | 31 +-- codex-rs/core/tests/suite/tool_harness.rs | 155 +++++++------ codex-rs/core/tests/suite/tool_parallelism.rs | 62 ++--- codex-rs/core/tests/suite/truncation.rs | 31 +-- codex-rs/core/tests/suite/unified_exec.rs | 218 ++++++++++-------- codex-rs/core/tests/suite/user_shell_cmd.rs | 31 +-- codex-rs/core/tests/suite/view_image.rs | 31 +-- .../core/tests/suite/websocket_fallback.rs | 31 +-- codex-rs/protocol/src/protocol.rs | 69 ------ 42 files changed, 1289 insertions(+), 1174 deletions(-) diff --git a/codex-rs/core/src/guardian/review_session.rs b/codex-rs/core/src/guardian/review_session.rs index afb5882a69..389373c8de 100644 --- a/codex-rs/core/src/guardian/review_session.rs +++ b/codex-rs/core/src/guardian/review_session.rs @@ -706,22 +706,29 @@ async fn run_review_on_session( let submit_result = run_before_review_deadline( deadline, params.external_cancel.as_ref(), - Box::pin(review_session.codex.submit(Op::UserTurn { - environments: None, + Box::pin(review_session.codex.submit(Op::UserInput { items: prompt_items.items, - #[allow(deprecated)] - cwd: params.parent_turn.cwd.to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy: legacy_sandbox_policy, - permission_profile: Some(guardian_permission_profile), - model: params.model.clone(), - effort: params.reasoning_effort, - summary: Some(params.reasoning_summary), - service_tier: None, + environments: None, final_output_json_schema: Some(params.schema.clone()), - collaboration_mode: None, - personality: params.personality, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + #[allow(deprecated)] + cwd: Some(params.parent_turn.cwd.to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(legacy_sandbox_policy), + permission_profile: Some(guardian_permission_profile), + summary: Some(params.reasoning_summary), + personality: params.personality, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: params.model.clone(), + reasoning_effort: params.reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, })), ) .await; diff --git a/codex-rs/core/src/session/handlers.rs b/codex-rs/core/src/session/handlers.rs index f8a4fa2920..e01ee28f99 100644 --- a/codex-rs/core/src/session/handlers.rs +++ b/codex-rs/core/src/session/handlers.rs @@ -49,9 +49,6 @@ use codex_protocol::request_permissions::RequestPermissionsResponse; use codex_protocol::request_user_input::RequestUserInputResponse; use crate::context_manager::is_user_turn_boundary; -use codex_protocol::config_types::CollaborationMode; -use codex_protocol::config_types::ModeKind; -use codex_protocol::config_types::Settings; use codex_protocol::dynamic_tools::DynamicToolResponse; use codex_protocol::items::UserMessageItem; use codex_protocol::mcp::RequestId as ProtocolRequestId; @@ -114,56 +111,6 @@ pub(super) async fn user_input_or_turn_inner( mirror_user_text_to_realtime: Option<()>, ) { let (items, updates, responsesapi_client_metadata) = match op { - Op::UserTurn { - cwd, - approval_policy, - approvals_reviewer, - sandbox_policy, - permission_profile, - model, - effort, - summary, - service_tier, - final_output_json_schema, - items, - collaboration_mode, - personality, - environments, - } => { - let collaboration_mode = collaboration_mode.or_else(|| { - Some(CollaborationMode { - mode: ModeKind::Default, - settings: Settings { - model: model.clone(), - reasoning_effort: effort, - developer_instructions: None, - }, - }) - }); - ( - items, - SessionSettingsUpdate { - cwd: Some(cwd), - approval_policy: Some(approval_policy), - approvals_reviewer, - sandbox_policy: Some(sandbox_policy), - workspace_roots: None, - profile_workspace_roots: None, - permission_profile, - active_permission_profile: None, - windows_sandbox_level: None, - collaboration_mode, - reasoning_summary: summary, - service_tier, - final_output_json_schema: Some(final_output_json_schema), - environments, - personality, - app_server_client_name: None, - app_server_client_version: None, - }, - None, - ) - } Op::UserInput { items, environments, @@ -826,7 +773,7 @@ pub(super) async fn submission_loop( .await; false } - Op::UserInput { .. } | Op::UserTurn { .. } => { + Op::UserInput { .. } => { user_input_or_turn(&sess, sub.id.clone(), sub.op).await; false } diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index a6d82e211d..4f090a8a3a 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -5197,7 +5197,7 @@ fn submission_dispatch_span_uses_debug_for_realtime_audio() { } #[test] -fn op_kind_distinguishes_turn_ops() { +fn op_kind_for_input_and_context_ops() { assert_eq!( Op::OverrideTurnContext { cwd: None, @@ -5237,24 +5237,31 @@ async fn user_turn_updates_approvals_reviewer() { handlers::user_input_or_turn( &session, "sub-1".to_string(), - Op::UserTurn { - environments: None, + Op::UserInput { items: vec![UserInput::Text { text: "hello".to_string(), text_elements: Vec::new(), }], - cwd: config.cwd.to_path_buf(), - approval_policy: config.permissions.approval_policy.value(), - approvals_reviewer: Some(codex_config::types::ApprovalsReviewer::AutoReview), - sandbox_policy: config.legacy_sandbox_policy(), - permission_profile: None, - model: turn_context.model_info.slug.clone(), - effort: config.model_reasoning_effort, - summary: config.model_reasoning_summary, - service_tier: None, + environments: None, final_output_json_schema: None, - collaboration_mode: None, - personality: config.personality, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(config.cwd.to_path_buf()), + approval_policy: Some(config.permissions.approval_policy.value()), + approvals_reviewer: Some(codex_config::types::ApprovalsReviewer::AutoReview), + sandbox_policy: Some(config.legacy_sandbox_policy()), + summary: config.model_reasoning_summary, + personality: config.personality, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: turn_context.model_info.slug.clone(), + reasoning_effort: config.model_reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, }, ) .await; diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index 2007104868..a1ba7b8fb2 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -190,8 +190,14 @@ pub enum ApplyPatchModelOutput { ShellCommandViaHeredoc, } -/// Returns the permission fields required by `Op::UserTurn` for tests that -/// construct the op directly. +/// A collection of different ways the model can output an apply_patch call +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum ShellModelOutput { + ShellCommand, + // UnifiedExec has its own set of tests +} + +/// Returns the permission fields required by test thread-settings overrides. pub fn turn_permission_fields( permission_profile: PermissionProfile, cwd: &Path, @@ -754,24 +760,30 @@ impl TestCodex { turn_permission_fields(permission_profile, self.config.cwd.as_path()); let session_model = self.session_configured.model.clone(); self.codex - .submit(Op::UserTurn { - environments, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments, final_output_json_schema: None, - cwd: self.config.cwd.to_path_buf(), - approval_policy, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(self.config.cwd.to_path_buf()), + approval_policy: Some(approval_policy), + sandbox_policy: Some(sandbox_policy), + permission_profile, + service_tier, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/apply_patch_cli.rs b/codex-rs/core/tests/suite/apply_patch_cli.rs index 05379517e5..1e325e1bb5 100644 --- a/codex-rs/core/tests/suite/apply_patch_cli.rs +++ b/codex-rs/core/tests/suite/apply_patch_cli.rs @@ -83,24 +83,29 @@ async fn submit_without_wait_with_turn_permissions( let test = harness.test(); let session_model = test.session_configured.model.clone(); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: harness.cwd().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(harness.cwd().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; Ok(()) diff --git a/codex-rs/core/tests/suite/approvals.rs b/codex-rs/core/tests/suite/approvals.rs index 5045755e32..f08262eb6f 100644 --- a/codex-rs/core/tests/suite/approvals.rs +++ b/codex-rs/core/tests/suite/approvals.rs @@ -644,24 +644,29 @@ async fn submit_turn( let session_model = test.session_configured.model.clone(); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd.path().to_path_buf(), - approval_policy, - approvals_reviewer: Some(ApprovalsReviewer::User), - sandbox_policy, - permission_profile: None, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd.path().to_path_buf()), + approval_policy: Some(approval_policy), + approvals_reviewer: Some(ApprovalsReviewer::User), + sandbox_policy: Some(sandbox_policy), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -2578,24 +2583,30 @@ async fn matched_prefix_rule_runs_unsandboxed_under_zsh_fork() -> Result<()> { let (sandbox_policy, permission_profile) = turn_permission_fields(permission_profile, test.cwd.path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "run allowed touch under zsh fork".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd.path().to_path_buf(), - approval_policy, - approvals_reviewer: Some(ApprovalsReviewer::User), - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd.path().to_path_buf()), + approval_policy: Some(approval_policy), + approvals_reviewer: Some(ApprovalsReviewer::User), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index 818e0eba7b..f6731a0ea4 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -1758,12 +1758,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re sse(vec![ev_response_created("resp1"), ev_completed("resp1")]), ) .await; - let TestCodex { - codex, - config, - session_configured, - .. - } = test_codex().with_model("gpt-5.4").build(&server).await?; + let TestCodex { codex, config, .. } = test_codex().with_model("gpt-5.4").build(&server).await?; let collaboration_mode = CollaborationMode { mode: ModeKind::Default, @@ -1775,28 +1770,26 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re }; codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello".into(), text_elements: Vec::new(), }], - cwd: config.cwd.to_path_buf(), - approval_policy: config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: config.legacy_sandbox_policy(), - permission_profile: None, - model: session_configured.model.clone(), - effort: Some(ReasoningEffort::Low), - summary: Some( - config - .model_reasoning_summary - .unwrap_or(ReasoningSummary::Auto), - ), - service_tier: None, - collaboration_mode: Some(collaboration_mode), + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(config.cwd.to_path_buf()), + approval_policy: Some(config.permissions.approval_policy.value()), + sandbox_policy: Some(config.legacy_sandbox_policy()), + summary: Some( + config + .model_reasoning_summary + .unwrap_or(ReasoningSummary::Auto), + ), + collaboration_mode: Some(collaboration_mode), + ..Default::default() + }, }) .await?; @@ -1898,24 +1891,29 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default() .await?; codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello".into(), text_elements: Vec::new(), }], - cwd: config.cwd.to_path_buf(), - approval_policy: config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: config.legacy_sandbox_policy(), - permission_profile: None, - model: session_configured.model, - effort: None, - summary: Some(ReasoningSummary::Concise), - service_tier: None, - collaboration_mode: None, + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(config.cwd.to_path_buf()), + approval_policy: Some(config.permissions.approval_policy.value()), + sandbox_policy: Some(config.legacy_sandbox_policy()), + summary: Some(ReasoningSummary::Concise), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_configured.model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await .unwrap(); diff --git a/codex-rs/core/tests/suite/code_mode.rs b/codex-rs/core/tests/suite/code_mode.rs index beae9e4afb..19373b52e4 100644 --- a/codex-rs/core/tests/suite/code_mode.rs +++ b/codex-rs/core/tests/suite/code_mode.rs @@ -2584,24 +2584,29 @@ text( turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "use exec to inspect and call hidden tools".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: test.session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/collaboration_instructions.rs b/codex-rs/core/tests/suite/collaboration_instructions.rs index 2b0c20ab26..bd01dc4e7d 100644 --- a/codex-rs/core/tests/suite/collaboration_instructions.rs +++ b/codex-rs/core/tests/suite/collaboration_instructions.rs @@ -178,28 +178,26 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> { let collaboration_mode = collab_mode_with_instructions(Some(collab_text)); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello".into(), text_elements: Vec::new(), }], - cwd: test.config.cwd.to_path_buf(), - approval_policy: test.config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: test.config.legacy_sandbox_policy(), - permission_profile: None, - model: test.session_configured.model.clone(), - effort: None, - summary: Some( - test.config - .model_reasoning_summary - .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), - ), - service_tier: None, - collaboration_mode: Some(collaboration_mode), + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.config.cwd.to_path_buf()), + approval_policy: Some(test.config.permissions.approval_policy.value()), + sandbox_policy: Some(test.config.legacy_sandbox_policy()), + summary: Some( + test.config + .model_reasoning_summary + .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), + ), + collaboration_mode: Some(collaboration_mode), + ..Default::default() + }, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -230,28 +228,26 @@ async fn collaboration_instructions_omitted_when_disabled() -> Result<()> { let collaboration_mode = collab_mode_with_instructions(Some("turn instructions")); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello".into(), text_elements: Vec::new(), }], - cwd: test.config.cwd.to_path_buf(), - approval_policy: test.config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: test.config.legacy_sandbox_policy(), - permission_profile: None, - model: test.session_configured.model.clone(), - effort: None, - summary: Some( - test.config - .model_reasoning_summary - .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), - ), - service_tier: None, - collaboration_mode: Some(collaboration_mode), + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.config.cwd.to_path_buf()), + approval_policy: Some(test.config.permissions.approval_policy.value()), + sandbox_policy: Some(test.config.legacy_sandbox_policy()), + summary: Some( + test.config + .model_reasoning_summary + .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), + ), + collaboration_mode: Some(collaboration_mode), + ..Default::default() + }, }) .await?; wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -355,28 +351,26 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu .await?; test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello".into(), text_elements: Vec::new(), }], - cwd: test.config.cwd.to_path_buf(), - approval_policy: test.config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: test.config.legacy_sandbox_policy(), - permission_profile: None, - model: test.session_configured.model.clone(), - effort: None, - summary: Some( - test.config - .model_reasoning_summary - .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), - ), - service_tier: None, - collaboration_mode: Some(turn_mode), + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.config.cwd.to_path_buf()), + approval_policy: Some(test.config.permissions.approval_policy.value()), + sandbox_policy: Some(test.config.legacy_sandbox_policy()), + summary: Some( + test.config + .model_reasoning_summary + .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), + ), + collaboration_mode: Some(turn_mode), + ..Default::default() + }, }) .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 d1384ff800..2c789a271d 100644 --- a/codex-rs/core/tests/suite/compact.rs +++ b/codex-rs/core/tests/suite/compact.rs @@ -88,24 +88,29 @@ fn ev_shell_command_call(call_id: &str, command: &str) -> serde_json::Value { fn disabled_permission_user_turn(text: impl Into, cwd: PathBuf, model: String) -> Op { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); - Op::UserTurn { - environments: None, + Op::UserInput { items: vec![UserInput::Text { text: text.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, } } diff --git a/codex-rs/core/tests/suite/exec_policy.rs b/codex-rs/core/tests/suite/exec_policy.rs index 3f6c9cfdc0..f1e01c22ce 100644 --- a/codex-rs/core/tests/suite/exec_policy.rs +++ b/codex-rs/core/tests/suite/exec_policy.rs @@ -46,24 +46,31 @@ async fn submit_user_turn( let (sandbox_policy, permission_profile) = turn_permission_fields(permission_profile, test.config.cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd_path().to_path_buf(), - approval_policy, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd_path().to_path_buf()), + approval_policy: Some(approval_policy), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: collaboration_mode.or({ + Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }) + }), + ..Default::default() + }, }) .await?; Ok(()) @@ -126,24 +133,29 @@ async fn execpolicy_blocks_shell_invocation() -> Result<()> { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "run shell command".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd_path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd_path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/image_rollout.rs b/codex-rs/core/tests/suite/image_rollout.rs index 3404edbb1e..085ca96f37 100644 --- a/codex-rs/core/tests/suite/image_rollout.rs +++ b/codex-rs/core/tests/suite/image_rollout.rs @@ -113,8 +113,7 @@ async fn copy_paste_local_image_persists_rollout_request_shape() -> anyhow::Resu turn_permission_fields(PermissionProfile::Disabled, cwd.path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![ UserInput::LocalImage { path: abs_path.clone(), @@ -125,18 +124,24 @@ async fn copy_paste_local_image_persists_rollout_request_shape() -> anyhow::Resu text_elements: Vec::new(), }, ], + environments: None, final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -204,8 +209,7 @@ async fn drag_drop_image_persists_rollout_request_shape() -> anyhow::Result<()> turn_permission_fields(PermissionProfile::Disabled, cwd.path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![ UserInput::Image { image_url: image_url.clone(), @@ -216,18 +220,24 @@ async fn drag_drop_image_persists_rollout_request_shape() -> anyhow::Result<()> text_elements: Vec::new(), }, ], + environments: None, final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/items.rs b/codex-rs/core/tests/suite/items.rs index 0015a418ca..82e01e2451 100644 --- a/codex-rs/core/tests/suite/items.rs +++ b/codex-rs/core/tests/suite/items.rs @@ -44,30 +44,28 @@ use std::path::PathBuf; fn disabled_plan_turn( text: &str, - model: String, + _model: String, collaboration_mode: CollaborationMode, ) -> anyhow::Result { let cwd = std::env::current_dir()?; let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); - Ok(Op::UserTurn { - environments: None, + Ok(Op::UserInput { items: vec![UserInput::Text { text: text.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: Some(collaboration_mode), - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(collaboration_mode), + ..Default::default() + }, }) } diff --git a/codex-rs/core/tests/suite/json_result.rs b/codex-rs/core/tests/suite/json_result.rs index c4ce8ac908..e81d7aa82a 100644 --- a/codex-rs/core/tests/suite/json_result.rs +++ b/codex-rs/core/tests/suite/json_result.rs @@ -75,24 +75,29 @@ async fn codex_returns_json_result(model: String) -> anyhow::Result<()> { // 1) Normal user input – should hit server once. codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello world".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: Some(serde_json::from_str(SCHEMA)?), - cwd: cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/mcp_turn_metadata.rs b/codex-rs/core/tests/suite/mcp_turn_metadata.rs index 17fe33dc8b..16e6cbe37d 100644 --- a/codex-rs/core/tests/suite/mcp_turn_metadata.rs +++ b/codex-rs/core/tests/suite/mcp_turn_metadata.rs @@ -64,27 +64,35 @@ async fn submit_user_turn( approval_policy: AskForApproval, collaboration_mode: Option, ) -> Result<()> { + let session_model = test.session_configured.model.clone(); let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, test.cwd.path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: text.to_string(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd.path().to_path_buf(), - approval_policy, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: test.session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd.path().to_path_buf()), + approval_policy: Some(approval_policy), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: collaboration_mode.or({ + Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }) + }), + ..Default::default() + }, }) .await?; Ok(()) diff --git a/codex-rs/core/tests/suite/model_switching.rs b/codex-rs/core/tests/suite/model_switching.rs index adce6e36eb..1c9358a8a3 100644 --- a/codex-rs/core/tests/suite/model_switching.rs +++ b/codex-rs/core/tests/suite/model_switching.rs @@ -42,21 +42,26 @@ use wiremock::MockServer; fn read_only_user_turn(test: &TestCodex, items: Vec, model: String) -> Op { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::read_only(), test.cwd_path()); - Op::UserTurn { - environments: None, + Op::UserInput { items, + environments: None, final_output_json_schema: None, - cwd: test.cwd_path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model, - effort: test.config.model_reasoning_effort, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd_path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model, + reasoning_effort: test.config.model_reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, } } diff --git a/codex-rs/core/tests/suite/model_visible_layout.rs b/codex-rs/core/tests/suite/model_visible_layout.rs index d9c636b35f..9cf83424c9 100644 --- a/codex-rs/core/tests/suite/model_visible_layout.rs +++ b/codex-rs/core/tests/suite/model_visible_layout.rs @@ -117,24 +117,29 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> { turn_permission_fields(PermissionProfile::read_only(), first_turn_cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "first turn".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: first_turn_cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy: first_sandbox_policy, - permission_profile: first_permission_profile, - model: test.session_configured.model.clone(), - effort: test.config.model_reasoning_effort, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(first_turn_cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(first_sandbox_policy), + permission_profile: first_permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: test.config.model_reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; wait_for_event(&test.codex, |event| { @@ -147,24 +152,30 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> { preturn_context_diff_cwd.as_path(), ); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "second turn with context updates".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: preturn_context_diff_cwd, - approval_policy: AskForApproval::OnRequest, - approvals_reviewer: None, - sandbox_policy: second_sandbox_policy, - permission_profile: second_permission_profile, - model: test.session_configured.model.clone(), - effort: test.config.model_reasoning_effort, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: Some(Personality::Friendly), + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(preturn_context_diff_cwd), + approval_policy: Some(AskForApproval::OnRequest), + sandbox_policy: Some(second_sandbox_policy), + permission_profile: second_permission_profile, + personality: Some(Personality::Friendly), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: test.config.model_reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; wait_for_event(&test.codex, |event| { @@ -230,24 +241,29 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R turn_permission_fields(PermissionProfile::read_only(), cwd_one.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "first turn in agents_one".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd_one.clone(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy: first_sandbox_policy, - permission_profile: first_permission_profile, - model: test.session_configured.model.clone(), - effort: test.config.model_reasoning_effort, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_one.clone()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(first_sandbox_policy), + permission_profile: first_permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: test.config.model_reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; wait_for_event(&test.codex, |event| { @@ -258,24 +274,29 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R let (second_sandbox_policy, second_permission_profile) = turn_permission_fields(PermissionProfile::read_only(), cwd_two.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "second turn in agents_two".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd_two, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy: second_sandbox_policy, - permission_profile: second_permission_profile, - model: test.session_configured.model.clone(), - effort: test.config.model_reasoning_effort, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_two), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(second_sandbox_policy), + permission_profile: second_permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: test.config.model_reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; wait_for_event(&test.codex, |event| { @@ -377,24 +398,30 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul ); resumed .codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "resume and change personality".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: resume_override_cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: resumed.session_configured.model.clone(), - effort: resumed.config.model_reasoning_effort, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: Some(Personality::Friendly), + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(resume_override_cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + personality: Some(Personality::Friendly), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: resumed.session_configured.model.clone(), + reasoning_effort: resumed.config.model_reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .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 8463ee1cf1..3b729738df 100644 --- a/codex-rs/core/tests/suite/models_cache_ttl.rs +++ b/codex-rs/core/tests/suite/models_cache_ttl.rs @@ -92,24 +92,29 @@ async fn renews_cache_ttl_on_matching_models_etag() -> Result<()> { turn_permission_fields(PermissionProfile::Disabled, test.cwd_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hi".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd_path().to_path_buf(), - approval_policy: codex_protocol::protocol::AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: test.session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd_path().to_path_buf()), + approval_policy: Some(codex_protocol::protocol::AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/models_etag_responses.rs b/codex-rs/core/tests/suite/models_etag_responses.rs index 346c503c25..49f34d8644 100644 --- a/codex-rs/core/tests/suite/models_etag_responses.rs +++ b/codex-rs/core/tests/suite/models_etag_responses.rs @@ -104,24 +104,29 @@ async fn refresh_models_on_models_etag_mismatch_and_avoid_duplicate_models_fetch .await; codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "please run a tool".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd_path, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_path), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/pending_input.rs b/codex-rs/core/tests/suite/pending_input.rs index d511c8f0b6..b057b86171 100644 --- a/codex-rs/core/tests/suite/pending_input.rs +++ b/codex-rs/core/tests/suite/pending_input.rs @@ -113,24 +113,29 @@ async fn submit_danger_full_access_user_turn(test: &TestCodex, text: &str) { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: text.to_string(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.config.cwd.to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: test.session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.config.cwd.to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await .unwrap_or_else(|err| panic!("submit user turn: {err}")); diff --git a/codex-rs/core/tests/suite/personality.rs b/codex-rs/core/tests/suite/personality.rs index 09eb61fa69..8924ca2a25 100644 --- a/codex-rs/core/tests/suite/personality.rs +++ b/codex-rs/core/tests/suite/personality.rs @@ -60,24 +60,30 @@ fn read_only_text_turn_with_personality( ) -> Op { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::read_only(), test.cwd_path()); - Op::UserTurn { - environments: None, + Op::UserInput { items: vec![UserInput::Text { text: text.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd_path().to_path_buf(), - approval_policy, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model, - effort: test.config.model_reasoning_effort, - summary: None, - service_tier: None, - collaboration_mode: None, - personality, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd_path().to_path_buf()), + approval_policy: Some(approval_policy), + sandbox_policy: Some(sandbox_policy), + permission_profile, + personality, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model, + reasoning_effort: test.config.model_reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, } } diff --git a/codex-rs/core/tests/suite/prompt_caching.rs b/codex-rs/core/tests/suite/prompt_caching.rs index 2023778a11..accf3fb789 100644 --- a/codex-rs/core/tests/suite/prompt_caching.rs +++ b/codex-rs/core/tests/suite/prompt_caching.rs @@ -714,7 +714,7 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; - // Second turn using per-turn overrides via UserTurn + // Second turn using per-turn thread-settings overrides. let new_cwd = TempDir::new().unwrap(); let writable = TempDir::new().unwrap(); let permission_profile = PermissionProfile::workspace_write_with( @@ -726,24 +726,24 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res let (sandbox_policy, permission_profile) = turn_permission_fields(permission_profile, new_cwd.path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello 2".into(), text_elements: Vec::new(), }], - cwd: new_cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: "o3".to_string(), - effort: Some(ReasoningEffort::High), - summary: Some(ReasoningSummary::Detailed), - service_tier: None, - collaboration_mode: None, + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(new_cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + model: Some("o3".to_string()), + effort: Some(Some(ReasoningEffort::High)), + summary: Some(ReasoningSummary::Detailed), + ..Default::default() + }, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -840,47 +840,57 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a let default_summary = config.model_reasoning_summary; codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello 1".into(), text_elements: Vec::new(), }], - cwd: default_cwd.to_path_buf(), - approval_policy: default_approval_policy, - approvals_reviewer: None, - sandbox_policy: default_sandbox_policy.clone(), - permission_profile: None, - model: default_model.clone(), - effort: default_effort, - summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)), - service_tier: None, - collaboration_mode: None, + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(default_cwd.to_path_buf()), + approval_policy: Some(default_approval_policy), + sandbox_policy: Some(default_sandbox_policy.clone()), + summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: default_model.clone(), + reasoning_effort: default_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello 2".into(), text_elements: Vec::new(), }], - cwd: default_cwd.to_path_buf(), - approval_policy: default_approval_policy, - approvals_reviewer: None, - sandbox_policy: default_sandbox_policy.clone(), - permission_profile: None, - model: default_model.clone(), - effort: default_effort, - summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)), - service_tier: None, - collaboration_mode: None, + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(default_cwd.to_path_buf()), + approval_policy: Some(default_approval_policy), + sandbox_policy: Some(default_sandbox_policy.clone()), + summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: default_model.clone(), + reasoning_effort: default_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -969,24 +979,29 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu let default_summary = config.model_reasoning_summary; codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello 1".into(), text_elements: Vec::new(), }], - cwd: default_cwd.to_path_buf(), - approval_policy: default_approval_policy, - approvals_reviewer: None, - sandbox_policy: default_sandbox_policy.clone(), - permission_profile: None, - model: default_model, - effort: default_effort, - summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)), - service_tier: None, - collaboration_mode: None, + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(default_cwd.to_path_buf()), + approval_policy: Some(default_approval_policy), + sandbox_policy: Some(default_sandbox_policy.clone()), + summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: default_model, + reasoning_effort: default_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; @@ -994,24 +1009,30 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, default_cwd.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello 2".into(), text_elements: Vec::new(), }], - cwd: default_cwd.to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: "o3".to_string(), - effort: Some(ReasoningEffort::High), - summary: Some(ReasoningSummary::Detailed), - service_tier: None, - collaboration_mode: None, + environments: None, final_output_json_schema: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(default_cwd.to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + summary: Some(ReasoningSummary::Detailed), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: "o3".to_string(), + reasoning_effort: Some(ReasoningEffort::High), + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; diff --git a/codex-rs/core/tests/suite/remote_env.rs b/codex-rs/core/tests/suite/remote_env.rs index e19379ffc8..873796ff6c 100644 --- a/codex-rs/core/tests/suite/remote_env.rs +++ b/codex-rs/core/tests/suite/remote_env.rs @@ -67,24 +67,29 @@ async fn submit_turn_with_approval_and_environments( environments: Vec, ) -> Result<()> { test.codex - .submit(Op::UserTurn { - environments: Some(environments), + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: Some(environments), final_output_json_schema: None, - cwd: test.cwd.path().to_path_buf(), - approval_policy: AskForApproval::OnRequest, - approvals_reviewer: Some(ApprovalsReviewer::User), - sandbox_policy: SandboxPolicy::new_read_only_policy(), - permission_profile: None, - model: test.session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::OnRequest), + approvals_reviewer: Some(ApprovalsReviewer::User), + sandbox_policy: Some(SandboxPolicy::new_read_only_policy()), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/remote_models.rs b/codex-rs/core/tests/suite/remote_models.rs index d1caf24836..adc73d8a79 100644 --- a/codex-rs/core/tests/suite/remote_models.rs +++ b/codex-rs/core/tests/suite/remote_models.rs @@ -142,9 +142,7 @@ async fn remote_models_config_context_window_override_clamps_to_max_context_wind ) .await; - let TestCodex { - codex, cwd, config, .. - } = test_codex() + let TestCodex { codex, .. } = test_codex() .with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing()) .with_config(|config| { config.model = Some(requested_model.to_string()); @@ -154,24 +152,15 @@ async fn remote_models_config_context_window_override_clamps_to_max_context_wind .await?; codex - .submit(Op::UserTurn { + .submit(Op::UserInput { items: vec![UserInput::Text { text: "check context window".into(), text_elements: Vec::new(), }], - final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: config.legacy_sandbox_policy(), - model: requested_model.to_string(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - permission_profile: None, - personality: None, environments: None, + final_output_json_schema: None, + responsesapi_client_metadata: None, + thread_settings: Default::default(), }) .await?; @@ -220,9 +209,7 @@ async fn remote_models_config_override_above_max_uses_max_context_window() -> Re ) .await; - let TestCodex { - codex, cwd, config, .. - } = test_codex() + let TestCodex { codex, .. } = test_codex() .with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing()) .with_config(|config| { config.model = Some(requested_model.to_string()); @@ -232,24 +219,15 @@ async fn remote_models_config_override_above_max_uses_max_context_window() -> Re .await?; codex - .submit(Op::UserTurn { + .submit(Op::UserInput { items: vec![UserInput::Text { text: "check context window".into(), text_elements: Vec::new(), }], - final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: config.legacy_sandbox_policy(), - model: requested_model.to_string(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - permission_profile: None, - personality: None, environments: None, + final_output_json_schema: None, + responsesapi_client_metadata: None, + thread_settings: Default::default(), }) .await?; @@ -298,9 +276,7 @@ async fn remote_models_use_context_window_when_config_override_is_absent() -> Re ) .await; - let TestCodex { - codex, cwd, config, .. - } = test_codex() + let TestCodex { codex, .. } = test_codex() .with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing()) .with_config(|config| { config.model = Some(requested_model.to_string()); @@ -309,24 +285,15 @@ async fn remote_models_use_context_window_when_config_override_is_absent() -> Re .await?; codex - .submit(Op::UserTurn { + .submit(Op::UserInput { items: vec![UserInput::Text { text: "check context window".into(), text_elements: Vec::new(), }], - final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: config.legacy_sandbox_policy(), - model: requested_model.to_string(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - permission_profile: None, - personality: None, environments: None, + final_output_json_schema: None, + responsesapi_client_metadata: None, + thread_settings: Default::default(), }) .await?; @@ -388,9 +355,7 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<( ) .await; - let TestCodex { - codex, cwd, config, .. - } = test_codex() + let TestCodex { codex, .. } = test_codex() .with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing()) .with_config(|config| { config.model = Some(requested_model.to_string()); @@ -399,24 +364,15 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<( .await?; codex - .submit(Op::UserTurn { + .submit(Op::UserInput { items: vec![UserInput::Text { text: "check model slug".into(), text_elements: Vec::new(), }], - final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: config.legacy_sandbox_policy(), - permission_profile: None, - model: requested_model.to_string(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, environments: None, + final_output_json_schema: None, + responsesapi_client_metadata: None, + thread_settings: Default::default(), }) .await?; @@ -452,36 +408,21 @@ async fn namespaced_model_slug_uses_catalog_metadata_without_fallback_warning() ) .await; - let TestCodex { - codex, cwd, config, .. - } = test_codex() + let TestCodex { codex, .. } = test_codex() .with_model(requested_model) .build(&server) .await?; codex - .submit(Op::UserTurn { + .submit(Op::UserInput { items: vec![UserInput::Text { text: "check namespaced model metadata".into(), text_elements: Vec::new(), }], - final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: config.permissions.approval_policy.value(), - approvals_reviewer: None, - sandbox_policy: config.legacy_sandbox_policy(), - permission_profile: None, - model: requested_model.to_string(), - effort: None, - summary: Some( - config - .model_reasoning_summary - .unwrap_or(ReasoningSummary::Auto), - ), - service_tier: None, - collaboration_mode: None, - personality: None, environments: None, + final_output_json_schema: None, + responsesapi_client_metadata: None, + thread_settings: Default::default(), }) .await?; @@ -633,24 +574,22 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path()); codex - .submit(Op::UserTurn { + .submit(Op::UserInput { items: vec![UserInput::Text { text: "run call".into(), text_elements: Vec::new(), }], - final_output_json_schema: None, - cwd: cwd_path, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: REMOTE_MODEL_SLUG.to_string(), - effort: None, - summary: Some(ReasoningSummary::Auto), - service_tier: None, - collaboration_mode: None, - personality: None, environments: None, + final_output_json_schema: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_path), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + summary: Some(ReasoningSummary::Auto), + ..Default::default() + }, }) .await?; @@ -865,24 +804,22 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path()); codex - .submit(Op::UserTurn { + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello remote".into(), text_elements: Vec::new(), }], - final_output_json_schema: None, - cwd: cwd_path, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: model.to_string(), - effort: None, - summary: Some(ReasoningSummary::Auto), - service_tier: None, - collaboration_mode: None, - personality: None, environments: None, + final_output_json_schema: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_path), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + summary: Some(ReasoningSummary::Auto), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/request_permissions.rs b/codex-rs/core/tests/suite/request_permissions.rs index cf021f29e4..9800104685 100644 --- a/codex-rs/core/tests/suite/request_permissions.rs +++ b/codex-rs/core/tests/suite/request_permissions.rs @@ -190,24 +190,30 @@ async fn submit_turn( let (sandbox_policy, permission_profile) = turn_permission_fields(permission_profile, test.cwd.path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd.path().to_path_buf(), - approval_policy, - approvals_reviewer: Some(ApprovalsReviewer::User), - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd.path().to_path_buf()), + approval_policy: Some(approval_policy), + approvals_reviewer: Some(ApprovalsReviewer::User), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .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 cb13243966..84e101e73a 100644 --- a/codex-rs/core/tests/suite/request_permissions_tool.rs +++ b/codex-rs/core/tests/suite/request_permissions_tool.rs @@ -142,24 +142,30 @@ async fn submit_turn( let (sandbox_policy, permission_profile) = turn_permission_fields(permission_profile, test.config.cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd.path().to_path_buf(), - approval_policy, - approvals_reviewer, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd.path().to_path_buf()), + approval_policy: Some(approval_policy), + approvals_reviewer, + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .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 6ddd9d0b5e..e0ec684797 100644 --- a/codex-rs/core/tests/suite/request_user_input.rs +++ b/codex-rs/core/tests/suite/request_user_input.rs @@ -132,36 +132,33 @@ async fn request_user_input_round_trip_for_mode(mode: ModeKind) -> anyhow::Resul ]); let second_mock = responses::mount_sse_once(&server, second_response).await; - let session_model = session_configured.model.clone(); let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd.path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "please confirm".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: Some(CollaborationMode { - mode, - settings: Settings { - model: session_configured.model.clone(), - reasoning_effort: None, - developer_instructions: None, - }, - }), - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(CollaborationMode { + mode, + settings: Settings { + model: session_configured.model.clone(), + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -282,31 +279,29 @@ async fn request_user_input_interrupt_emits_deferred_token_count() -> anyhow::Re let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd.path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "please confirm".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: Some(CollaborationMode { - mode: ModeKind::Plan, - settings: Settings { - model: session_configured.model, - reasoning_effort: None, - developer_instructions: None, - }, - }), - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(CollaborationMode { + mode: ModeKind::Plan, + settings: Settings { + model: session_configured.model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -388,24 +383,22 @@ where turn_permission_fields(PermissionProfile::Disabled, cwd.path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "please confirm".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: Some(collaboration_mode), - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(collaboration_mode), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/responses_api_proxy_headers.rs b/codex-rs/core/tests/suite/responses_api_proxy_headers.rs index 09e99f78c3..f396a825a1 100644 --- a/codex-rs/core/tests/suite/responses_api_proxy_headers.rs +++ b/codex-rs/core/tests/suite/responses_api_proxy_headers.rs @@ -130,24 +130,29 @@ async fn submit_turn_with_timeout(test: &TestCodex, prompt: &str) -> Result<()> let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::workspace_write(), cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::OnRequest, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::OnRequest), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index 7ead0364dc..7c811a88e0 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -105,24 +105,29 @@ fn read_only_user_turn_with_model( let cwd = fixture.cwd.path().to_path_buf(); let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::read_only(), cwd.as_path()); - Op::UserTurn { + Op::UserInput { items: vec![UserInput::Text { text: text.into(), text_elements: Vec::new(), }], - final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, environments: None, + final_output_json_schema: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, } } diff --git a/codex-rs/core/tests/suite/safety_check_downgrade.rs b/codex-rs/core/tests/suite/safety_check_downgrade.rs index c937d49ad4..ab985ce0f7 100644 --- a/codex-rs/core/tests/suite/safety_check_downgrade.rs +++ b/codex-rs/core/tests/suite/safety_check_downgrade.rs @@ -37,24 +37,29 @@ const CYBER_POLICY_MESSAGE: &str = fn disabled_text_turn(test: &TestCodex, text: &str) -> Op { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, test.cwd_path()); - Op::UserTurn { - environments: None, + Op::UserInput { items: vec![UserInput::Text { text: text.to_string(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd_path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: REQUESTED_MODEL.to_string(), - effort: test.config.model_reasoning_effort, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd_path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: REQUESTED_MODEL.to_string(), + reasoning_effort: test.config.model_reasoning_effort, + developer_instructions: None, + }, + }), + ..Default::default() + }, } } diff --git a/codex-rs/core/tests/suite/shell_snapshot.rs b/codex-rs/core/tests/suite/shell_snapshot.rs index 49ef4956cd..14241ffafb 100644 --- a/codex-rs/core/tests/suite/shell_snapshot.rs +++ b/codex-rs/core/tests/suite/shell_snapshot.rs @@ -159,24 +159,29 @@ async fn run_snapshot_command_with_options( turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "run unified exec with shell snapshot".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -254,24 +259,29 @@ async fn run_shell_command_snapshot_with_options( turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "run shell_command with shell snapshot".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -329,24 +339,29 @@ async fn run_tool_turn_on_harness( let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -567,24 +582,29 @@ async fn shell_command_snapshot_still_intercepts_apply_patch() -> Result<()> { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "apply patch via shell_command with snapshot".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd.clone(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd.clone()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/skill_approval.rs b/codex-rs/core/tests/suite/skill_approval.rs index 72244d534e..ad8ad6a91a 100644 --- a/codex-rs/core/tests/suite/skill_approval.rs +++ b/codex-rs/core/tests/suite/skill_approval.rs @@ -46,24 +46,29 @@ async fn submit_turn_with_policies( let (sandbox_policy, permission_profile) = turn_permission_fields(permission_profile, test.cwd_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.to_string(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd_path().to_path_buf(), - approval_policy, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: test.session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd_path().to_path_buf()), + approval_policy: Some(approval_policy), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; Ok(()) diff --git a/codex-rs/core/tests/suite/skills.rs b/codex-rs/core/tests/suite/skills.rs index 6434f9c533..9173f60c4a 100644 --- a/codex-rs/core/tests/suite/skills.rs +++ b/codex-rs/core/tests/suite/skills.rs @@ -74,8 +74,7 @@ async fn user_turn_includes_skill_instructions() -> Result<()> { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![ UserInput::Text { text: "please use $demo".to_string(), @@ -86,18 +85,24 @@ async fn user_turn_includes_skill_instructions() -> Result<()> { path: skill_path.clone(), }, ], + environments: None, final_output_json_schema: None, - cwd: test.config.cwd.to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.config.cwd.to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/sqlite_state.rs b/codex-rs/core/tests/suite/sqlite_state.rs index ab0b4c27ea..f576e55a3d 100644 --- a/codex-rs/core/tests/suite/sqlite_state.rs +++ b/codex-rs/core/tests/suite/sqlite_state.rs @@ -405,24 +405,29 @@ async fn mcp_call_marks_thread_memory_mode_polluted_when_configured() -> Result< turn_permission_fields(PermissionProfile::read_only(), cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "call the rmcp echo tool".to_string(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: test.session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: test.session_configured.model.clone(), + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .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 38843f2d83..2227e5b34e 100644 --- a/codex-rs/core/tests/suite/tool_harness.rs +++ b/codex-rs/core/tests/suite/tool_harness.rs @@ -102,24 +102,29 @@ async fn shell_command_tool_executes_command_and_streams_output() -> anyhow::Res turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "please run the shell command".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd_path, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_path), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -178,24 +183,29 @@ async fn update_plan_tool_emits_plan_update_event() -> anyhow::Result<()> { turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "please update the plan".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd_path, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_path), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -264,24 +274,29 @@ async fn update_plan_tool_rejects_malformed_payload() -> anyhow::Result<()> { turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "please update the plan".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd_path, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_path), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -360,24 +375,29 @@ async fn apply_patch_tool_executes_and_emits_patch_events() -> anyhow::Result<() turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "please apply a patch".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd_path, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_path), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -493,24 +513,29 @@ async fn apply_patch_reports_parse_diagnostics() -> anyhow::Result<()> { turn_permission_fields(PermissionProfile::Disabled, cwd_path.as_path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "please apply a patch".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd_path, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd_path), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/tool_parallelism.rs b/codex-rs/core/tests/suite/tool_parallelism.rs index 47282c283d..6663991e02 100644 --- a/codex-rs/core/tests/suite/tool_parallelism.rs +++ b/codex-rs/core/tests/suite/tool_parallelism.rs @@ -37,24 +37,29 @@ async fn run_turn(test: &TestCodex, prompt: &str) -> anyhow::Result<()> { turn_permission_fields(PermissionProfile::Disabled, test.cwd.path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -358,24 +363,29 @@ async fn shell_tools_start_before_response_completed_when_stream_delayed() -> an let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, test.cwd.path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "stream delayed completion".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/truncation.rs b/codex-rs/core/tests/suite/truncation.rs index 447bca6731..be9267934d 100644 --- a/codex-rs/core/tests/suite/truncation.rs +++ b/codex-rs/core/tests/suite/truncation.rs @@ -515,24 +515,29 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> { fixture .codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "call the rmcp image tool".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: fixture.cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile: Some(permission_profile), - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(fixture.cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile: Some(permission_profile), + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/unified_exec.rs b/codex-rs/core/tests/suite/unified_exec.rs index 6b962116af..98755201c9 100644 --- a/codex-rs/core/tests/suite/unified_exec.rs +++ b/codex-rs/core/tests/suite/unified_exec.rs @@ -192,24 +192,29 @@ async fn submit_unified_exec_turn( turn_permission_fields(permission_profile, test.config.cwd.as_path()); test.codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: prompt.into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: test.config.cwd.to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.config.cwd.to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -278,24 +283,29 @@ async fn unified_exec_intercepts_apply_patch_exec_command() -> Result<()> { turn_permission_fields(PermissionProfile::Disabled, &cwd); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "apply patch via unified exec".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -2120,24 +2130,29 @@ async fn unified_exec_keeps_long_running_session_after_turn_end() -> Result<()> turn_permission_fields(PermissionProfile::Disabled, &turn_cwd); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "keep unified exec process after turn end".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: turn_cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(turn_cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -2218,24 +2233,29 @@ async fn unified_exec_interrupt_preserves_long_running_session() -> Result<()> { turn_permission_fields(PermissionProfile::Disabled, &turn_cwd); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "interrupt long-running unified exec".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: turn_cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(turn_cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -2685,25 +2705,29 @@ async fn unified_exec_runs_under_sandbox() -> Result<()> { turn_permission_fields(PermissionProfile::read_only(), &turn_cwd); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "summarize large output".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: turn_cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - // Important! - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(turn_cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -2803,24 +2827,29 @@ async fn unified_exec_enforces_glob_deny_read_policy() -> Result<()> { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::read_only(), &turn_cwd); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "read the fixture files".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: turn_cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(turn_cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; @@ -2936,24 +2965,29 @@ async fn unified_exec_python_prompt_under_seatbelt() -> Result<()> { turn_permission_fields(PermissionProfile::read_only(), &turn_cwd); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "start python under seatbelt".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: turn_cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(turn_cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/user_shell_cmd.rs b/codex-rs/core/tests/suite/user_shell_cmd.rs index 4fe3586d7f..536ee7b495 100644 --- a/codex-rs/core/tests/suite/user_shell_cmd.rs +++ b/codex-rs/core/tests/suite/user_shell_cmd.rs @@ -174,24 +174,29 @@ async fn user_shell_command_does_not_replace_active_turn() -> anyhow::Result<()> fixture .codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "run model shell command".to_string(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd, - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: fixture.session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: fixture.session_configured.model.clone(), + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/core/tests/suite/view_image.rs b/codex-rs/core/tests/suite/view_image.rs index d78e8761fd..e631e537c6 100644 --- a/codex-rs/core/tests/suite/view_image.rs +++ b/codex-rs/core/tests/suite/view_image.rs @@ -72,21 +72,26 @@ const VIEW_IMAGE_TURN_COMPLETE_TIMEOUT: Duration = Duration::from_secs(30); fn disabled_user_turn(test: &TestCodex, items: Vec, model: String) -> Op { let (sandbox_policy, permission_profile) = turn_permission_fields(PermissionProfile::Disabled, test.config.cwd.as_path()); - Op::UserTurn { - environments: None, + Op::UserInput { items, + environments: None, final_output_json_schema: None, - cwd: test.config.cwd.to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(test.config.cwd.to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model, + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, } } diff --git a/codex-rs/core/tests/suite/websocket_fallback.rs b/codex-rs/core/tests/suite/websocket_fallback.rs index f073ce7ab8..32a6e30caf 100644 --- a/codex-rs/core/tests/suite/websocket_fallback.rs +++ b/codex-rs/core/tests/suite/websocket_fallback.rs @@ -152,24 +152,29 @@ async fn websocket_fallback_hides_first_websocket_retry_stream_error() -> Result turn_permission_fields(PermissionProfile::Disabled, cwd.path()); codex - .submit(Op::UserTurn { - environments: None, + .submit(Op::UserInput { items: vec![UserInput::Text { text: "hello".into(), text_elements: Vec::new(), }], + environments: None, final_output_json_schema: None, - cwd: cwd.path().to_path_buf(), - approval_policy: AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy, - permission_profile, - model: session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, + responsesapi_client_metadata: None, + thread_settings: codex_protocol::protocol::ThreadSettingsOverrides { + cwd: Some(cwd.path().to_path_buf()), + approval_policy: Some(AskForApproval::Never), + sandbox_policy: Some(sandbox_policy), + permission_profile, + collaboration_mode: Some(codex_protocol::config_types::CollaborationMode { + mode: codex_protocol::config_types::ModeKind::Default, + settings: codex_protocol::config_types::Settings { + model: session_configured.model.clone(), + reasoning_effort: None, + developer_instructions: None, + }, + }), + ..Default::default() + }, }) .await?; diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index 77d862086c..cec929b07f 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -518,74 +518,6 @@ pub enum Op { thread_settings: ThreadSettingsOverrides, }, - /// Similar to [`Op::UserInput`], but contains additional context required - /// for a turn of a [`crate::codex_thread::CodexThread`]. - UserTurn { - /// User input items, see `InputItem` - items: Vec, - - /// `cwd` to use with the [`SandboxPolicy`] and potentially tool calls - /// such as `local_shell`. - cwd: PathBuf, - - /// Policy to use for command approval. - approval_policy: AskForApproval, - - /// Reviewer to use for approval requests raised during this turn. - /// - /// When omitted, the session keeps the current setting - approvals_reviewer: Option, - - /// Policy to use for tool calls such as `local_shell`. - sandbox_policy: SandboxPolicy, - - /// Full permissions profile to use for tool calls such as `local_shell`. - /// - /// When omitted, `sandbox_policy` is used as a legacy compatibility - /// projection. - #[serde(default, skip_serializing_if = "Option::is_none")] - permission_profile: Option, - - /// Must be a valid model slug for the configured client session - /// associated with this conversation. - model: String, - - /// Will only be honored if the model is configured to use reasoning. - #[serde(skip_serializing_if = "Option::is_none")] - effort: Option, - - /// Will only be honored if the model is configured to use reasoning. - /// - /// When omitted, the session keeps the current setting (which allows core to - /// fall back to the selected model's default on new sessions). - #[serde(default, skip_serializing_if = "Option::is_none")] - summary: Option, - - /// Optional service tier override for this turn. - /// - /// Use `Some(Some(_))` to set a specific tier for this turn, `Some(None)` to - /// explicitly clear the tier for this turn, or `None` to keep the existing - /// session preference. - #[serde(default, skip_serializing_if = "Option::is_none")] - service_tier: Option>, - - // The JSON schema to use for the final assistant message - final_output_json_schema: Option, - - /// EXPERIMENTAL - set a pre-set collaboration mode. - /// Takes precedence over model, effort, and developer instructions if set. - #[serde(skip_serializing_if = "Option::is_none")] - collaboration_mode: Option, - - /// Optional personality override for this turn. - #[serde(skip_serializing_if = "Option::is_none")] - personality: Option, - - /// Optional turn-scoped environments. - #[serde(default, skip_serializing_if = "Option::is_none")] - environments: Option>, - }, - /// Inter-agent communication that should be recorded as assistant history /// while still using the normal thread submission lifecycle. InterAgentCommunication { @@ -843,7 +775,6 @@ impl Op { Self::RealtimeConversationClose => "realtime_conversation_close", Self::RealtimeConversationListVoices => "realtime_conversation_list_voices", Self::UserInput { .. } => "user_input", - Self::UserTurn { .. } => "user_turn", Self::InterAgentCommunication { .. } => "inter_agent_communication", Self::OverrideTurnContext { .. } => "override_turn_context", Self::ExecApproval { .. } => "exec_approval",