This commit is contained in:
alexsong-oai
2026-04-15 14:33:42 -07:00
parent 369fc518d4
commit 6759e3266b
4 changed files with 83 additions and 0 deletions
@@ -3,6 +3,7 @@ use crate::plugins::PluginId;
use crate::plugins::PluginInstallRequest;
use crate::plugins::PluginsManager;
use crate::plugins::add_marketplace;
use crate::plugins::validate_marketplace_add_source;
use codex_utils_absolute_path::AbsolutePathBuf;
use serde_json::Value as JsonValue;
use std::collections::BTreeMap;
@@ -536,6 +537,14 @@ fn extract_plugin_migration_details(
settings: &JsonValue,
configured_enabled_plugins: &HashSet<String>,
) -> Option<MigrationDetails> {
let loadable_marketplaces = collect_marketplace_import_sources(settings)
.into_iter()
.filter_map(|(marketplace_name, source)| {
validate_marketplace_add_source(&source.source, source.ref_name)
.ok()
.map(|()| marketplace_name)
})
.collect::<HashSet<_>>();
let mut plugins = BTreeMap::new();
for plugin_id in collect_enabled_plugins(settings)
.into_iter()
@@ -544,6 +553,9 @@ fn extract_plugin_migration_details(
let Ok(plugin_id) = PluginId::parse(&plugin_id) else {
continue;
};
if !loadable_marketplaces.contains(&plugin_id.marketplace_name) {
continue;
}
let plugin_group = plugins
.entry(plugin_id.marketplace_name.clone())
.or_insert_with(|| PluginsMigration {
@@ -418,6 +418,11 @@ fn detect_home_lists_enabled_plugins_from_settings() {
"formatter@acme-tools": true,
"deployer@acme-tools": true,
"analyzer@security-plugins": false
},
"extraKnownMarketplaces": {
"acme-tools": {
"source": "acme-corp/claude-plugins"
}
}
}"#,
)
@@ -464,6 +469,11 @@ fn detect_repo_skips_plugins_that_are_already_enabled_in_codex() {
"enabledPlugins": {
"formatter@acme-tools": true,
"deployer@acme-tools": true
},
"extraKnownMarketplaces": {
"acme-tools": {
"source": "acme-corp/claude-plugins"
}
}
}"#,
)
@@ -516,6 +526,59 @@ async fn import_plugins_requires_details() {
assert_eq!(err.to_string(), "plugins migration item is missing details");
}
#[test]
fn detect_home_skips_plugins_without_marketplace_source() {
let (_root, claude_home, codex_home) = fixture_paths();
fs::create_dir_all(&claude_home).expect("create claude home");
fs::write(
claude_home.join("settings.json"),
r#"{
"enabledPlugins": {
"formatter@acme-tools": true
}
}"#,
)
.expect("write settings");
let items = service_for_paths(claude_home, codex_home)
.detect(ExternalAgentConfigDetectOptions {
include_home: true,
cwds: None,
})
.expect("detect");
assert_eq!(items, Vec::<ExternalAgentConfigMigrationItem>::new());
}
#[test]
fn detect_home_skips_plugins_with_invalid_marketplace_source() {
let (_root, claude_home, codex_home) = fixture_paths();
fs::create_dir_all(&claude_home).expect("create claude home");
fs::write(
claude_home.join("settings.json"),
r#"{
"enabledPlugins": {
"formatter@acme-tools": true
},
"extraKnownMarketplaces": {
"acme-tools": {
"source": "github"
}
}
}"#,
)
.expect("write settings");
let items = service_for_paths(claude_home, codex_home)
.detect(ExternalAgentConfigDetectOptions {
include_home: true,
cwds: None,
})
.expect("detect");
assert_eq!(items, Vec::<ExternalAgentConfigMigrationItem>::new());
}
#[tokio::test]
async fn import_plugins_requires_source_marketplace_details() {
let (_root, claude_home, codex_home) = fixture_paths();
@@ -56,6 +56,13 @@ pub async fn add_marketplace(
.map_err(|err| MarketplaceAddError::Internal(format!("failed to add marketplace: {err}")))?
}
pub fn validate_marketplace_add_source(
source: &str,
ref_name: Option<String>,
) -> Result<(), MarketplaceAddError> {
parse_marketplace_source(source, ref_name).map(|_| ())
}
fn add_marketplace_sync(
codex_home: &Path,
request: MarketplaceAddRequest,
+1
View File
@@ -63,6 +63,7 @@ pub use marketplace_add::MarketplaceAddError;
pub use marketplace_add::MarketplaceAddOutcome;
pub use marketplace_add::MarketplaceAddRequest;
pub use marketplace_add::add_marketplace;
pub use marketplace_add::validate_marketplace_add_source;
pub use remote::RemotePluginFetchError;
pub use remote::fetch_remote_featured_plugin_ids;
pub(crate) use render::render_explicit_plugin_instructions;