Files
codex/codex-rs/exec-server-protocol/src/capabilities_tests.rs
T
Anthony Tafoya ab7439231c Add executor capability discovery V2 infrastructure (#47683)
## What changed

- Define `capabilities/discoverV2` request and inventory types and advertise `capabilityDiscoveryV2` in executor metadata.
- Prewarm installed plugin and global skill locations at server startup, with nonfatal scan failures.
- Add sandbox-scoped discovery caching with file watcher invalidation and request-time reloads when watching is unavailable.
- Batch metadata reads through the filesystem sandbox helper and bound discovery responses to 4 MiB and 2,048 capabilities.
- Share plugin identity and installed-version selection in `codex-core-plugin-common`, and fall back to `.app.json` when a plugin does not declare an apps configuration.

The V2 discovery manager is not yet wired into RPC request dispatch.

## Testing

Add coverage for inventory metadata, sandbox cache isolation, watcher invalidation, startup scan failures, response limits, and compatibility with older executor metadata.

GitOrigin-RevId: a223a5bc15fdf251023c0c71f468fd92c3b2d847
2026-09-23 22:20:34 +00:00

52 lines
1.7 KiB
Rust

//! V2 discovery requests and responses round-trip through JSON.
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn discovery_contract_round_trips_json() -> Result<(), Box<dyn std::error::Error>> {
let request = DiscoverV2CapabilitiesRequest {
cwd: PathUri::parse("file:///workspace")?,
sandbox: None,
};
let wire = serde_json::to_value(&request)?;
assert_eq!(
serde_json::from_value::<DiscoverV2CapabilitiesRequest>(wire)?,
request
);
let text_file = CapabilityTextFile {
path: PathUri::parse("file:///plugin/config.json")?,
contents: "{}".to_string(),
};
let skill = ExecutorSkill {
name: "example".to_string(),
namespace: Some("nested".to_string()),
description: "Example skill".to_string(),
short_description: None,
path: PathUri::parse("file:///plugin/skills/example/SKILL.md")?,
metadata: Some(text_file.clone()),
};
let response = DiscoverV2CapabilitiesResponse {
plugins: vec![ExecutorPlugin {
id: "example@company".to_string(),
remote_plugin_id: None,
version: "local".to_string(),
root: PathUri::parse("file:///plugin")?,
files: DiscoveredPluginFiles {
manifest: text_file.clone(),
mcp_config: Some(text_file.clone()),
apps_config: Some(text_file),
},
skills: vec![skill.clone()],
}],
skills: vec![skill],
warnings: Vec::new(),
};
let wire = serde_json::to_value(&response)?;
assert_eq!(
serde_json::from_value::<DiscoverV2CapabilitiesResponse>(wire)?,
response
);
Ok(())
}