mirror of
https://github.com/openai/codex.git
synced 2026-11-14 21:40:39 +00:00
Add batched executor capability discovery (#33852)
## Why Selected capability roots can contribute plugins, MCP servers, connectors, and skills. Discovering each contribution separately requires repeated access to the executor filesystem. ## What changed - Add the `capabilityRoots/discoverV1` exec-server RPC to scan selected roots and materialize recognized plugin manifests, configuration files, skill instructions, and skill metadata in one bounded request. - Add the opt-in `executor_capability_discovery` feature, with a thread-scoped cache and per-step snapshot shared by MCP and skill discovery. - Parse MCP, connector, and skill contributions from the materialized snapshot, including serving cached skill instructions without another filesystem read. ## Testing - Cover discovery limits, manifest precedence, root-local failures, cache reuse, plugin contributions, and parity with the existing environment skill loader. GitOrigin-RevId: f98fd2321cafb58c596db02da1f83c09d8eb375d
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
use codex_connectors::parse_plugin_app_config;
|
||||
use codex_core_plugins::manifest::parse_plugin_manifest_uri;
|
||||
use codex_exec_server::CapabilityRootDiscovery;
|
||||
use codex_mcp::parse_executor_plugin_mcp_config;
|
||||
use codex_plugin::manifest::PluginManifestMcpServers;
|
||||
use codex_protocol::capabilities::CapabilityRootLocation;
|
||||
use codex_protocol::capabilities::SelectedCapabilityRoot;
|
||||
|
||||
use super::SelectedPluginMetadata;
|
||||
|
||||
pub(super) fn metadata_from_discovery(
|
||||
selected_root: &SelectedCapabilityRoot,
|
||||
discovery: &CapabilityRootDiscovery,
|
||||
) -> Option<SelectedPluginMetadata> {
|
||||
for warning in &discovery.warnings {
|
||||
tracing::warn!(
|
||||
selected_root = selected_root.id,
|
||||
warning,
|
||||
"exec-server capability discovery warning"
|
||||
);
|
||||
}
|
||||
if let Some(error) = &discovery.error {
|
||||
tracing::warn!(
|
||||
selected_root = selected_root.id,
|
||||
error,
|
||||
"exec-server capability discovery failed"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
let plugin_files = discovery.plugin.as_ref()?;
|
||||
let manifest = match parse_plugin_manifest_uri(
|
||||
&discovery.path,
|
||||
&plugin_files.manifest.path,
|
||||
&plugin_files.manifest.contents,
|
||||
) {
|
||||
Ok(manifest) => manifest,
|
||||
Err(error) => {
|
||||
tracing::warn!(
|
||||
selected_root = selected_root.id,
|
||||
path = %plugin_files.manifest.path,
|
||||
%error,
|
||||
"failed to parse exec-server-discovered plugin manifest"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let CapabilityRootLocation::Environment { environment_id, .. } = &selected_root.location;
|
||||
let servers = match manifest.paths.mcp_servers.as_ref() {
|
||||
Some(PluginManifestMcpServers::Object(contents)) => {
|
||||
parse_mcp_servers(selected_root, &discovery.path, contents, environment_id)
|
||||
}
|
||||
Some(PluginManifestMcpServers::Path(path)) => plugin_files
|
||||
.mcp_config
|
||||
.as_ref()
|
||||
.filter(|file| file.path == *path)
|
||||
.map(|file| {
|
||||
parse_mcp_servers(
|
||||
selected_root,
|
||||
&discovery.path,
|
||||
&file.contents,
|
||||
environment_id,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
tracing::warn!(
|
||||
selected_root = selected_root.id,
|
||||
path = %path,
|
||||
"exec-server capability bundle omitted declared MCP config"
|
||||
);
|
||||
Vec::new()
|
||||
}),
|
||||
None => plugin_files
|
||||
.mcp_config
|
||||
.as_ref()
|
||||
.map(|file| {
|
||||
parse_mcp_servers(
|
||||
selected_root,
|
||||
&discovery.path,
|
||||
&file.contents,
|
||||
environment_id,
|
||||
)
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
};
|
||||
let connector_ids = manifest
|
||||
.paths
|
||||
.apps
|
||||
.as_ref()
|
||||
.and_then(|path| {
|
||||
plugin_files
|
||||
.apps_config
|
||||
.as_ref()
|
||||
.filter(|file| file.path == *path)
|
||||
.or_else(|| {
|
||||
tracing::warn!(
|
||||
selected_root = selected_root.id,
|
||||
path = %path,
|
||||
"exec-server capability bundle omitted declared connector config"
|
||||
);
|
||||
None
|
||||
})
|
||||
})
|
||||
.and_then(|file| match parse_plugin_app_config(&file.contents) {
|
||||
Ok(declarations) => Some(declarations),
|
||||
Err(error) => {
|
||||
tracing::warn!(
|
||||
selected_root = selected_root.id,
|
||||
path = %file.path,
|
||||
%error,
|
||||
"failed to parse exec-server-discovered connector config"
|
||||
);
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|declaration| declaration.connector_id.0)
|
||||
.collect();
|
||||
|
||||
Some(SelectedPluginMetadata {
|
||||
plugin_id: selected_root.id.clone(),
|
||||
plugin_display_name: manifest.display_name().to_string(),
|
||||
servers,
|
||||
connector_ids,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_mcp_servers(
|
||||
selected_root: &SelectedCapabilityRoot,
|
||||
plugin_root: &codex_utils_path_uri::PathUri,
|
||||
contents: &str,
|
||||
environment_id: &str,
|
||||
) -> Vec<(String, codex_config::McpServerConfig)> {
|
||||
let parsed = match parse_executor_plugin_mcp_config(plugin_root, contents, environment_id) {
|
||||
Ok(parsed) => parsed,
|
||||
Err(error) => {
|
||||
tracing::warn!(
|
||||
selected_root = selected_root.id,
|
||||
%error,
|
||||
"failed to parse exec-server-discovered MCP config"
|
||||
);
|
||||
return Vec::new();
|
||||
}
|
||||
};
|
||||
for error in parsed.errors {
|
||||
tracing::warn!(
|
||||
selected_root = selected_root.id,
|
||||
server = error.name,
|
||||
error = error.message,
|
||||
"ignoring invalid exec-server-discovered MCP server"
|
||||
);
|
||||
}
|
||||
parsed.servers.into_iter().collect()
|
||||
}
|
||||
Reference in New Issue
Block a user