mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat: Handle alternate plugin manifest paths (#18182)
Load plugin manifests through a shared discoverable-path helper so manifest reads, installs, and skill names all see the same alternate manifest location.
This commit is contained in:
committed by
GitHub
Unverified
parent
a803790a10
commit
37161bc76e
@@ -35,9 +35,10 @@ use codex_core_plugins::marketplace::MarketplacePluginAuthPolicy;
|
||||
use codex_core_plugins::marketplace::MarketplacePluginPolicy;
|
||||
use codex_core_plugins::marketplace::MarketplacePluginSource;
|
||||
use codex_core_plugins::marketplace::ResolvedMarketplacePlugin;
|
||||
use codex_core_plugins::marketplace::find_installable_marketplace_plugin;
|
||||
use codex_core_plugins::marketplace::find_marketplace_plugin;
|
||||
use codex_core_plugins::marketplace::list_marketplaces;
|
||||
use codex_core_plugins::marketplace::load_marketplace;
|
||||
use codex_core_plugins::marketplace::resolve_marketplace_plugin;
|
||||
use codex_core_plugins::marketplace_upgrade::ConfiguredMarketplaceUpgradeError;
|
||||
use codex_core_plugins::marketplace_upgrade::ConfiguredMarketplaceUpgradeOutcome;
|
||||
use codex_core_plugins::marketplace_upgrade::configured_git_marketplace_names;
|
||||
@@ -535,7 +536,7 @@ impl PluginsManager {
|
||||
&self,
|
||||
request: PluginInstallRequest,
|
||||
) -> Result<PluginInstallOutcome, PluginInstallError> {
|
||||
let resolved = resolve_marketplace_plugin(
|
||||
let resolved = find_installable_marketplace_plugin(
|
||||
&request.marketplace_path,
|
||||
&request.plugin_name,
|
||||
self.restriction_product,
|
||||
@@ -549,7 +550,7 @@ impl PluginsManager {
|
||||
auth: Option<&CodexAuth>,
|
||||
request: PluginInstallRequest,
|
||||
) -> Result<PluginInstallOutcome, PluginInstallError> {
|
||||
let resolved = resolve_marketplace_plugin(
|
||||
let resolved = find_installable_marketplace_plugin(
|
||||
&request.marketplace_path,
|
||||
&request.plugin_name,
|
||||
self.restriction_product,
|
||||
@@ -572,7 +573,7 @@ impl PluginsManager {
|
||||
&self,
|
||||
resolved: ResolvedMarketplacePlugin,
|
||||
) -> Result<PluginInstallOutcome, PluginInstallError> {
|
||||
let auth_policy = resolved.auth_policy;
|
||||
let auth_policy = resolved.policy.authentication;
|
||||
let plugin_version =
|
||||
if resolved.plugin_id.marketplace_name == OPENAI_CURATED_MARKETPLACE_NAME {
|
||||
Some(
|
||||
@@ -587,10 +588,11 @@ impl PluginsManager {
|
||||
};
|
||||
let store = self.store.clone();
|
||||
let result: StorePluginInstallResult = tokio::task::spawn_blocking(move || {
|
||||
let MarketplacePluginSource::Local { path: source_path } = resolved.source;
|
||||
if let Some(plugin_version) = plugin_version {
|
||||
store.install_with_version(resolved.source_path, resolved.plugin_id, plugin_version)
|
||||
store.install_with_version(source_path, resolved.plugin_id, plugin_version)
|
||||
} else {
|
||||
store.install(resolved.source_path, resolved.plugin_id)
|
||||
store.install(source_path, resolved.plugin_id)
|
||||
}
|
||||
})
|
||||
.await
|
||||
@@ -978,32 +980,24 @@ impl PluginsManager {
|
||||
return Err(MarketplaceError::PluginsDisabled);
|
||||
}
|
||||
|
||||
let marketplace = load_marketplace(&request.marketplace_path)?;
|
||||
let marketplace_name = marketplace.name.clone();
|
||||
let plugin = marketplace
|
||||
.plugins
|
||||
.into_iter()
|
||||
.find(|plugin| plugin.name == request.plugin_name);
|
||||
let Some(plugin) = plugin else {
|
||||
let plugin = find_marketplace_plugin(&request.marketplace_path, &request.plugin_name)?;
|
||||
if !self.restriction_product_matches(plugin.policy.products.as_deref()) {
|
||||
return Err(MarketplaceError::PluginNotFound {
|
||||
plugin_name: request.plugin_name.clone(),
|
||||
marketplace_name,
|
||||
plugin_name: plugin.plugin_id.plugin_name,
|
||||
marketplace_name: plugin.plugin_id.marketplace_name,
|
||||
});
|
||||
};
|
||||
let plugin_id = PluginId::new(plugin.name.clone(), marketplace.name.clone()).map_err(
|
||||
|err| match err {
|
||||
PluginIdError::Invalid(message) => MarketplaceError::InvalidPlugin(message),
|
||||
},
|
||||
)?;
|
||||
let plugin_key = plugin_id.as_key();
|
||||
}
|
||||
|
||||
let marketplace_name = plugin.plugin_id.marketplace_name.clone();
|
||||
let plugin_key = plugin.plugin_id.as_key();
|
||||
let (installed_plugins, enabled_plugins) = self.configured_plugin_states(config);
|
||||
let plugin = self
|
||||
.read_plugin_detail_for_marketplace_plugin(
|
||||
config,
|
||||
&marketplace.name,
|
||||
&marketplace_name,
|
||||
ConfiguredMarketplacePlugin {
|
||||
id: plugin_key.clone(),
|
||||
name: plugin.name,
|
||||
name: plugin.plugin_id.plugin_name,
|
||||
source: plugin.source,
|
||||
policy: plugin.policy,
|
||||
interface: plugin.interface,
|
||||
@@ -1014,12 +1008,12 @@ impl PluginsManager {
|
||||
.await?;
|
||||
|
||||
Ok(PluginReadOutcome {
|
||||
marketplace_name: if marketplace.name == OPENAI_CURATED_MARKETPLACE_NAME {
|
||||
marketplace_name: if marketplace_name == OPENAI_CURATED_MARKETPLACE_NAME {
|
||||
OPENAI_CURATED_MARKETPLACE_DISPLAY_NAME.to_string()
|
||||
} else {
|
||||
marketplace.name
|
||||
marketplace_name
|
||||
},
|
||||
marketplace_path: marketplace.path,
|
||||
marketplace_path: request.marketplace_path.clone(),
|
||||
plugin,
|
||||
})
|
||||
}
|
||||
@@ -1037,13 +1031,6 @@ impl PluginsManager {
|
||||
});
|
||||
}
|
||||
|
||||
let plugin_id =
|
||||
PluginId::new(plugin.name.clone(), marketplace_name.to_string()).map_err(|err| {
|
||||
match err {
|
||||
PluginIdError::Invalid(message) => MarketplaceError::InvalidPlugin(message),
|
||||
}
|
||||
})?;
|
||||
let plugin_key = plugin_id.as_key();
|
||||
let source_path = match &plugin.source {
|
||||
MarketplacePluginSource::Local { path } => path.clone(),
|
||||
};
|
||||
@@ -1053,20 +1040,16 @@ impl PluginsManager {
|
||||
));
|
||||
}
|
||||
let manifest = load_plugin_manifest(source_path.as_path()).ok_or_else(|| {
|
||||
MarketplaceError::InvalidPlugin(
|
||||
"missing or invalid .codex-plugin/plugin.json".to_string(),
|
||||
)
|
||||
MarketplaceError::InvalidPlugin("missing or invalid plugin.json".to_string())
|
||||
})?;
|
||||
let description = manifest.description.clone();
|
||||
let manifest_paths = &manifest.paths;
|
||||
let skill_config_rules = codex_core_skills::config_rules::skill_config_rules_from_stack(
|
||||
&config.config_layer_stack,
|
||||
);
|
||||
let resolved_skills = load_plugin_skills(
|
||||
&source_path,
|
||||
manifest_paths,
|
||||
&manifest.paths,
|
||||
self.restriction_product,
|
||||
&skill_config_rules,
|
||||
&codex_core_skills::config_rules::skill_config_rules_from_stack(
|
||||
&config.config_layer_stack,
|
||||
),
|
||||
)
|
||||
.await;
|
||||
let apps = load_plugin_apps(source_path.as_path()).await;
|
||||
@@ -1078,7 +1061,7 @@ impl PluginsManager {
|
||||
mcp_server_names.dedup();
|
||||
|
||||
Ok(PluginDetail {
|
||||
id: plugin_key,
|
||||
id: plugin.id,
|
||||
name: plugin.name,
|
||||
description,
|
||||
source: plugin.source,
|
||||
|
||||
@@ -1578,7 +1578,13 @@ source = "/tmp/debug"
|
||||
|
||||
let marketplace = marketplaces
|
||||
.into_iter()
|
||||
.find(|marketplace| marketplace.name == "debug")
|
||||
.find(|marketplace| {
|
||||
marketplace.path
|
||||
== AbsolutePathBuf::try_from(
|
||||
marketplace_root.join(".agents/plugins/marketplace.json"),
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
.expect("installed marketplace should be listed");
|
||||
|
||||
assert_eq!(
|
||||
@@ -1648,7 +1654,13 @@ source = "/tmp/debug"
|
||||
|
||||
let marketplace = marketplaces
|
||||
.into_iter()
|
||||
.find(|marketplace| marketplace.name == "debug")
|
||||
.find(|marketplace| {
|
||||
marketplace.path
|
||||
== AbsolutePathBuf::try_from(
|
||||
marketplace_root.join(".agents/plugins/marketplace.json"),
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
.expect("configured marketplace should be discovered");
|
||||
|
||||
assert_eq!(marketplace.plugins[0].id, "sample@debug");
|
||||
@@ -1695,7 +1707,16 @@ plugins = true
|
||||
.unwrap()
|
||||
.marketplaces;
|
||||
|
||||
assert!(marketplaces.is_empty());
|
||||
assert!(
|
||||
marketplaces.iter().all(|marketplace| {
|
||||
marketplace.path
|
||||
!= AbsolutePathBuf::try_from(
|
||||
marketplace_root.join(".agents/plugins/marketplace.json"),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
"installed marketplace root missing from config should not be listed"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user