Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions codex-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion codex-rs/app-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <feature_name> > 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; the Plan preset selects medium 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.
Expand Down
23 changes: 8 additions & 15 deletions codex-rs/app-server/src/codex_message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,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;
Expand Down Expand Up @@ -881,15 +880,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);
}
Expand Down Expand Up @@ -6479,13 +6476,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<Vec<TurnEnvironmentSelection>> =
params.environments.map(|environments| {
environments
Expand Down
6 changes: 0 additions & 6 deletions codex-rs/app-server/src/message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,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;
Expand Down Expand Up @@ -290,11 +289,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()),
));
Expand Down
Original file line number Diff line number Diff line change
@@ -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)]

Expand Down
10 changes: 6 additions & 4 deletions codex-rs/app-server/tests/suite/v2/turn_start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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?;
Expand Down Expand Up @@ -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(()));

Expand Down Expand Up @@ -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(())
}
Expand Down
4 changes: 1 addition & 3 deletions codex-rs/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions codex-rs/collaboration-mode-templates/templates/default.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
1 change: 0 additions & 1 deletion codex-rs/core-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ pub use codex_login::AuthManager;
pub use codex_login::default_client::set_default_originator;
pub use codex_model_provider_info::OPENAI_PROVIDER_ID;
pub use codex_model_provider_info::built_in_model_providers;
pub use codex_models_manager::collaboration_mode_presets::CollaborationModesConfig;
pub use codex_models_manager::manager::RefreshStrategy;
pub use codex_models_manager::manager::SharedModelsManager;
pub use codex_protocol::ThreadId;
Expand Down
7 changes: 0 additions & 7 deletions codex-rs/core/src/prompt_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -41,11 +39,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,
);
Expand Down
10 changes: 2 additions & 8 deletions codex-rs/core/src/test_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,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 {
Expand All @@ -130,7 +126,5 @@ pub fn all_model_presets() -> &'static Vec<ModelPreset> {
}

pub fn builtin_collaboration_mode_presets() -> Vec<CollaborationModeMask> {
collaboration_mode_presets::builtin_collaboration_mode_presets(
collaboration_mode_presets::CollaborationModesConfig::default(),
)
collaboration_mode_presets::builtin_collaboration_mode_presets()
}
16 changes: 2 additions & 14 deletions codex-rs/core/src/thread_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -255,13 +254,11 @@ pub(crate) struct ThreadManagerState {
pub fn build_models_manager(
config: &Config,
auth_manager: Arc<AuthManager>,
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,
)
}

Expand All @@ -281,7 +278,6 @@ impl ThreadManager {
config: &Config,
auth_manager: Arc<AuthManager>,
session_source: SessionSource,
collaboration_modes_config: CollaborationModesConfig,
environment_manager: Arc<EnvironmentManager>,
analytics_events_client: Option<AnalyticsEventsClient>,
) -> Self {
Expand All @@ -303,11 +299,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,
Expand Down Expand Up @@ -378,11 +370,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,
Expand Down
7 changes: 0 additions & 7 deletions codex-rs/core/src/thread_manager_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -392,7 +391,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,
);
Expand Down Expand Up @@ -499,7 +497,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,
);
Expand Down Expand Up @@ -710,7 +707,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,
);
Expand Down Expand Up @@ -814,7 +810,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,
);
Expand Down Expand Up @@ -907,7 +902,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,
);
Expand Down Expand Up @@ -1046,7 +1040,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,
);
Expand Down
7 changes: 3 additions & 4 deletions codex-rs/core/src/tools/handlers/request_user_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ModeKind>,
}

impl ToolHandler for RequestUserInputHandler {
Expand Down Expand Up @@ -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));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion codex-rs/core/src/tools/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 0 additions & 2 deletions codex-rs/core/tests/common/test_codex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,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;
Expand Down Expand Up @@ -429,7 +428,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,
)
Expand Down
Loading
Loading