From 833212115e18e9eb75b0a75dcecf4034b8bab6ac Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Tue, 21 Apr 2026 08:33:58 -0700 Subject: [PATCH 1/3] 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 18bf032277..1e57cd4a4d 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 0000000000..95d64d152a --- /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 b381c353da..0741ad5bd8 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 d9c108033f..0eac54df2a 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 fc96aceaf9..88a3174443 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 00bc19e40d..a03a2134e5 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 5806016b9a..55b9ff8a9e 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; From 53cf12cd529c0dd289731dce3bf1635cb5e48799 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Tue, 21 Apr 2026 09:00:40 -0700 Subject: [PATCH 2/3] build: reduce Rust dev debuginfo (#18844) ## What changed This PR makes the default Cargo dev profile use line-tables-only debug info: ```toml [profile.dev] debug = 1 ``` That keeps useful backtraces while avoiding the cost of full variable debug info in normal local dev builds. This also makes the Bazel CI setting explicit with `-Cdebuginfo=0` for target and exec-configuration Rust actions. Bazel/rules_rust does not read Cargo profiles for this setting, and the current fastbuild action already emitted `--codegen=debuginfo=0`; the Bazel part of this PR makes that choice direct in our build configuration. ## Why The slow codex-core rebuilds are dominated by debug-info codegen, not parsing or type checking. On a warm-dependency package rebuild, the baseline codex-core compile was about 39.5s wall / 38.9s rustc total, with codegen_crate around 14.0s and LLVM_passes around 13.4s. Setting codex-core to line-tables-only debug info brought that to about 27.2s wall / 26.7s rustc total, with codegen_crate around 3.1s and LLVM_passes around 2.8s. `debug = 0` was only about another 0.7s faster than `debug = 1` in the codex-core measurement, so `debug = 1` is the better default dev tradeoff: it captures nearly all of the compile-time win while preserving basic debuggability. I also sampled other first-party crates instead of keeping a codex-core-only package override. codex-app-server showed the same pattern: rustc total dropped from 15.85s to 10.48s, while codegen_crate plus LLVM_passes dropped from about 13.47s to 3.23s. codex-app-server-protocol had a smaller but still real improvement, 16.05s to 14.58s total, and smaller crates showed modest wins. That points to a workspace dev-profile policy rather than a hand-maintained list of large crates. ## Relationship to #18612 [#18612](https://github.com/openai/codex/pull/18612) added the `dev-small` profile. That remains useful when someone wants a working local build quickly and is willing to opt in with `cargo build --profile dev-small`. This PR is deliberately less aggressive: it changes the common default dev profile while preserving line tables/backtraces. `dev-small` remains the explicit "build quickly, no debuggability concern" path. ## Other investigation I looked for another structural win comparable to [#16631](https://github.com/openai/codex/pull/16631) and [#16630](https://github.com/openai/codex/pull/16630), but did not find one. The attempted TOML monomorphization changes were noisy or worse in measurement, and the async task changes reduced some instantiations but only translated to roughly a one-second improvement while being much more disruptive. The debug-info setting was the one repeatable, material win that survived measurement. ## Verification - `just bazel-lock-update` - `just bazel-lock-check` - `cargo check -p codex-core --lib` - `cargo test -p codex-core --lib` - Bazel `aquery --config=ci-linux` confirmed `--codegen=debuginfo=0` and `-Cdebuginfo=0` for `//codex-rs/core:core` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18844). * #18846 * __->__ #18844 --- .bazelrc | 4 ++++ codex-rs/Cargo.toml | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/.bazelrc b/.bazelrc index fb6e93e58c..112c2301e2 100644 --- a/.bazelrc +++ b/.bazelrc @@ -65,6 +65,10 @@ common:ci --verbose_failures common:ci --build_metadata=REPO_URL=https://github.com/openai/codex.git common:ci --build_metadata=ROLE=CI common:ci --build_metadata=VISIBILITY=PUBLIC +# rules_rust derives debug level from Bazel toolchain/compilation-mode settings, +# not Cargo profiles. Keep CI Rust actions explicit and lean. +common:ci --@rules_rust//rust/settings:extra_rustc_flag=-Cdebuginfo=0 +common:ci --@rules_rust//rust/settings:extra_exec_rustc_flag=-Cdebuginfo=0 # Disable disk cache in CI since we have a remote one and aren't using persistent workers. common:ci --disk_cache= diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index f4be9c1abc..b83674e591 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -430,6 +430,11 @@ ignored = [ "codex-v8-poc", ] +[profile.dev] +# Keep line tables/backtraces while avoiding expensive full variable debug info +# across local dev builds. +debug = 1 + [profile.dev-small] inherits = "dev" opt-level = 0 From bfada0a5d41eecbbfedc3c4357646b0fa4344a63 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Tue, 21 Apr 2026 09:01:08 -0700 Subject: [PATCH 3/3] core: make test-log a dev dependency test-log is only used by codex-core tests, so it does not need to be part of the normal codex-core dependency graph. Keeping it in dev-dependencies removes it from normal builds and keeps the production dependency set a little smaller. Verification: - `cargo tree -p codex-core --edges normal --invert test-log` - `cargo check -p codex-core --lib` - `cargo test -p codex-core --lib` --- codex-rs/core/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codex-rs/core/Cargo.toml b/codex-rs/core/Cargo.toml index 6ef6741fd9..d1cca0ac32 100644 --- a/codex-rs/core/Cargo.toml +++ b/codex-rs/core/Cargo.toml @@ -104,7 +104,6 @@ sha2 = { workspace = true } shlex = { workspace = true } similar = { workspace = true } tempfile = { workspace = true } -test-log = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true, features = [ "io-std", @@ -166,6 +165,7 @@ opentelemetry_sdk = { workspace = true, features = [ ] } serial_test = { workspace = true } tempfile = { workspace = true } +test-log = { workspace = true } tracing-opentelemetry = { workspace = true } tracing-subscriber = { workspace = true } tracing-test = { workspace = true, features = ["no-env-filter"] }