From 7988650c0ecb1c916ce9825f30ac7dd1bb240408 Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Tue, 28 Apr 2026 23:12:17 -0700 Subject: [PATCH 1/5] Move request input mode gating into tools --- codex-rs/app-server/README.md | 2 +- .../app-server/src/codex_message_processor.rs | 23 +++--- codex-rs/app-server/src/message_processor.rs | 6 -- .../tests/suite/v2/collaboration_mode_list.rs | 3 +- .../app-server/tests/suite/v2/turn_start.rs | 10 +-- codex-rs/cli/src/main.rs | 4 +- .../templates/default.md | 4 +- codex-rs/core/src/prompt_debug.rs | 7 -- codex-rs/core/src/test_support.rs | 10 +-- codex-rs/core/src/thread_manager.rs | 16 +---- codex-rs/core/src/thread_manager_tests.rs | 7 -- .../src/tools/handlers/request_user_input.rs | 7 +- .../handlers/request_user_input_tests.rs | 2 +- codex-rs/core/src/tools/spec.rs | 2 +- codex-rs/core/tests/common/test_codex.rs | 2 - codex-rs/core/tests/suite/client.rs | 6 -- codex-rs/core/tests/suite/skills.rs | 2 - codex-rs/docs/codex_mcp_interface.md | 1 + codex-rs/mcp-server/src/message_processor.rs | 7 -- .../model-provider/src/amazon_bedrock/mod.rs | 3 - codex-rs/model-provider/src/provider.rs | 20 ++---- .../src/collaboration_mode_presets.rs | 71 ++----------------- .../src/collaboration_mode_presets_tests.rs | 44 ++++-------- codex-rs/models-manager/src/manager.rs | 16 +---- codex-rs/models-manager/src/manager_tests.rs | 14 +--- codex-rs/tools/src/lib.rs | 1 + codex-rs/tools/src/request_user_input_tool.rs | 35 +++++---- .../src/request_user_input_tool_tests.rs | 35 ++++----- codex-rs/tools/src/tool_config.rs | 8 +-- codex-rs/tools/src/tool_config_tests.rs | 7 +- codex-rs/tools/src/tool_registry_plan.rs | 2 +- .../tools/src/tool_registry_plan_tests.rs | 14 ++-- codex-rs/tui/src/app.rs | 10 +-- codex-rs/tui/src/chatwidget/tests.rs | 1 - codex-rs/tui/src/chatwidget/tests/helpers.rs | 18 +---- codex-rs/tui/src/collaboration_modes.rs | 6 +- codex-rs/tui/src/model_catalog.rs | 37 +--------- 37 files changed, 123 insertions(+), 340 deletions(-) diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md index d96b0e514a75..8794e0ff632f 100644 --- a/codex-rs/app-server/README.md +++ b/codex-rs/app-server/README.md @@ -194,7 +194,7 @@ Example with notification opt-out: - `modelProvider/capabilities/read` — read provider-level capabilities for the currently configured model provider. - `experimentalFeature/list` — list feature flags with stage metadata (`beta`, `underDevelopment`, `stable`, etc.), enabled/default-enabled state, and cursor pagination. For non-beta flags, `displayName`/`description`/`announcement` are `null`. - `experimentalFeature/enablement/set` — patch the in-memory process-wide runtime feature enablement for the currently supported feature keys (`apps`, `memories`, `plugins`, `remote_control`, `tool_search`, `tool_suggest`, `tool_call_mcp_elicitation`). For each feature, precedence is: cloud requirements > --enable > config.toml > experimentalFeature/enablement/set (new) > code default. -- `collaborationMode/list` — list available collaboration mode presets (experimental, no pagination). This response omits built-in developer instructions; clients should either pass `settings.developer_instructions: null` when setting a mode to use Codex's built-in instructions, or provide their own instructions explicitly. +- `collaborationMode/list` — list available collaboration mode presets (experimental, no pagination). Built-in presets do not select a model or reasoning effort. This response omits built-in developer instructions; clients should either pass `settings.developer_instructions: null` when setting a mode to use Codex's built-in instructions, or provide their own instructions explicitly. - `skills/list` — list skills for one or more `cwd` values (optional `forceReload`). - `marketplace/add` — add a remote plugin marketplace from an HTTP(S) Git URL, SSH Git URL, or GitHub `owner/repo` shorthand, then persist it into the user marketplace config. Returns the installed root path plus whether the marketplace was already present. - `marketplace/remove` — remove a configured marketplace by name from the user marketplace config, and delete its installed marketplace root when one exists. diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index 77fe5f9ec99e..3b227f777617 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -318,7 +318,6 @@ use codex_mcp::resolve_oauth_scopes; use codex_memories_write::clear_memory_roots_contents; use codex_model_provider::ProviderAccountError; use codex_model_provider::create_model_provider; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_models_manager::collaboration_mode_presets::builtin_collaboration_mode_presets; use codex_protocol::ThreadId; use codex_protocol::config_types::CollaborationMode; @@ -851,15 +850,13 @@ impl CodexMessageProcessor { fn normalize_turn_start_collaboration_mode( &self, mut collaboration_mode: CollaborationMode, - collaboration_modes_config: CollaborationModesConfig, ) -> CollaborationMode { if collaboration_mode.settings.developer_instructions.is_none() - && let Some(instructions) = - builtin_collaboration_mode_presets(collaboration_modes_config) - .into_iter() - .find(|preset| preset.mode == Some(collaboration_mode.mode)) - .and_then(|preset| preset.developer_instructions.flatten()) - .filter(|instructions| !instructions.is_empty()) + && let Some(instructions) = builtin_collaboration_mode_presets() + .into_iter() + .find(|preset| preset.mode == Some(collaboration_mode.mode)) + .and_then(|preset| preset.developer_instructions.flatten()) + .filter(|instructions| !instructions.is_empty()) { collaboration_mode.settings.developer_instructions = Some(instructions); } @@ -6457,13 +6454,9 @@ impl CodexMessageProcessor { self.track_error_response(&request_id, error, /*error_type*/ None); })?; - let collaboration_modes_config = CollaborationModesConfig { - default_mode_request_user_input: thread - .enabled(Feature::DefaultModeRequestUserInput), - }; - let collaboration_mode = params.collaboration_mode.map(|mode| { - self.normalize_turn_start_collaboration_mode(mode, collaboration_modes_config) - }); + let collaboration_mode = params + .collaboration_mode + .map(|mode| self.normalize_turn_start_collaboration_mode(mode)); let environments: Option> = params.environments.map(|environments| { environments diff --git a/codex-rs/app-server/src/message_processor.rs b/codex-rs/app-server/src/message_processor.rs index dbe01322479a..02c0c23f84d5 100644 --- a/codex-rs/app-server/src/message_processor.rs +++ b/codex-rs/app-server/src/message_processor.rs @@ -78,7 +78,6 @@ use codex_login::default_client::get_codex_user_agent; use codex_login::default_client::set_default_client_residency_requirement; use codex_login::default_client::set_default_originator; use codex_model_provider::create_model_provider; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_protocol::ThreadId; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::W3cTraceContext; @@ -292,11 +291,6 @@ impl MessageProcessor { config.as_ref(), auth_manager.clone(), session_source, - CollaborationModesConfig { - default_mode_request_user_input: config - .features - .enabled(Feature::DefaultModeRequestUserInput), - }, environment_manager, Some(analytics_events_client.clone()), )); diff --git a/codex-rs/app-server/tests/suite/v2/collaboration_mode_list.rs b/codex-rs/app-server/tests/suite/v2/collaboration_mode_list.rs index 3c8a3e573e2a..f5914f0449b9 100644 --- a/codex-rs/app-server/tests/suite/v2/collaboration_mode_list.rs +++ b/codex-rs/app-server/tests/suite/v2/collaboration_mode_list.rs @@ -1,8 +1,7 @@ //! Validates that the collaboration mode list endpoint returns the expected default presets. //! //! The test drives the app server through the MCP harness and asserts that the list response -//! includes the plan and default modes with their default model and reasoning effort -//! settings, which keeps the API contract visible in one place. +//! includes the plan and default modes, which keeps the API contract visible in one place. #![allow(clippy::unwrap_used)] diff --git a/codex-rs/app-server/tests/suite/v2/turn_start.rs b/codex-rs/app-server/tests/suite/v2/turn_start.rs index 3ff04d50227a..faba13f6061c 100644 --- a/codex-rs/app-server/tests/suite/v2/turn_start.rs +++ b/codex-rs/app-server/tests/suite/v2/turn_start.rs @@ -969,7 +969,7 @@ async fn turn_start_accepts_collaboration_mode_override_v2() -> Result<()> { codex_home.path(), &server.uri(), "never", - &BTreeMap::from([(Feature::DefaultModeRequestUserInput, true)]), + &BTreeMap::default(), )?; let mut mcp = McpProcess::new(codex_home.path()).await?; @@ -1029,13 +1029,15 @@ async fn turn_start_accepts_collaboration_mode_override_v2() -> Result<()> { let payload = request.body_json(); assert_eq!(payload["model"].as_str(), Some("mock-model-collab")); let payload_text = payload.to_string(); - assert!(payload_text.contains("The `request_user_input` tool is available in Default mode.")); + assert!(payload_text.contains( + "Use the `request_user_input` tool only when it is listed in the available tools" + )); Ok(()) } #[tokio::test] -async fn turn_start_uses_thread_feature_overrides_for_collaboration_mode_instructions_v2() +async fn turn_start_uses_thread_feature_overrides_for_request_user_input_tool_description_v2() -> Result<()> { skip_if_no_network!(Ok(())); @@ -1114,7 +1116,7 @@ async fn turn_start_uses_thread_feature_overrides_for_collaboration_mode_instruc let request = response_mock.single_request(); let payload_text = request.body_json().to_string(); - assert!(payload_text.contains("The `request_user_input` tool is available in Default mode.")); + assert!(payload_text.contains("This tool is only available in Default or Plan mode.")); Ok(()) } diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index 01e44fd8ca33..f3ab1600b464 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -62,7 +62,6 @@ use codex_features::is_known_feature_key; use codex_login::AuthManager; use codex_memories_write::clear_memory_roots_contents; use codex_models_manager::bundled_models_response; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_models_manager::manager::RefreshStrategy; use codex_protocol::protocol::AskForApproval; use codex_protocol::user_input::UserInput; @@ -1411,8 +1410,7 @@ async fn run_debug_models_command( let config = Config::load_with_cli_overrides(cli_overrides).await?; let auth_manager = AuthManager::shared_from_config(&config, /*enable_codex_api_key_env*/ true).await; - let models_manager = - build_models_manager(&config, auth_manager, CollaborationModesConfig::default()); + let models_manager = build_models_manager(&config, auth_manager); models_manager .raw_model_catalog(RefreshStrategy::OnlineIfUncached) .await diff --git a/codex-rs/collaboration-mode-templates/templates/default.md b/codex-rs/collaboration-mode-templates/templates/default.md index ff00857c6d16..715982c396bb 100644 --- a/codex-rs/collaboration-mode-templates/templates/default.md +++ b/codex-rs/collaboration-mode-templates/templates/default.md @@ -6,6 +6,6 @@ Your active mode changes only when new developer instructions with a different ` ## request_user_input availability -{{REQUEST_USER_INPUT_AVAILABILITY}} +Use the `request_user_input` tool only when it is listed in the available tools for this turn. -{{ASKING_QUESTIONS_GUIDANCE}} +In Default mode, strongly prefer making reasonable assumptions and executing the user's request rather than stopping to ask questions. If you absolutely must ask a question because the answer cannot be discovered from local context and a reasonable assumption would be risky, ask the user directly with a concise plain-text question. Never write a multiple choice question as a textual assistant message. diff --git a/codex-rs/core/src/prompt_debug.rs b/codex-rs/core/src/prompt_debug.rs index cc1203c2db38..88742b413e79 100644 --- a/codex-rs/core/src/prompt_debug.rs +++ b/codex-rs/core/src/prompt_debug.rs @@ -4,9 +4,7 @@ use std::sync::Arc; use codex_exec_server::EnvironmentManager; use codex_exec_server::EnvironmentManagerArgs; use codex_exec_server::ExecServerRuntimePaths; -use codex_features::Feature; use codex_login::AuthManager; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_protocol::error::Result as CodexResult; use codex_protocol::models::ResponseInputItem; use codex_protocol::models::ResponseItem; @@ -40,11 +38,6 @@ pub async fn build_prompt_input( &config, Arc::clone(&auth_manager), SessionSource::Exec, - CollaborationModesConfig { - default_mode_request_user_input: config - .features - .enabled(Feature::DefaultModeRequestUserInput), - }, Arc::new(EnvironmentManager::new(EnvironmentManagerArgs::new(local_runtime_paths)).await), /*analytics_events_client*/ None, ); diff --git a/codex-rs/core/src/test_support.rs b/codex-rs/core/src/test_support.rs index 0cb0e9d0cde1..6dbcf7a46487 100644 --- a/codex-rs/core/src/test_support.rs +++ b/codex-rs/core/src/test_support.rs @@ -106,11 +106,7 @@ pub fn models_manager_with_provider( provider: ModelProviderInfo, ) -> SharedModelsManager { let provider = create_model_provider(provider, Some(auth_manager)); - provider.models_manager( - codex_home, - /*config_model_catalog*/ None, - Default::default(), - ) + provider.models_manager(codex_home, /*config_model_catalog*/ None) } pub fn get_model_offline(model: Option<&str>) -> String { @@ -126,7 +122,5 @@ pub fn all_model_presets() -> &'static Vec { } pub fn builtin_collaboration_mode_presets() -> Vec { - collaboration_mode_presets::builtin_collaboration_mode_presets( - collaboration_mode_presets::CollaborationModesConfig::default(), - ) + collaboration_mode_presets::builtin_collaboration_mode_presets() } diff --git a/codex-rs/core/src/thread_manager.rs b/codex-rs/core/src/thread_manager.rs index 5d463f934638..52e22d100f5e 100644 --- a/codex-rs/core/src/thread_manager.rs +++ b/codex-rs/core/src/thread_manager.rs @@ -28,7 +28,6 @@ use codex_login::AuthManager; use codex_login::CodexAuth; use codex_model_provider::create_model_provider; use codex_model_provider_info::ModelProviderInfo; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_models_manager::manager::RefreshStrategy; use codex_models_manager::manager::SharedModelsManager; use codex_protocol::ThreadId; @@ -244,13 +243,11 @@ pub(crate) struct ThreadManagerState { pub fn build_models_manager( config: &Config, auth_manager: Arc, - collaboration_modes_config: CollaborationModesConfig, ) -> SharedModelsManager { let provider = create_model_provider(config.model_provider.clone(), Some(auth_manager)); provider.models_manager( config.codex_home.to_path_buf(), config.model_catalog.clone(), - collaboration_modes_config, ) } @@ -270,7 +267,6 @@ impl ThreadManager { config: &Config, auth_manager: Arc, session_source: SessionSource, - collaboration_modes_config: CollaborationModesConfig, environment_manager: Arc, analytics_events_client: Option, ) -> Self { @@ -292,11 +288,7 @@ impl ThreadManager { state: Arc::new(ThreadManagerState { threads: Arc::new(RwLock::new(HashMap::new())), thread_created_tx, - models_manager: build_models_manager( - config, - auth_manager.clone(), - collaboration_modes_config, - ), + models_manager: build_models_manager(config, auth_manager.clone()), environment_manager, skills_manager, plugins_manager, @@ -367,11 +359,7 @@ impl ThreadManager { threads: Arc::new(RwLock::new(HashMap::new())), thread_created_tx, models_manager: create_model_provider(provider, Some(auth_manager.clone())) - .models_manager( - codex_home, - /*config_model_catalog*/ None, - CollaborationModesConfig::default(), - ), + .models_manager(codex_home, /*config_model_catalog*/ None), environment_manager, skills_manager, plugins_manager, diff --git a/codex-rs/core/src/thread_manager_tests.rs b/codex-rs/core/src/thread_manager_tests.rs index 54d7ea4f7211..fe71938ac006 100644 --- a/codex-rs/core/src/thread_manager_tests.rs +++ b/codex-rs/core/src/thread_manager_tests.rs @@ -6,7 +6,6 @@ use crate::session::tests::make_session_and_context; use crate::tasks::InterruptedTurnHistoryMarker; use crate::tasks::interrupted_turn_history_marker; use codex_features::Feature; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_models_manager::manager::RefreshStrategy; use codex_protocol::models::ContentItem; use codex_protocol::models::ReasoningItemReasoningSummary; @@ -388,7 +387,6 @@ async fn resume_and_fork_do_not_restore_thread_environments_from_rollout() { &config, auth_manager.clone(), SessionSource::Exec, - CollaborationModesConfig::default(), Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, ); @@ -485,7 +483,6 @@ async fn new_uses_active_provider_for_model_refresh() { &config, auth_manager, SessionSource::Exec, - CollaborationModesConfig::default(), Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, ); @@ -696,7 +693,6 @@ async fn interrupted_fork_snapshot_does_not_synthesize_turn_id_for_legacy_histor &config, auth_manager.clone(), SessionSource::Exec, - CollaborationModesConfig::default(), Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, ); @@ -798,7 +794,6 @@ async fn interrupted_fork_snapshot_preserves_explicit_turn_id() { &config, auth_manager.clone(), SessionSource::Exec, - CollaborationModesConfig::default(), Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, ); @@ -889,7 +884,6 @@ async fn interrupted_fork_snapshot_uses_persisted_mid_turn_history_without_live_ &config, auth_manager.clone(), SessionSource::Exec, - CollaborationModesConfig::default(), Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, ); @@ -1025,7 +1019,6 @@ async fn resumed_thread_activates_paused_goal_and_continues_on_request() -> anyh &config, auth_manager.clone(), SessionSource::Exec, - CollaborationModesConfig::default(), Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, ); diff --git a/codex-rs/core/src/tools/handlers/request_user_input.rs b/codex-rs/core/src/tools/handlers/request_user_input.rs index 2c94145d31fd..eea66127623d 100644 --- a/codex-rs/core/src/tools/handlers/request_user_input.rs +++ b/codex-rs/core/src/tools/handlers/request_user_input.rs @@ -5,13 +5,14 @@ use crate::tools::context::ToolPayload; use crate::tools::handlers::parse_arguments; use crate::tools::registry::ToolHandler; use crate::tools::registry::ToolKind; +use codex_protocol::config_types::ModeKind; use codex_protocol::request_user_input::RequestUserInputArgs; use codex_tools::REQUEST_USER_INPUT_TOOL_NAME; use codex_tools::normalize_request_user_input_args; use codex_tools::request_user_input_unavailable_message; pub struct RequestUserInputHandler { - pub default_mode_request_user_input: bool, + pub available_modes: Vec, } impl ToolHandler for RequestUserInputHandler { @@ -46,9 +47,7 @@ impl ToolHandler for RequestUserInputHandler { } let mode = session.collaboration_mode().await.mode; - if let Some(message) = - request_user_input_unavailable_message(mode, self.default_mode_request_user_input) - { + if let Some(message) = request_user_input_unavailable_message(mode, &self.available_modes) { return Err(FunctionCallError::RespondToModel(message)); } diff --git a/codex-rs/core/src/tools/handlers/request_user_input_tests.rs b/codex-rs/core/src/tools/handlers/request_user_input_tests.rs index 811e4a668648..7c577c54bef3 100644 --- a/codex-rs/core/src/tools/handlers/request_user_input_tests.rs +++ b/codex-rs/core/src/tools/handlers/request_user_input_tests.rs @@ -23,7 +23,7 @@ async fn multi_agent_v2_request_user_input_rejects_subagent_threads() { }); let result = RequestUserInputHandler { - default_mode_request_user_input: true, + available_modes: Vec::new(), } .handle(ToolInvocation { session: Arc::new(session), diff --git a/codex-rs/core/src/tools/spec.rs b/codex-rs/core/src/tools/spec.rs index c167fdbc3ca6..308d8c46f734 100644 --- a/codex-rs/core/src/tools/spec.rs +++ b/codex-rs/core/src/tools/spec.rs @@ -166,7 +166,7 @@ pub(crate) fn build_specs_with_discoverable_tools( let shell_command_handler = Arc::new(ShellCommandHandler::from(config.shell_command_backend)); let request_permissions_handler = Arc::new(RequestPermissionsHandler); let request_user_input_handler = Arc::new(RequestUserInputHandler { - default_mode_request_user_input: config.default_mode_request_user_input, + available_modes: config.request_user_input_available_modes.clone(), }); let deferred_dynamic_tools = dynamic_tools .iter() diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index 60002eff446a..b7c63899f90c 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -26,7 +26,6 @@ use codex_login::CodexAuth; use codex_model_provider_info::ModelProviderInfo; use codex_model_provider_info::built_in_model_providers; use codex_models_manager::bundled_models_response; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_protocol::config_types::ServiceTier; use codex_protocol::models::PermissionProfile; use codex_protocol::openai_models::ModelsResponse; @@ -428,7 +427,6 @@ impl TestCodexBuilder { &config, codex_core::test_support::auth_manager_from_auth(auth.clone()), SessionSource::Exec, - CollaborationModesConfig::default(), Arc::clone(&environment_manager), /*analytics_events_client*/ None, ) diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index 67340f31672e..0c2e43aedf9d 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -13,7 +13,6 @@ use codex_model_provider_info::ModelProviderInfo; use codex_model_provider_info::WireApi; use codex_model_provider_info::built_in_model_providers; use codex_models_manager::bundled_models_response; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_otel::SessionTelemetry; use codex_otel::TelemetryAuthMode; use codex_protocol::ThreadId; @@ -1105,11 +1104,6 @@ async fn prefers_apikey_when_config_prefers_apikey_even_with_chatgpt_tokens() { &config, auth_manager, SessionSource::Exec, - CollaborationModesConfig { - default_mode_request_user_input: config - .features - .enabled(Feature::DefaultModeRequestUserInput), - }, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, ); diff --git a/codex-rs/core/tests/suite/skills.rs b/codex-rs/core/tests/suite/skills.rs index 183881013da9..c0645b7cfcee 100644 --- a/codex-rs/core/tests/suite/skills.rs +++ b/codex-rs/core/tests/suite/skills.rs @@ -8,7 +8,6 @@ use codex_exec_server::EnvironmentManager; use codex_exec_server::ExecServerRuntimePaths; use codex_exec_server::ExecutorFileSystem; use codex_login::CodexAuth; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::Op; @@ -239,7 +238,6 @@ async fn list_skills_skips_cwd_roots_when_environment_disabled() -> Result<()> { &config, codex_core::test_support::auth_manager_from_auth(CodexAuth::from_api_key("dummy")), SessionSource::Exec, - CollaborationModesConfig::default(), Arc::new(EnvironmentManager::disabled_for_tests( ExecServerRuntimePaths::new( std::env::current_exe()?, diff --git a/codex-rs/docs/codex_mcp_interface.md b/codex-rs/docs/codex_mcp_interface.md index b4e3adfe53c4..858afa36554f 100644 --- a/codex-rs/docs/codex_mcp_interface.md +++ b/codex-rs/docs/codex_mcp_interface.md @@ -88,6 +88,7 @@ Fetch the built-in collaboration mode presets with `collaborationMode/list`. Thi - `data` - ordered list of collaboration mode masks (partial settings to apply on top of the base mode) - For tri-state fields like `reasoning_effort` and `developer_instructions`, omit the field to keep the current value, set it to `null` to clear it, or set a concrete value to update it. + - Built-in presets do not set `model` or `reasoning_effort`; clients keep the current values unless they apply separate overrides. When sending `turn/start` with `collaborationMode`, `settings.developer_instructions: null` means "use built-in instructions for the selected mode". diff --git a/codex-rs/mcp-server/src/message_processor.rs b/codex-rs/mcp-server/src/message_processor.rs index 32d05d1f93ba..0e9a1435fcb7 100644 --- a/codex-rs/mcp-server/src/message_processor.rs +++ b/codex-rs/mcp-server/src/message_processor.rs @@ -5,11 +5,9 @@ use codex_arg0::Arg0DispatchPaths; use codex_core::ThreadManager; use codex_core::config::Config; use codex_exec_server::EnvironmentManager; -use codex_features::Feature; use codex_login::AuthManager; use codex_login::default_client::USER_AGENT_SUFFIX; use codex_login::default_client::get_codex_user_agent; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_protocol::ThreadId; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::Submission; @@ -65,11 +63,6 @@ impl MessageProcessor { config.as_ref(), auth_manager, SessionSource::Mcp, - CollaborationModesConfig { - default_mode_request_user_input: config - .features - .enabled(Feature::DefaultModeRequestUserInput), - }, environment_manager, /*analytics_events_client*/ None, )); diff --git a/codex-rs/model-provider/src/amazon_bedrock/mod.rs b/codex-rs/model-provider/src/amazon_bedrock/mod.rs index b9987ed2a84f..c8f772c62a14 100644 --- a/codex-rs/model-provider/src/amazon_bedrock/mod.rs +++ b/codex-rs/model-provider/src/amazon_bedrock/mod.rs @@ -11,7 +11,6 @@ use codex_login::AuthManager; use codex_login::CodexAuth; use codex_model_provider_info::ModelProviderAwsAuthInfo; use codex_model_provider_info::ModelProviderInfo; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_models_manager::manager::SharedModelsManager; use codex_models_manager::manager::StaticModelsManager; use codex_protocol::account::ProviderAccount; @@ -94,12 +93,10 @@ impl ModelProvider for AmazonBedrockModelProvider { &self, _codex_home: PathBuf, config_model_catalog: Option, - collaboration_modes_config: CollaborationModesConfig, ) -> SharedModelsManager { Arc::new(StaticModelsManager::new( /*auth_manager*/ None, config_model_catalog.unwrap_or_else(static_model_catalog), - collaboration_modes_config, )) } } diff --git a/codex-rs/model-provider/src/provider.rs b/codex-rs/model-provider/src/provider.rs index b6ce0da3cd2e..67240a6f57f7 100644 --- a/codex-rs/model-provider/src/provider.rs +++ b/codex-rs/model-provider/src/provider.rs @@ -7,7 +7,6 @@ use codex_api::SharedAuthProvider; use codex_login::AuthManager; use codex_login::CodexAuth; use codex_model_provider_info::ModelProviderInfo; -use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig; use codex_models_manager::manager::OpenAiModelsManager; use codex_models_manager::manager::SharedModelsManager; use codex_models_manager::manager::StaticModelsManager; @@ -118,7 +117,6 @@ pub trait ModelProvider: fmt::Debug + Send + Sync { &self, codex_home: PathBuf, config_model_catalog: Option, - collaboration_modes_config: CollaborationModesConfig, ) -> SharedModelsManager; } @@ -213,13 +211,11 @@ impl ModelProvider for ConfiguredModelProvider { &self, codex_home: PathBuf, config_model_catalog: Option, - collaboration_modes_config: CollaborationModesConfig, ) -> SharedModelsManager { match config_model_catalog { Some(model_catalog) => Arc::new(StaticModelsManager::new( self.auth_manager.clone(), model_catalog, - collaboration_modes_config, )), None => { let endpoint = Arc::new(OpenAiModelsEndpoint::new( @@ -230,7 +226,6 @@ impl ModelProvider for ConfiguredModelProvider { codex_home, endpoint, self.auth_manager.clone(), - collaboration_modes_config, )) } } @@ -445,11 +440,8 @@ mod tests { ModelProviderInfo::create_amazon_bedrock_provider(/*aws*/ None), /*auth_manager*/ None, ); - let manager = provider.models_manager( - test_codex_home(), - /*config_model_catalog*/ None, - Default::default(), - ); + let manager = + provider.models_manager(test_codex_home(), /*config_model_catalog*/ None); let catalog = manager.raw_model_catalog(RefreshStrategy::Online).await; let model_ids = catalog @@ -491,7 +483,6 @@ mod tests { Some(ModelsResponse { models: vec![custom_model], }), - Default::default(), ); let catalog = manager.raw_model_catalog(RefreshStrategy::Online).await; @@ -528,11 +519,8 @@ mod tests { )), ); - let manager = provider.models_manager( - test_codex_home(), - /*config_model_catalog*/ None, - Default::default(), - ); + let manager = + provider.models_manager(test_codex_home(), /*config_model_catalog*/ None); let catalog = manager.raw_model_catalog(RefreshStrategy::Online).await; assert!( diff --git a/codex-rs/models-manager/src/collaboration_mode_presets.rs b/codex-rs/models-manager/src/collaboration_mode_presets.rs index f67ab91db421..18969e6fe37e 100644 --- a/codex-rs/models-manager/src/collaboration_mode_presets.rs +++ b/codex-rs/models-manager/src/collaboration_mode_presets.rs @@ -3,33 +3,17 @@ use codex_collaboration_mode_templates::PLAN as COLLABORATION_MODE_PLAN; use codex_protocol::config_types::CollaborationModeMask; use codex_protocol::config_types::ModeKind; use codex_protocol::config_types::TUI_VISIBLE_COLLABORATION_MODES; -use codex_protocol::openai_models::ReasoningEffort; use codex_utils_template::Template; use std::sync::LazyLock; const KNOWN_MODE_NAMES_TEMPLATE_KEY: &str = "KNOWN_MODE_NAMES"; -const REQUEST_USER_INPUT_AVAILABILITY_TEMPLATE_KEY: &str = "REQUEST_USER_INPUT_AVAILABILITY"; -const ASKING_QUESTIONS_GUIDANCE_TEMPLATE_KEY: &str = "ASKING_QUESTIONS_GUIDANCE"; static COLLABORATION_MODE_DEFAULT_TEMPLATE: LazyLock