| |
| |
| |
| |
|
|
| use crate::loader::load_plugin_apps_from_manifest; |
| use crate::loader::load_plugin_hooks; |
| use crate::loader::load_plugin_mcp_servers_from_manifest_with_format; |
| use crate::loader::plugin_skill_roots; |
| use crate::manifest::PluginManifestFormat; |
| use crate::manifest::load_plugin_manifest_with_format; |
| use crate::store::PluginStore; |
| use codex_hooks::plugin_hook_declarations; |
| use codex_plugin::PluginId; |
|
|
| |
| #[derive(Debug, Clone, Default, PartialEq, Eq)] |
| pub struct RemotePluginCapabilities { |
| pub has_mcps: bool, |
| pub has_apps: bool, |
| pub has_hooks: bool, |
| pub has_skills: bool, |
| } |
|
|
| impl RemotePluginCapabilities { |
| pub(crate) async fn include_active_bundle( |
| &mut self, |
| store: &PluginStore, |
| plugin_id: &PluginId, |
| ) { |
| let Some(root) = store.active_plugin_root(plugin_id) else { |
| return; |
| }; |
| let Some(loaded) = load_plugin_manifest_with_format(root.as_path()) else { |
| return; |
| }; |
| let paths = &loaded.manifest.paths; |
| self.has_skills |= !plugin_skill_roots(&root, paths, loaded.format).is_empty(); |
| self.has_mcps |= !load_plugin_mcp_servers_from_manifest_with_format( |
| root.as_path(), |
| paths, |
| None, |
| |
| |
| None, |
| loaded.format, |
| ) |
| .await |
| .is_empty(); |
| |
| |
| self.has_apps |= !load_plugin_apps_from_manifest(root.as_path(), paths) |
| .await |
| .is_empty(); |
| if loaded.format == PluginManifestFormat::Legacy { |
| let (sources, _) = |
| load_plugin_hooks(&root, plugin_id, &store.plugin_data_root(plugin_id), paths); |
| self.has_hooks |= !plugin_hook_declarations(&sources).is_empty(); |
| } |
| } |
| } |
|
|
| #[cfg(test)] |
| #[path = "plugin_capabilities_tests.rs"] |
| mod tests; |
|
|