From 75cc8b5a57be5018d4613631342751bccce4c898 Mon Sep 17 00:00:00 2001 From: jif-oai Date: Fri, 8 May 2026 14:33:20 +0200 Subject: [PATCH 1/3] extension: add codex-extension-api --- codex-rs/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 81a8528a1402..730df4236959 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -471,6 +471,7 @@ unwrap_used = "deny" ignored = [ "codex-agent-graph-store", "codex-extension-api", + "codex-memories-mcp", "icu_provider", "openssl-sys", "codex-v8-poc", From 2eb48e8467b45e6cd736c3a5385bcf54969ff6d0 Mon Sep 17 00:00:00 2001 From: jif-oai Date: Fri, 8 May 2026 14:37:38 +0200 Subject: [PATCH 2/3] extension: wire extension registries --- codex-rs/Cargo.lock | 5 ++ codex-rs/app-server/Cargo.toml | 1 + codex-rs/app-server/src/extensions.rs | 9 +++ codex-rs/app-server/src/lib.rs | 1 + codex-rs/app-server/src/mcp_refresh.rs | 2 + codex-rs/app-server/src/message_processor.rs | 2 + codex-rs/core-api/Cargo.toml | 1 + codex-rs/core-api/src/lib.rs | 1 + codex-rs/core/Cargo.toml | 1 + codex-rs/core/src/codex_delegate.rs | 1 + codex-rs/core/src/lib.rs | 1 + codex-rs/core/src/prompt_debug.rs | 2 + codex-rs/core/src/session/mod.rs | 30 ++++++++ codex-rs/core/src/session/session.rs | 15 ++++ codex-rs/core/src/session/tests.rs | 76 +++++++++++++++++++ .../core/src/session/tests/guardian_tests.rs | 1 + codex-rs/core/src/session/turn_context.rs | 6 +- codex-rs/core/src/state/service.rs | 5 ++ codex-rs/core/src/thread_manager.rs | 7 ++ codex-rs/core/src/thread_manager_tests.rs | 12 +++ .../src/tools/handlers/multi_agents_tests.rs | 2 + codex-rs/core/tests/common/Cargo.toml | 1 + codex-rs/core/tests/common/test_codex.rs | 2 + codex-rs/core/tests/suite/client.rs | 2 + codex-rs/mcp-server/Cargo.toml | 1 + codex-rs/mcp-server/src/message_processor.rs | 2 + codex-rs/thread-manager-sample/src/main.rs | 2 + 27 files changed, 188 insertions(+), 3 deletions(-) create mode 100644 codex-rs/app-server/src/extensions.rs diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 76b6209813f8..bf1d7be1c832 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -1895,6 +1895,7 @@ dependencies = [ "codex-core", "codex-core-plugins", "codex-exec-server", + "codex-extension-api", "codex-external-agent-migration", "codex-external-agent-sessions", "codex-features", @@ -2497,6 +2498,7 @@ dependencies = [ "codex-core-skills", "codex-exec-server", "codex-execpolicy", + "codex-extension-api", "codex-features", "codex-feedback", "codex-git-utils", @@ -2600,6 +2602,7 @@ dependencies = [ "codex-config", "codex-core", "codex-exec-server", + "codex-extension-api", "codex-features", "codex-login", "codex-model-provider-info", @@ -3100,6 +3103,7 @@ dependencies = [ "codex-config", "codex-core", "codex-exec-server", + "codex-extension-api", "codex-login", "codex-protocol", "codex-shell-command", @@ -4307,6 +4311,7 @@ dependencies = [ "codex-config", "codex-core", "codex-exec-server", + "codex-extension-api", "codex-features", "codex-hooks", "codex-login", diff --git a/codex-rs/app-server/Cargo.toml b/codex-rs/app-server/Cargo.toml index 5675640ff0fb..bb26b5bd7acb 100644 --- a/codex-rs/app-server/Cargo.toml +++ b/codex-rs/app-server/Cargo.toml @@ -37,6 +37,7 @@ codex-config = { workspace = true } codex-core = { workspace = true } codex-core-plugins = { workspace = true } codex-exec-server = { workspace = true } +codex-extension-api = { workspace = true } codex-external-agent-migration = { workspace = true } codex-external-agent-sessions = { workspace = true } codex-features = { workspace = true } diff --git a/codex-rs/app-server/src/extensions.rs b/codex-rs/app-server/src/extensions.rs new file mode 100644 index 000000000000..8fa5e3f69368 --- /dev/null +++ b/codex-rs/app-server/src/extensions.rs @@ -0,0 +1,9 @@ +use std::sync::Arc; + +use codex_core::config::Config; +use codex_extension_api::ExtensionRegistry; +use codex_extension_api::ExtensionRegistryBuilder; + +pub(crate) fn thread_extensions() -> Arc> { + Arc::new(ExtensionRegistryBuilder::::new().build()) +} diff --git a/codex-rs/app-server/src/lib.rs b/codex-rs/app-server/src/lib.rs index 6999948b049e..53f02b20687a 100644 --- a/codex-rs/app-server/src/lib.rs +++ b/codex-rs/app-server/src/lib.rs @@ -83,6 +83,7 @@ mod config_manager_service; mod connection_rpc_gate; mod dynamic_tools; mod error_code; +mod extensions; mod filters; mod fs_watch; mod fuzzy_file_search; diff --git a/codex-rs/app-server/src/mcp_refresh.rs b/codex-rs/app-server/src/mcp_refresh.rs index a327b4b125b9..c085e44cf6c0 100644 --- a/codex-rs/app-server/src/mcp_refresh.rs +++ b/codex-rs/app-server/src/mcp_refresh.rs @@ -99,6 +99,7 @@ async fn queue_refresh( #[cfg(test)] mod tests { use super::*; + use crate::extensions::thread_extensions; use async_trait::async_trait; use codex_arg0::Arg0DispatchPaths; use codex_config::CloudRequirementsLoader; @@ -183,6 +184,7 @@ mod tests { auth_manager, SessionSource::Exec, Arc::new(EnvironmentManager::default_for_tests()), + thread_extensions(), /*analytics_events_client*/ None, thread_store, Some(state_db.clone()), diff --git a/codex-rs/app-server/src/message_processor.rs b/codex-rs/app-server/src/message_processor.rs index c8204e05b613..8418d10b43d6 100644 --- a/codex-rs/app-server/src/message_processor.rs +++ b/codex-rs/app-server/src/message_processor.rs @@ -8,6 +8,7 @@ use crate::attestation::app_server_attestation_provider; use crate::config_manager::ConfigManager; use crate::connection_rpc_gate::ConnectionRpcGate; use crate::error_code::invalid_request; +use crate::extensions::thread_extensions; use crate::fs_watch::FsWatchManager; use crate::outgoing_message::ConnectionId; use crate::outgoing_message::ConnectionRequestId; @@ -303,6 +304,7 @@ impl MessageProcessor { auth_manager.clone(), session_source, environment_manager, + thread_extensions(), Some(analytics_events_client.clone()), Arc::clone(&thread_store), state_db.clone(), diff --git a/codex-rs/core-api/Cargo.toml b/codex-rs/core-api/Cargo.toml index 2b4a0216d618..998da39ce7b3 100644 --- a/codex-rs/core-api/Cargo.toml +++ b/codex-rs/core-api/Cargo.toml @@ -19,6 +19,7 @@ codex-arg0 = { workspace = true } codex-analytics = { workspace = true } codex-config = { workspace = true } codex-core = { workspace = true } +codex-extension-api = { workspace = true } codex-exec-server = { workspace = true } codex-features = { workspace = true } codex-login = { workspace = true } diff --git a/codex-rs/core-api/src/lib.rs b/codex-rs/core-api/src/lib.rs index 790079ec3094..ea3fe042c47d 100644 --- a/codex-rs/core-api/src/lib.rs +++ b/codex-rs/core-api/src/lib.rs @@ -45,6 +45,7 @@ pub use codex_core::skills::SkillsManager; pub use codex_core::thread_store_from_config; pub use codex_exec_server::EnvironmentManager; pub use codex_exec_server::ExecServerRuntimePaths; +pub use codex_extension_api::empty_extension_registry; pub use codex_features::Feature; pub use codex_features::Features; pub use codex_login::AuthManager; diff --git a/codex-rs/core/Cargo.toml b/codex-rs/core/Cargo.toml index 3e1d650a9866..bf58a2235b5b 100644 --- a/codex-rs/core/Cargo.toml +++ b/codex-rs/core/Cargo.toml @@ -35,6 +35,7 @@ codex-config = { workspace = true } codex-core-plugins = { workspace = true } codex-core-skills = { workspace = true } codex-exec-server = { workspace = true } +codex-extension-api = { workspace = true } codex-features = { workspace = true } codex-feedback = { workspace = true } codex-login = { workspace = true } diff --git a/codex-rs/core/src/codex_delegate.rs b/codex-rs/core/src/codex_delegate.rs index 793162cb2d22..5a01384bf005 100644 --- a/codex-rs/core/src/codex_delegate.rs +++ b/codex-rs/core/src/codex_delegate.rs @@ -83,6 +83,7 @@ pub(crate) async fn run_codex_thread_interactive( skills_manager: Arc::clone(&parent_session.services.skills_manager), plugins_manager: Arc::clone(&parent_session.services.plugins_manager), mcp_manager: Arc::clone(&parent_session.services.mcp_manager), + extensions: Arc::clone(&parent_session.services.extensions), conversation_history: initial_history.unwrap_or(InitialHistory::New), session_source: SessionSource::SubAgent(subagent_source.clone()), thread_source: Some(ThreadSource::Subagent), diff --git a/codex-rs/core/src/lib.rs b/codex-rs/core/src/lib.rs index 7b3de524c52c..93acda7854bc 100644 --- a/codex-rs/core/src/lib.rs +++ b/codex-rs/core/src/lib.rs @@ -22,6 +22,7 @@ mod config_lock; pub use codex_thread::CodexThread; pub use codex_thread::CodexThreadTurnContextOverrides; pub use codex_thread::ThreadConfigSnapshot; +pub use session::turn_context::TurnContext; mod agent; mod attestation; mod codex_delegate; diff --git a/codex-rs/core/src/prompt_debug.rs b/codex-rs/core/src/prompt_debug.rs index 688ce27508fd..72fa5b4e44a7 100644 --- a/codex-rs/core/src/prompt_debug.rs +++ b/codex-rs/core/src/prompt_debug.rs @@ -20,6 +20,7 @@ use crate::session::turn::built_tools; use crate::state_db_bridge::StateDbHandle; use crate::thread_manager::ThreadManager; use crate::thread_manager::thread_store_from_config; +use codex_extension_api::empty_extension_registry; /// Build the model-visible `input` list for a single debug turn. #[doc(hidden)] @@ -49,6 +50,7 @@ pub async fn build_prompt_input( .await .map_err(|err| CodexErr::Fatal(err.to_string()))?, ), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store, state_db.clone(), diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs index 7e4c8d7073be..6d28b9959c54 100644 --- a/codex-rs/core/src/session/mod.rs +++ b/codex-rs/core/src/session/mod.rs @@ -53,6 +53,7 @@ use codex_config::types::OAuthCredentialsStoreMode; use codex_exec_server::Environment; use codex_exec_server::EnvironmentManager; use codex_exec_server::FileSystemSandboxContext; +use codex_extension_api::PromptSlot; use codex_features::FEATURES; use codex_features::Feature; use codex_features::unstable_features_warning_event; @@ -392,6 +393,7 @@ pub(crate) struct CodexSpawnArgs { pub(crate) skills_manager: Arc, pub(crate) plugins_manager: Arc, pub(crate) mcp_manager: Arc, + pub(crate) extensions: Arc>, pub(crate) conversation_history: InitialHistory, pub(crate) session_source: SessionSource, pub(crate) thread_source: Option, @@ -455,6 +457,7 @@ impl Codex { skills_manager, plugins_manager, mcp_manager, + extensions, conversation_history, session_source, thread_source, @@ -650,6 +653,7 @@ impl Codex { skills_manager, plugins_manager, mcp_manager.clone(), + extensions, agent_control, environment_manager, analytics_events_client, @@ -2570,6 +2574,7 @@ impl Session { ) -> Vec { let mut developer_sections = Vec::::with_capacity(8); let mut contextual_user_sections = Vec::::with_capacity(2); + let mut separate_developer_sections = Vec::::new(); let ( reference_context_item, previous_turn_settings, @@ -2714,6 +2719,24 @@ impl Session { { developer_sections.push(commit_message_instruction); } + for contributor in self.services.extensions.context_contributors() { + for fragment in contributor.contribute( + &self.services.session_extension_data, + &self.services.thread_extension_data, + ) { + match fragment.slot() { + PromptSlot::DeveloperPolicy | PromptSlot::DeveloperCapabilities => { + developer_sections.push(fragment.text().to_string()); + } + PromptSlot::ContextualUser => { + contextual_user_sections.push(fragment.text().to_string()); + } + PromptSlot::SeparateDeveloper => { + separate_developer_sections.push(fragment.text().to_string()); + } + } + } + } if let Some(user_instructions) = turn_context.user_instructions.as_deref() { contextual_user_sections.push( UserInstructions { @@ -2746,6 +2769,13 @@ impl Session { { items.push(developer_message); } + for section in separate_developer_sections { + if let Some(developer_message) = + crate::context_manager::updates::build_developer_update_item(vec![section]) + { + items.push(developer_message); + } + } if let Some(usage_hint_text) = multi_agent_v2_usage_hint_text && let Some(usage_hint_message) = crate::context_manager::updates::build_developer_update_item(vec![ diff --git a/codex-rs/core/src/session/session.rs b/codex-rs/core/src/session/session.rs index 23d22f94a5ca..8c9ea1a123b7 100644 --- a/codex-rs/core/src/session/session.rs +++ b/codex-rs/core/src/session/session.rs @@ -364,6 +364,7 @@ impl Session { skills_manager: Arc, plugins_manager: Arc, mcp_manager: Arc, + extensions: Arc>, agent_control: AgentControl, environment_manager: Arc, analytics_events_client: Option, @@ -810,6 +811,16 @@ impl Session { SessionId::from(thread_id) }; let agent_control = agent_control.with_session_id(session_id); + let session_extension_data = codex_extension_api::ExtensionData::new(); + let thread_extension_data = codex_extension_api::ExtensionData::new(); + for contributor in extensions.thread_start_contributors() { + contributor.contribute( + config.as_ref(), + &session_extension_data, + &thread_extension_data, + ); + } + let services = SessionServices { // Initialize the MCP connection manager with an uninitialized // instance. It will be replaced with one created via @@ -845,6 +856,10 @@ impl Session { skills_manager, plugins_manager: Arc::clone(&plugins_manager), mcp_manager: Arc::clone(&mcp_manager), + extensions, + // TODO(jif): extract session to share between sub-agents + session_extension_data, + thread_extension_data, agent_control, network_proxy, network_approval: Arc::clone(&network_approval), diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index 6a5b08c12425..e331ea19eda0 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -3725,6 +3725,7 @@ async fn session_new_fails_when_zsh_fork_enabled_without_zsh_path() { skills_manager, plugins_manager, mcp_manager, + Arc::new(codex_extension_api::ExtensionRegistryBuilder::new().build()), AgentControl::default(), Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, @@ -3871,6 +3872,9 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) { skills_manager, plugins_manager, mcp_manager, + extensions: Arc::new(codex_extension_api::ExtensionRegistryBuilder::new().build()), + session_extension_data: codex_extension_api::ExtensionData::new(), + thread_extension_data: codex_extension_api::ExtensionData::new(), agent_control, network_proxy: None, network_approval: Arc::clone(&network_approval), @@ -4061,6 +4065,7 @@ async fn make_session_with_config_and_rx( skills_manager, plugins_manager, mcp_manager, + Arc::new(codex_extension_api::ExtensionRegistryBuilder::new().build()), AgentControl::default(), Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, @@ -4163,6 +4168,7 @@ async fn make_session_with_history_source_and_agent_control_and_rx( skills_manager, plugins_manager, mcp_manager, + Arc::new(codex_extension_api::ExtensionRegistryBuilder::new().build()), agent_control, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), /*analytics_events_client*/ None, @@ -5586,6 +5592,9 @@ where skills_manager, plugins_manager, mcp_manager, + extensions: Arc::new(codex_extension_api::ExtensionRegistryBuilder::new().build()), + session_extension_data: codex_extension_api::ExtensionData::new(), + thread_extension_data: codex_extension_api::ExtensionData::new(), agent_control, network_proxy: None, network_approval: Arc::clone(&network_approval), @@ -6133,6 +6142,73 @@ async fn make_multi_agent_v2_usage_hint_test_session( (session, turn_context) } +struct GitAttributionTestContributor; +struct GitAttributionTestState; + +impl codex_extension_api::ContextContributor for GitAttributionTestContributor { + fn contribute( + &self, + _session_store: &codex_extension_api::ExtensionData, + thread_store: &codex_extension_api::ExtensionData, + ) -> Vec { + thread_store + .get::() + .is_some() + .then(|| { + codex_extension_api::PromptFragment::developer_policy( + "git attribution extension enabled", + ) + }) + .into_iter() + .collect() + } +} + +fn git_attribution_test_registry() +-> Arc> { + let mut builder = codex_extension_api::ExtensionRegistryBuilder::new(); + builder.prompt_contributor(Arc::new(GitAttributionTestContributor)); + Arc::new(builder.build()) +} + +#[tokio::test] +async fn build_initial_context_includes_git_attribution_from_extensions() { + let (mut session, turn_context) = make_session_and_context().await; + session.services.extensions = git_attribution_test_registry(); + session + .services + .thread_extension_data + .insert(GitAttributionTestState); + + let initial_context = session.build_initial_context(&turn_context).await; + let developer_messages = developer_message_texts(&initial_context); + + assert!( + developer_messages + .iter() + .flatten() + .any(|text| *text == "git attribution extension enabled"), + "expected git attribution developer text, got {developer_messages:?}" + ); +} + +#[tokio::test] +async fn build_initial_context_omits_git_attribution_when_feature_is_disabled() { + let (mut session, turn_context) = make_session_and_context().await; + session.services.extensions = git_attribution_test_registry(); + + let initial_context = session.build_initial_context(&turn_context).await; + let developer_messages = developer_message_texts(&initial_context); + + assert!( + !developer_messages + .iter() + .flatten() + .any(|text| *text == "git attribution extension enabled"), + "did not expect git attribution developer text, got {developer_messages:?}" + ); +} + #[tokio::test] async fn build_initial_context_adds_multi_agent_v2_root_usage_hint_as_developer_message() { let (session, turn_context) = diff --git a/codex-rs/core/src/session/tests/guardian_tests.rs b/codex-rs/core/src/session/tests/guardian_tests.rs index 8d4bfd9cbe4d..730b9f5e87ba 100644 --- a/codex-rs/core/src/session/tests/guardian_tests.rs +++ b/codex-rs/core/src/session/tests/guardian_tests.rs @@ -742,6 +742,7 @@ async fn guardian_subagent_does_not_inherit_parent_exec_policy_rules() { skills_manager, plugins_manager, mcp_manager, + extensions: codex_extension_api::empty_extension_registry(), conversation_history: InitialHistory::New, session_source: SessionSource::SubAgent(SubAgentSource::Other( GUARDIAN_REVIEWER_NAME.to_string(), diff --git a/codex-rs/core/src/session/turn_context.rs b/codex-rs/core/src/session/turn_context.rs index 5c8aad022541..5a8885e0f3df 100644 --- a/codex-rs/core/src/session/turn_context.rs +++ b/codex-rs/core/src/session/turn_context.rs @@ -52,11 +52,11 @@ impl TurnEnvironment { /// The context needed for a single turn of the thread. #[derive(Debug)] -pub(crate) struct TurnContext { +pub struct TurnContext { pub(crate) sub_id: String, pub(crate) trace_id: Option, pub(crate) realtime_active: bool, - pub(crate) config: Arc, + pub config: Arc, pub(crate) auth_manager: Option>, pub(crate) model_info: ModelInfo, pub(crate) session_telemetry: SessionTelemetry, @@ -84,7 +84,7 @@ pub(crate) struct TurnContext { pub(crate) windows_sandbox_level: WindowsSandboxLevel, pub(crate) shell_environment_policy: ShellEnvironmentPolicy, pub(crate) tools_config: ToolsConfig, - pub(crate) features: ManagedFeatures, + pub features: ManagedFeatures, pub(crate) ghost_snapshot: GhostSnapshotConfig, pub(crate) final_output_json_schema: Option, pub(crate) codex_self_exe: Option, diff --git a/codex-rs/core/src/state/service.rs b/codex-rs/core/src/state/service.rs index 7e13eddb769f..afba409a068e 100644 --- a/codex-rs/core/src/state/service.rs +++ b/codex-rs/core/src/state/service.rs @@ -18,6 +18,8 @@ use arc_swap::ArcSwap; use codex_analytics::AnalyticsEventsClient; use codex_core_plugins::PluginsManager; use codex_exec_server::EnvironmentManager; +use codex_extension_api::ExtensionData; +use codex_extension_api::ExtensionRegistry; use codex_hooks::Hooks; use codex_login::AuthManager; use codex_mcp::McpConnectionManager; @@ -59,6 +61,9 @@ pub(crate) struct SessionServices { pub(crate) skills_manager: Arc, pub(crate) plugins_manager: Arc, pub(crate) mcp_manager: Arc, + pub(crate) extensions: Arc>, + pub(crate) session_extension_data: ExtensionData, + pub(crate) thread_extension_data: ExtensionData, pub(crate) agent_control: AgentControl, pub(crate) network_proxy: Option, pub(crate) network_approval: Arc, diff --git a/codex-rs/core/src/thread_manager.rs b/codex-rs/core/src/thread_manager.rs index bfd91f68f806..83bfe3b3d1f9 100644 --- a/codex-rs/core/src/thread_manager.rs +++ b/codex-rs/core/src/thread_manager.rs @@ -20,6 +20,8 @@ use codex_app_server_protocol::ThreadHistoryBuilder; use codex_app_server_protocol::TurnStatus; use codex_core_plugins::PluginsManager; use codex_exec_server::EnvironmentManager; +use codex_extension_api::ExtensionRegistry; +use codex_extension_api::empty_extension_registry; use codex_login::AuthManager; use codex_login::CodexAuth; use codex_model_provider::create_model_provider; @@ -201,6 +203,7 @@ pub(crate) struct ThreadManagerState { skills_manager: Arc, plugins_manager: Arc, mcp_manager: Arc, + extensions: Arc>, thread_store: Arc, attestation_provider: Option>, session_source: SessionSource, @@ -242,6 +245,7 @@ impl ThreadManager { auth_manager: Arc, session_source: SessionSource, environment_manager: Arc, + extensions: Arc>, analytics_events_client: Option, thread_store: Arc, state_db: Option, @@ -270,6 +274,7 @@ impl ThreadManager { skills_manager, plugins_manager, mcp_manager, + extensions, thread_store, attestation_provider, auth_manager, @@ -370,6 +375,7 @@ impl ThreadManager { skills_manager, plugins_manager, mcp_manager, + extensions: empty_extension_registry(), thread_store, attestation_provider: None, auth_manager, @@ -1129,6 +1135,7 @@ impl ThreadManagerState { skills_manager: Arc::clone(&self.skills_manager), plugins_manager: Arc::clone(&self.plugins_manager), mcp_manager: Arc::clone(&self.mcp_manager), + extensions: Arc::clone(&self.extensions), conversation_history: initial_history, session_source, thread_source, diff --git a/codex-rs/core/src/thread_manager_tests.rs b/codex-rs/core/src/thread_manager_tests.rs index 21fa03ad7f5b..9fedff94707b 100644 --- a/codex-rs/core/src/thread_manager_tests.rs +++ b/codex-rs/core/src/thread_manager_tests.rs @@ -7,6 +7,7 @@ use crate::session::session::SessionSettingsUpdate; use crate::session::tests::make_session_and_context; use crate::tasks::InterruptedTurnHistoryMarker; use crate::tasks::interrupted_turn_history_marker; +use codex_extension_api::empty_extension_registry; use codex_features::Feature; use codex_models_manager::manager::RefreshStrategy; use codex_protocol::models::ContentItem; @@ -495,6 +496,7 @@ async fn resume_and_fork_do_not_restore_thread_environments_from_rollout() { auth_manager.clone(), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, /*state_db*/ None), /*state_db*/ None, @@ -612,6 +614,7 @@ async fn explicit_installation_id_skips_codex_home_file() { auth_manager, SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store, state_db.clone(), @@ -650,6 +653,7 @@ async fn resume_active_thread_from_rollout_returns_running_thread() { auth_manager.clone(), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, /*state_db*/ None), /*state_db*/ None, @@ -706,6 +710,7 @@ async fn resume_stopped_thread_from_rollout_spawns_new_thread() { auth_manager.clone(), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, /*state_db*/ None), /*state_db*/ None, @@ -769,6 +774,7 @@ async fn resume_stopped_thread_from_rollout_preserves_thread_source() { auth_manager.clone(), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store, state_db.clone(), @@ -858,6 +864,7 @@ async fn rollout_path_resume_and_fork_read_history_through_thread_store() { auth_manager.clone(), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store.clone(), state_db, @@ -960,6 +967,7 @@ async fn new_uses_active_provider_for_model_refresh() { auth_manager, SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, /*state_db*/ None), /*state_db*/ None, @@ -1175,6 +1183,7 @@ async fn interrupted_fork_snapshot_does_not_synthesize_turn_id_for_legacy_histor auth_manager.clone(), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, state_db.clone()), state_db.clone(), @@ -1282,6 +1291,7 @@ async fn interrupted_fork_snapshot_preserves_explicit_turn_id() { auth_manager.clone(), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, state_db.clone()), state_db.clone(), @@ -1378,6 +1388,7 @@ async fn interrupted_fork_snapshot_uses_persisted_mid_turn_history_without_live_ auth_manager.clone(), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, state_db.clone()), state_db.clone(), @@ -1520,6 +1531,7 @@ async fn resumed_thread_keeps_paused_goal_paused() -> anyhow::Result<()> { auth_manager.clone(), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, state_db.clone()), state_db.clone(), diff --git a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs index e7625fa44ffe..b030cb010c80 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs @@ -15,6 +15,7 @@ use crate::tools::handlers::multi_agents_v2::SendMessageHandler as SendMessageHa use crate::tools::handlers::multi_agents_v2::SpawnAgentHandler as SpawnAgentHandlerV2; use crate::tools::handlers::multi_agents_v2::WaitAgentHandler as WaitAgentHandlerV2; use crate::turn_diff_tracker::TurnDiffTracker; +use codex_extension_api::empty_extension_registry; use codex_features::Feature; use codex_login::AuthManager; use codex_login::CodexAuth; @@ -3163,6 +3164,7 @@ async fn tool_handlers_cascade_close_and_resume_and_keep_explicitly_closed_subtr AuthManager::from_auth_for_testing(CodexAuth::from_api_key("dummy")), SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, state_db.clone()), state_db.clone(), diff --git a/codex-rs/core/tests/common/Cargo.toml b/codex-rs/core/tests/common/Cargo.toml index e22a2872679e..fb6221cfce0c 100644 --- a/codex-rs/core/tests/common/Cargo.toml +++ b/codex-rs/core/tests/common/Cargo.toml @@ -18,6 +18,7 @@ base64 = { workspace = true } codex-arg0 = { workspace = true } codex-config = { workspace = true } codex-core = { workspace = true } +codex-extension-api = { workspace = true } codex-exec-server = { workspace = true } codex-features = { workspace = true } codex-hooks = { workspace = true } diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index 026c84ee2c40..24c25d63642d 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -23,6 +23,7 @@ use codex_core::thread_store_from_config; use codex_exec_server::CreateDirectoryOptions; use codex_exec_server::ExecutorFileSystem; use codex_exec_server::RemoveOptions; +use codex_extension_api::empty_extension_registry; use codex_features::Feature; use codex_login::CodexAuth; use codex_model_provider_info::ModelProviderInfo; @@ -437,6 +438,7 @@ impl TestCodexBuilder { codex_core::test_support::auth_manager_from_auth(auth.clone()), SessionSource::Exec, Arc::clone(&environment_manager), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store, state_db.clone(), diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index 83a7865d1658..510de6f1bfc3 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -7,6 +7,7 @@ use codex_core::ResponseEvent; use codex_core::ThreadManager; use codex_core::resolve_installation_id; use codex_core::thread_store_from_config; +use codex_extension_api::empty_extension_registry; use codex_features::Feature; use codex_login::AuthManager; use codex_login::CodexAuth; @@ -1137,6 +1138,7 @@ async fn prefers_apikey_when_config_prefers_apikey_even_with_chatgpt_tokens() { auth_manager, SessionSource::Exec, Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()), + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(&config, /*state_db*/ None), /*state_db*/ None, diff --git a/codex-rs/mcp-server/Cargo.toml b/codex-rs/mcp-server/Cargo.toml index ffe729aae123..29b2d6c7d721 100644 --- a/codex-rs/mcp-server/Cargo.toml +++ b/codex-rs/mcp-server/Cargo.toml @@ -22,6 +22,7 @@ codex-arg0 = { workspace = true } codex-config = { workspace = true } codex-core = { workspace = true } codex-exec-server = { workspace = true } +codex-extension-api = { workspace = true } codex-login = { workspace = true } codex-protocol = { workspace = true } codex-utils-cli = { workspace = true } diff --git a/codex-rs/mcp-server/src/message_processor.rs b/codex-rs/mcp-server/src/message_processor.rs index f963747e8774..7a06bcc02c19 100644 --- a/codex-rs/mcp-server/src/message_processor.rs +++ b/codex-rs/mcp-server/src/message_processor.rs @@ -7,6 +7,7 @@ use codex_core::ThreadManager; use codex_core::config::Config; use codex_core::thread_store_from_config; use codex_exec_server::EnvironmentManager; +use codex_extension_api::empty_extension_registry; use codex_login::AuthManager; use codex_login::default_client::USER_AGENT_SUFFIX; use codex_login::default_client::get_codex_user_agent; @@ -68,6 +69,7 @@ impl MessageProcessor { auth_manager, SessionSource::Mcp, environment_manager, + empty_extension_registry(), /*analytics_events_client*/ None, thread_store_from_config(config.as_ref(), state_db.clone()), state_db.clone(), diff --git a/codex-rs/thread-manager-sample/src/main.rs b/codex-rs/thread-manager-sample/src/main.rs index 68a95bd2d98b..191c294c9e46 100644 --- a/codex-rs/thread-manager-sample/src/main.rs +++ b/codex-rs/thread-manager-sample/src/main.rs @@ -53,6 +53,7 @@ use codex_core_api::UserInput; use codex_core_api::WebSearchMode; use codex_core_api::arg0_dispatch_or_else; use codex_core_api::built_in_model_providers; +use codex_core_api::empty_extension_registry; use codex_core_api::find_codex_home; use codex_core_api::init_state_db; use codex_core_api::item_event_to_server_notification; @@ -122,6 +123,7 @@ async fn run_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> { auth_manager, SessionSource::Exec, environment_manager, + empty_extension_registry(), /*analytics_events_client*/ None, Arc::clone(&thread_store), state_db, From 2b1bb06a8cc1a2824d27b05c2e7296a0505ec74b Mon Sep 17 00:00:00 2001 From: jif-oai Date: Mon, 11 May 2026 10:30:33 +0100 Subject: [PATCH 3/3] nit fix --- codex-rs/Cargo.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 730df4236959..41ba8c69ba6e 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -470,8 +470,6 @@ unwrap_used = "deny" [workspace.metadata.cargo-shear] ignored = [ "codex-agent-graph-store", - "codex-extension-api", - "codex-memories-mcp", "icu_provider", "openssl-sys", "codex-v8-poc",