From 833212115e18e9eb75b0a75dcecf4034b8bab6ac Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Tue, 21 Apr 2026 08:33:58 -0700 Subject: [PATCH] Move external agent config out of core (#18850) ## Summary - Move external agent config migration logic and tests from `codex-core` into `app-server/src/config`. - Keep the migration service crate-private to app-server and update the API adapter imports. - Remove stale core re-exports and expose only the needed marketplace source helper. ## Testing - `cargo test -p codex-app-server config::external_agent_config` - `just fmt` - `just fix -p codex-app-server` - `just fix -p codex-core` - `git diff --check` --- .../src/config}/external_agent_config.rs | 67 +++++++++++-------- .../config}/external_agent_config_tests.rs | 0 codex-rs/app-server/src/config/mod.rs | 1 + .../src/external_agent_config_api.rs | 14 ++-- codex-rs/app-server/src/lib.rs | 1 + codex-rs/core/src/lib.rs | 1 - codex-rs/core/src/plugins/marketplace_add.rs | 2 +- codex-rs/core/src/plugins/mod.rs | 5 +- 8 files changed, 50 insertions(+), 41 deletions(-) rename codex-rs/{core/src => app-server/src/config}/external_agent_config.rs (95%) rename codex-rs/{core/src => app-server/src/config}/external_agent_config_tests.rs (100%) create mode 100644 codex-rs/app-server/src/config/mod.rs diff --git a/codex-rs/core/src/external_agent_config.rs b/codex-rs/app-server/src/config/external_agent_config.rs similarity index 95% rename from codex-rs/core/src/external_agent_config.rs rename to codex-rs/app-server/src/config/external_agent_config.rs index 18bf03227..1e57cd4a4 100644 --- a/codex-rs/core/src/external_agent_config.rs +++ b/codex-rs/app-server/src/config/external_agent_config.rs @@ -1,18 +1,18 @@ -use crate::config::Config; -use crate::config::ConfigBuilder; -use crate::plugins::MarketplaceAddRequest; -use crate::plugins::PluginId; -use crate::plugins::PluginInstallRequest; -use crate::plugins::PluginsManager; -use crate::plugins::add_marketplace; -use crate::plugins::configured_plugins_from_stack; -use crate::plugins::find_marketplace_manifest_path; -use crate::plugins::is_local_marketplace_source; -use crate::plugins::parse_marketplace_source; +use codex_config::types::PluginConfig; +use codex_core::config::Config; +use codex_core::config::ConfigBuilder; +use codex_core::plugins::MarketplaceAddRequest; +use codex_core::plugins::PluginId; +use codex_core::plugins::PluginInstallRequest; +use codex_core::plugins::PluginsManager; +use codex_core::plugins::add_marketplace; +use codex_core::plugins::is_local_marketplace_source; use codex_core_plugins::marketplace::MarketplacePluginInstallPolicy; +use codex_core_plugins::marketplace::find_marketplace_manifest_path; use codex_protocol::protocol::Product; use serde_json::Value as JsonValue; use std::collections::BTreeMap; +use std::collections::HashMap; use std::collections::HashSet; use std::ffi::OsString; use std::fs; @@ -29,13 +29,13 @@ const EXTERNAL_OFFICIAL_MARKETPLACE_NAME: &str = "claude-plugins-official"; const EXTERNAL_OFFICIAL_MARKETPLACE_SOURCE: &str = "anthropics/claude-plugins-official"; #[derive(Debug, Clone, PartialEq, Eq)] -pub struct ExternalAgentConfigDetectOptions { +pub(crate) struct ExternalAgentConfigDetectOptions { pub include_home: bool, pub cwds: Option>, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ExternalAgentConfigMigrationItemType { +pub(crate) enum ExternalAgentConfigMigrationItemType { Config, Skills, AgentsMd, @@ -44,24 +44,24 @@ pub enum ExternalAgentConfigMigrationItemType { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct PluginsMigration { +pub(crate) struct PluginsMigration { pub marketplace_name: String, pub plugin_names: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct MigrationDetails { +pub(crate) struct MigrationDetails { pub plugins: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct PendingPluginImport { +pub(crate) struct PendingPluginImport { pub cwd: Option, pub details: MigrationDetails, } #[derive(Debug, Clone, Default, PartialEq, Eq)] -pub struct PluginImportOutcome { +pub(crate) struct PluginImportOutcome { pub succeeded_marketplaces: Vec, pub succeeded_plugin_ids: Vec, pub failed_marketplaces: Vec, @@ -69,7 +69,7 @@ pub struct PluginImportOutcome { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct ExternalAgentConfigMigrationItem { +pub(crate) struct ExternalAgentConfigMigrationItem { pub item_type: ExternalAgentConfigMigrationItemType, pub description: String, pub cwd: Option, @@ -77,13 +77,13 @@ pub struct ExternalAgentConfigMigrationItem { } #[derive(Clone)] -pub struct ExternalAgentConfigService { +pub(crate) struct ExternalAgentConfigService { codex_home: PathBuf, external_agent_home: PathBuf, } impl ExternalAgentConfigService { - pub fn new(codex_home: PathBuf) -> Self { + pub(crate) fn new(codex_home: PathBuf) -> Self { let external_agent_home = default_external_agent_home(); Self { codex_home, @@ -99,7 +99,7 @@ impl ExternalAgentConfigService { } } - pub async fn detect( + pub(crate) async fn detect( &self, params: ExternalAgentConfigDetectOptions, ) -> io::Result> { @@ -119,7 +119,7 @@ impl ExternalAgentConfigService { Ok(items) } - pub async fn import( + pub(crate) async fn import( &self, migration_items: Vec, ) -> io::Result> { @@ -297,10 +297,21 @@ impl ExternalAgentConfigService { .await { Ok(config) => { - let configured_plugin_ids = - configured_plugins_from_stack(&config.config_layer_stack) - .into_keys() - .collect::>(); + let configured_plugin_ids = config + .config_layer_stack + .get_user_layer() + .and_then(|user_layer| user_layer.config.get("plugins")) + .and_then(|plugins| { + match plugins.clone().try_into::>() { + Ok(plugins) => Some(plugins), + Err(err) => { + tracing::warn!("invalid plugins config: {err}"); + None + } + } + }) + .map(|plugins| plugins.into_keys().collect::>()) + .unwrap_or_default(); let configured_marketplace_plugins = configured_marketplace_plugins( &config, &PluginsManager::new(self.codex_home.clone()), @@ -410,7 +421,7 @@ impl ExternalAgentConfigService { Ok((local_details, remote_details)) } - pub async fn import_plugins( + pub(crate) async fn import_plugins( &self, cwd: Option<&Path>, details: Option, @@ -638,7 +649,7 @@ fn extract_plugin_migration_details( let loadable_marketplaces = collect_marketplace_import_sources(settings, source_root) .into_iter() .filter_map(|(marketplace_name, source)| { - parse_marketplace_source(&source.source, source.ref_name) + is_local_marketplace_source(&source.source, source.ref_name) .ok() .map(|_| marketplace_name) }) diff --git a/codex-rs/core/src/external_agent_config_tests.rs b/codex-rs/app-server/src/config/external_agent_config_tests.rs similarity index 100% rename from codex-rs/core/src/external_agent_config_tests.rs rename to codex-rs/app-server/src/config/external_agent_config_tests.rs diff --git a/codex-rs/app-server/src/config/mod.rs b/codex-rs/app-server/src/config/mod.rs new file mode 100644 index 000000000..95d64d152 --- /dev/null +++ b/codex-rs/app-server/src/config/mod.rs @@ -0,0 +1 @@ +pub(crate) mod external_agent_config; diff --git a/codex-rs/app-server/src/external_agent_config_api.rs b/codex-rs/app-server/src/external_agent_config_api.rs index b381c353d..0741ad5bd 100644 --- a/codex-rs/app-server/src/external_agent_config_api.rs +++ b/codex-rs/app-server/src/external_agent_config_api.rs @@ -1,3 +1,8 @@ +use crate::config::external_agent_config::ExternalAgentConfigDetectOptions; +use crate::config::external_agent_config::ExternalAgentConfigMigrationItem as CoreMigrationItem; +use crate::config::external_agent_config::ExternalAgentConfigMigrationItemType as CoreMigrationItemType; +use crate::config::external_agent_config::ExternalAgentConfigService; +use crate::config::external_agent_config::PendingPluginImport; use crate::error_code::INTERNAL_ERROR_CODE; use codex_app_server_protocol::ExternalAgentConfigDetectParams; use codex_app_server_protocol::ExternalAgentConfigDetectResponse; @@ -7,11 +12,6 @@ use codex_app_server_protocol::ExternalAgentConfigMigrationItemType; use codex_app_server_protocol::JSONRPCErrorError; use codex_app_server_protocol::MigrationDetails; use codex_app_server_protocol::PluginsMigration; -use codex_core::external_agent_config::ExternalAgentConfigDetectOptions; -use codex_core::external_agent_config::ExternalAgentConfigMigrationItem as CoreMigrationItem; -use codex_core::external_agent_config::ExternalAgentConfigMigrationItemType as CoreMigrationItemType; -use codex_core::external_agent_config::ExternalAgentConfigService; -use codex_core::external_agent_config::PendingPluginImport; use std::io; use std::path::PathBuf; @@ -108,12 +108,12 @@ impl ExternalAgentConfigApi { description: migration_item.description, cwd: migration_item.cwd, details: migration_item.details.map(|details| { - codex_core::external_agent_config::MigrationDetails { + crate::config::external_agent_config::MigrationDetails { plugins: details .plugins .into_iter() .map(|plugin| { - codex_core::external_agent_config::PluginsMigration { + crate::config::external_agent_config::PluginsMigration { marketplace_name: plugin.marketplace_name, plugin_names: plugin.plugin_names, } diff --git a/codex-rs/app-server/src/lib.rs b/codex-rs/app-server/src/lib.rs index d9c108033..0eac54df2 100644 --- a/codex-rs/app-server/src/lib.rs +++ b/codex-rs/app-server/src/lib.rs @@ -70,6 +70,7 @@ mod app_server_tracing; mod bespoke_event_handling; mod codex_message_processor; mod command_exec; +mod config; mod config_api; mod dynamic_tools; mod error_code; diff --git a/codex-rs/core/src/lib.rs b/codex-rs/core/src/lib.rs index fc96aceaf..88a317444 100644 --- a/codex-rs/core/src/lib.rs +++ b/codex-rs/core/src/lib.rs @@ -32,7 +32,6 @@ mod context_manager; pub mod exec; pub mod exec_env; mod exec_policy; -pub mod external_agent_config; pub mod file_watcher; mod flags; #[cfg(test)] diff --git a/codex-rs/core/src/plugins/marketplace_add.rs b/codex-rs/core/src/plugins/marketplace_add.rs index 00bc19e40..a03a2134e 100644 --- a/codex-rs/core/src/plugins/marketplace_add.rs +++ b/codex-rs/core/src/plugins/marketplace_add.rs @@ -56,7 +56,7 @@ pub async fn add_marketplace( .map_err(|err| MarketplaceAddError::Internal(format!("failed to add marketplace: {err}")))? } -pub(crate) fn is_local_marketplace_source( +pub fn is_local_marketplace_source( source: &str, explicit_ref: Option, ) -> Result { diff --git a/codex-rs/core/src/plugins/mod.rs b/codex-rs/core/src/plugins/mod.rs index 5806016b9..55b9ff8a9 100644 --- a/codex-rs/core/src/plugins/mod.rs +++ b/codex-rs/core/src/plugins/mod.rs @@ -25,7 +25,6 @@ pub use codex_plugin::validate_plugin_segment; pub type LoadedPlugin = codex_plugin::LoadedPlugin; pub type PluginLoadOutcome = codex_plugin::PluginLoadOutcome; -pub(crate) use codex_core_plugins::marketplace::find_marketplace_manifest_path; pub(crate) use discoverable::list_tool_suggest_discoverable_plugins; pub(crate) use injection::build_plugin_injections; pub use installed_marketplaces::INSTALLED_MARKETPLACES_DIR; @@ -46,13 +45,11 @@ pub use manager::PluginRemoteSyncError; pub use manager::PluginUninstallError; pub use manager::PluginsManager; pub use manager::RemotePluginSyncResult; -pub(crate) use manager::configured_plugins_from_stack; pub use marketplace_add::MarketplaceAddError; pub use marketplace_add::MarketplaceAddOutcome; pub use marketplace_add::MarketplaceAddRequest; pub use marketplace_add::add_marketplace; -pub(crate) use marketplace_add::is_local_marketplace_source; -pub(crate) use marketplace_add::parse_marketplace_source; +pub use marketplace_add::is_local_marketplace_source; pub use marketplace_remove::MarketplaceRemoveError; pub use marketplace_remove::MarketplaceRemoveOutcome; pub use marketplace_remove::MarketplaceRemoveRequest;