This commit is contained in:
Ahmed Ibrahim
2026-03-25 00:15:49 -07:00
parent 1661767afb
commit 143ca2120a
8 changed files with 52 additions and 169 deletions
+3 -137
View File
@@ -1,3 +1,5 @@
use super::LoadedPlugin;
use super::PluginLoadOutcome;
use super::PluginManifestPaths;
use super::curated_plugins_repo_path;
use super::load_plugin_manifest;
@@ -49,6 +51,7 @@ use codex_plugin::PluginCapabilitySummary;
use codex_plugin::PluginId;
use codex_plugin::PluginIdError;
use codex_plugin::PluginTelemetryMetadata;
use codex_plugin::prompt_safe_plugin_description;
use codex_protocol::protocol::Product;
use codex_protocol::protocol::SkillScope;
use codex_utils_absolute_path::AbsolutePathBuf;
@@ -76,7 +79,6 @@ const DEFAULT_MCP_CONFIG_FILE: &str = ".mcp.json";
const DEFAULT_APP_CONFIG_FILE: &str = ".app.json";
pub const OPENAI_CURATED_MARKETPLACE_NAME: &str = "openai-curated";
static CURATED_REPO_SYNC_STARTED: AtomicBool = AtomicBool::new(false);
const MAX_CAPABILITY_SUMMARY_DESCRIPTION_LEN: usize = 1024;
const FEATURED_PLUGIN_IDS_CACHE_TTL: std::time::Duration =
std::time::Duration::from_secs(60 * 60 * 3);
@@ -185,53 +187,6 @@ pub struct ConfiguredMarketplaceListOutcome {
pub errors: Vec<MarketplaceListError>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct LoadedPlugin {
pub config_name: String,
pub manifest_name: Option<String>,
pub manifest_description: Option<String>,
pub root: AbsolutePathBuf,
pub enabled: bool,
pub skill_roots: Vec<PathBuf>,
pub disabled_skill_paths: HashSet<PathBuf>,
pub has_enabled_skills: bool,
pub mcp_servers: HashMap<String, McpServerConfig>,
pub apps: Vec<AppConnectorId>,
pub error: Option<String>,
}
impl LoadedPlugin {
fn is_active(&self) -> bool {
self.enabled && self.error.is_none()
}
}
fn plugin_capability_summary_from_loaded(plugin: &LoadedPlugin) -> Option<PluginCapabilitySummary> {
if !plugin.is_active() {
return None;
}
let mut mcp_server_names: Vec<String> = plugin.mcp_servers.keys().cloned().collect();
mcp_server_names.sort_unstable();
let summary = PluginCapabilitySummary {
config_name: plugin.config_name.clone(),
display_name: plugin
.manifest_name
.clone()
.unwrap_or_else(|| plugin.config_name.clone()),
description: prompt_safe_plugin_description(plugin.manifest_description.as_deref()),
has_skills: plugin.has_enabled_skills,
mcp_server_names,
app_connector_ids: plugin.apps.clone(),
};
(summary.has_skills
|| !summary.mcp_server_names.is_empty()
|| !summary.app_connector_ids.is_empty())
.then_some(summary)
}
impl From<PluginDetail> for PluginCapabilitySummary {
fn from(value: PluginDetail) -> Self {
let has_skills = value.skills.iter().any(|skill| {
@@ -250,95 +205,6 @@ impl From<PluginDetail> for PluginCapabilitySummary {
}
}
fn prompt_safe_plugin_description(description: Option<&str>) -> Option<String> {
let description = description?
.split_whitespace()
.collect::<Vec<_>>()
.join(" ");
if description.is_empty() {
return None;
}
Some(
description
.chars()
.take(MAX_CAPABILITY_SUMMARY_DESCRIPTION_LEN)
.collect(),
)
}
#[derive(Debug, Clone, PartialEq)]
pub struct PluginLoadOutcome {
plugins: Vec<LoadedPlugin>,
capability_summaries: Vec<PluginCapabilitySummary>,
}
impl Default for PluginLoadOutcome {
fn default() -> Self {
Self::from_plugins(Vec::new())
}
}
impl PluginLoadOutcome {
fn from_plugins(plugins: Vec<LoadedPlugin>) -> Self {
let capability_summaries = plugins
.iter()
.filter_map(plugin_capability_summary_from_loaded)
.collect::<Vec<_>>();
Self {
plugins,
capability_summaries,
}
}
pub fn effective_skill_roots(&self) -> Vec<PathBuf> {
let mut skill_roots: Vec<PathBuf> = self
.plugins
.iter()
.filter(|plugin| plugin.is_active())
.flat_map(|plugin| plugin.skill_roots.iter().cloned())
.collect();
skill_roots.sort_unstable();
skill_roots.dedup();
skill_roots
}
pub fn effective_mcp_servers(&self) -> HashMap<String, McpServerConfig> {
let mut mcp_servers = HashMap::new();
for plugin in self.plugins.iter().filter(|plugin| plugin.is_active()) {
for (name, config) in &plugin.mcp_servers {
mcp_servers
.entry(name.clone())
.or_insert_with(|| config.clone());
}
}
mcp_servers
}
pub fn effective_apps(&self) -> Vec<AppConnectorId> {
let mut apps = Vec::new();
let mut seen_connector_ids = std::collections::HashSet::new();
for plugin in self.plugins.iter().filter(|plugin| plugin.is_active()) {
for connector_id in &plugin.apps {
if seen_connector_ids.insert(connector_id.clone()) {
apps.push(connector_id.clone());
}
}
}
apps
}
pub fn capability_summaries(&self) -> &[PluginCapabilitySummary] {
&self.capability_summaries
}
pub fn plugins(&self) -> &[LoadedPlugin] {
&self.plugins
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct RemotePluginSyncResult {
/// Plugin ids newly installed into the local plugin cache.
@@ -7,7 +7,9 @@ use crate::config_loader::ConfigLayerEntry;
use crate::config_loader::ConfigLayerStack;
use crate::config_loader::ConfigRequirements;
use crate::config_loader::ConfigRequirementsToml;
use crate::plugins::LoadedPlugin;
use crate::plugins::MarketplacePluginInstallPolicy;
use crate::plugins::PluginLoadOutcome;
use crate::plugins::test_support::TEST_CURATED_PLUGIN_SHA;
use crate::plugins::test_support::write_curated_plugin_sha_with as write_curated_plugin_sha;
use crate::plugins::test_support::write_file;
+7 -2
View File
@@ -1,3 +1,5 @@
use crate::config::types::McpServerConfig;
mod discoverable;
mod injection;
mod manager;
@@ -13,22 +15,25 @@ pub(crate) mod test_support;
mod toggles;
pub use codex_plugin::AppConnectorId;
pub use codex_plugin::EffectiveSkillRoots;
pub use codex_plugin::PluginCapabilitySummary;
pub use codex_plugin::PluginId;
pub use codex_plugin::PluginIdError;
pub use codex_plugin::PluginTelemetryMetadata;
pub type LoadedPlugin = codex_plugin::LoadedPlugin<McpServerConfig>;
pub type PluginLoadOutcome = codex_plugin::PluginLoadOutcome<McpServerConfig>;
pub(crate) use discoverable::list_tool_suggest_discoverable_plugins;
pub(crate) use injection::build_plugin_injections;
pub use manager::ConfiguredMarketplace;
pub use manager::ConfiguredMarketplaceListOutcome;
pub use manager::ConfiguredMarketplacePlugin;
pub use manager::LoadedPlugin;
pub use manager::OPENAI_CURATED_MARKETPLACE_NAME;
pub use manager::PluginDetail;
pub use manager::PluginInstallError;
pub use manager::PluginInstallOutcome;
pub use manager::PluginInstallRequest;
pub use manager::PluginLoadOutcome;
pub use manager::PluginReadOutcome;
pub use manager::PluginReadRequest;
pub use manager::PluginRemoteSyncError;