From af7b472fd55cb5a648b7928e8ecee3aa5835f432 Mon Sep 17 00:00:00 2001 From: Dylan Hurd Date: Tue, 5 May 2026 22:26:43 -0400 Subject: [PATCH] fix(plugins): clean inactive versions on startup --- codex-rs/core-plugins/src/manager.rs | 1 + codex-rs/core-plugins/src/manager_tests.rs | 45 ++++++++++++++++++++++ codex-rs/core/src/session/mcp.rs | 3 -- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/codex-rs/core-plugins/src/manager.rs b/codex-rs/core-plugins/src/manager.rs index 89bb90883b..3f57e43b88 100644 --- a/codex-rs/core-plugins/src/manager.rs +++ b/codex-rs/core-plugins/src/manager.rs @@ -1487,6 +1487,7 @@ impl PluginsManager { on_effective_plugins_changed: Option>, ) { if config.plugins_enabled { + self.cleanup_inactive_plugin_versions_for_config(config); self.start_curated_repo_sync(); let should_spawn_marketplace_auto_upgrade = { let mut state = match self.configured_marketplace_upgrade_state.write() { diff --git a/codex-rs/core-plugins/src/manager_tests.rs b/codex-rs/core-plugins/src/manager_tests.rs index 1f20fa9cef..244bec8fc3 100644 --- a/codex-rs/core-plugins/src/manager_tests.rs +++ b/codex-rs/core-plugins/src/manager_tests.rs @@ -3198,6 +3198,51 @@ fn refresh_curated_plugin_cache_installs_short_sha_version_alongside_existing_lo ); } +#[tokio::test] +async fn cleanup_inactive_plugin_versions_for_config_removes_configured_inactive_versions() { + let tmp = tempfile::tempdir().unwrap(); + write_file( + &tmp.path().join(CONFIG_TOML_FILE), + r#"[features] +plugins = true + +[plugins."slack@openai-curated"] +enabled = true +"#, + ); + write_plugin( + &tmp.path().join("plugins/cache/openai-curated"), + "slack/1.0.0", + "slack", + ); + write_plugin( + &tmp.path().join("plugins/cache/openai-curated"), + "slack/2.0.0", + "slack", + ); + fs::write( + tmp.path() + .join("plugins/cache/openai-curated/slack/.active-version"), + "2.0.0\n", + ) + .unwrap(); + let config = load_config(tmp.path(), tmp.path()).await; + + PluginsManager::new(tmp.path().to_path_buf()) + .cleanup_inactive_plugin_versions_for_config(&config); + + assert!( + !tmp.path() + .join("plugins/cache/openai-curated/slack/1.0.0") + .exists() + ); + assert!( + tmp.path() + .join("plugins/cache/openai-curated/slack/2.0.0") + .is_dir() + ); +} + #[test] fn refresh_curated_plugin_cache_reinstalls_missing_configured_plugin_with_current_short_version() { let tmp = tempfile::tempdir().unwrap(); diff --git a/codex-rs/core/src/session/mcp.rs b/codex-rs/core/src/session/mcp.rs index dea4e4d5b0..d32ecf2b19 100644 --- a/codex-rs/core/src/session/mcp.rs +++ b/codex-rs/core/src/session/mcp.rs @@ -339,9 +339,6 @@ impl Session { std::mem::replace(&mut *manager, refreshed_manager) }; old_manager.shutdown().await; - self.services - .plugins_manager - .cleanup_inactive_plugin_versions_for_config(&config.plugins_config_input()); } pub(crate) async fn refresh_mcp_servers_if_requested(