Download codex-rs/core-plugins/src/provider_tests.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 13.4 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/core-plugins/src/provider_tests.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/core-plugins/src/provider_tests.rs
-
curl -L -o provider_tests.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/core-plugins/src/provider_tests.rs
13.4 kB
| use super::ExecutorPluginProvider; | |
| use super::ExecutorPluginProviderError; | |
| use super::resolve_plugin_root; | |
| use crate::manifest::parse_plugin_manifest_uri; | |
| use codex_exec_server::CopyOptions; | |
| use codex_exec_server::CreateDirectoryOptions; | |
| use codex_exec_server::EnvironmentManager; | |
| use codex_exec_server::ExecutorFileSystem; | |
| use codex_exec_server::ExecutorFileSystemFuture; | |
| use codex_exec_server::FileMetadata; | |
| use codex_exec_server::FileSystemReadStream; | |
| use codex_exec_server::FileSystemResult; | |
| use codex_exec_server::FileSystemSandboxContext; | |
| use codex_exec_server::GetMetadataOptions; | |
| use codex_exec_server::LOCAL_ENVIRONMENT_ID; | |
| use codex_exec_server::ReadDirectoryEntry; | |
| use codex_exec_server::ReadFileOptions; | |
| use codex_exec_server::RemoveOptions; | |
| use codex_exec_server::WalkOptions; | |
| use codex_exec_server::WalkOutcome; | |
| use codex_exec_server::WriteFileOptions; | |
| use codex_exec_server_test_support::environment_manager_without_environments; | |
| use codex_plugin::PluginProvider; | |
| use codex_plugin::ResolvedPlugin; | |
| use codex_protocol::capabilities::CapabilityRootLocation; | |
| use codex_protocol::capabilities::SelectedCapabilityRoot; | |
| use codex_utils_path_uri::PathUri; | |
| use pretty_assertions::assert_eq; | |
| use std::fs; | |
| use std::io; | |
| use std::path::Path; | |
| use std::sync::Arc; | |
| use std::sync::Mutex; | |
| use tempfile::tempdir; | |
| const MANIFEST_CONTENTS: &str = r#"{ | |
| "name": "demo-plugin", | |
| "version": " 1.2.3 ", | |
| "description": "Demo plugin", | |
| "skills": "./skills", | |
| "mcpServers": "./.mcp.json", | |
| "apps": "./.app.json", | |
| "interface": { | |
| "displayName": "Demo Plugin", | |
| "composerIcon": "./assets/icon.svg" | |
| } | |
| }"#; | |
| enum FileSystemCall { | |
| Metadata(PathUri), | |
| Read(PathUri), | |
| } | |
| struct SyntheticPluginFileSystem { | |
| plugin_root: PathUri, | |
| manifest_path: PathUri, | |
| calls: Mutex<Vec<FileSystemCall>>, | |
| } | |
| impl SyntheticPluginFileSystem { | |
| fn unsupported<T>() -> FileSystemResult<T> { | |
| Err(io::Error::new( | |
| io::ErrorKind::Unsupported, | |
| "operation is not used by plugin resolution", | |
| )) | |
| } | |
| } | |
| impl ExecutorFileSystem for SyntheticPluginFileSystem { | |
| fn canonicalize<'a>( | |
| &'a self, | |
| _path: &'a PathUri, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, PathUri> { | |
| Box::pin(async { Self::unsupported() }) | |
| } | |
| fn read_file<'a>( | |
| &'a self, | |
| path: &'a PathUri, | |
| _options: ReadFileOptions, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, Vec<u8>> { | |
| Box::pin(async move { | |
| self.calls | |
| .lock() | |
| .unwrap_or_else(std::sync::PoisonError::into_inner) | |
| .push(FileSystemCall::Read(path.clone())); | |
| if path == &self.manifest_path { | |
| Ok(MANIFEST_CONTENTS.as_bytes().to_vec()) | |
| } else { | |
| Err(io::Error::new(io::ErrorKind::NotFound, "not found")) | |
| } | |
| }) | |
| } | |
| fn read_file_stream<'a>( | |
| &'a self, | |
| _path: &'a PathUri, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, FileSystemReadStream> { | |
| Box::pin(async { Self::unsupported() }) | |
| } | |
| fn write_file<'a>( | |
| &'a self, | |
| _path: &'a PathUri, | |
| _contents: Vec<u8>, | |
| _options: WriteFileOptions, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, ()> { | |
| Box::pin(async { Self::unsupported() }) | |
| } | |
| fn create_directory<'a>( | |
| &'a self, | |
| _path: &'a PathUri, | |
| _options: CreateDirectoryOptions, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, ()> { | |
| Box::pin(async { Self::unsupported() }) | |
| } | |
| fn get_metadata<'a>( | |
| &'a self, | |
| path: &'a PathUri, | |
| _options: GetMetadataOptions, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, FileMetadata> { | |
| Box::pin(async move { | |
| self.calls | |
| .lock() | |
| .unwrap_or_else(std::sync::PoisonError::into_inner) | |
| .push(FileSystemCall::Metadata(path.clone())); | |
| let (is_directory, is_file) = if path == &self.plugin_root { | |
| (true, false) | |
| } else if path == &self.manifest_path { | |
| (false, true) | |
| } else { | |
| return Err(io::Error::new(io::ErrorKind::NotFound, "not found")); | |
| }; | |
| Ok(FileMetadata { | |
| is_directory, | |
| is_file, | |
| is_symlink: false, | |
| size: 0, | |
| created_at_ms: 0, | |
| modified_at_ms: 0, | |
| }) | |
| }) | |
| } | |
| fn read_directory<'a>( | |
| &'a self, | |
| _path: &'a PathUri, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, Vec<ReadDirectoryEntry>> { | |
| Box::pin(async { Self::unsupported() }) | |
| } | |
| fn walk<'a>( | |
| &'a self, | |
| _path: &'a PathUri, | |
| _options: WalkOptions, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, WalkOutcome> { | |
| Box::pin(async { Self::unsupported() }) | |
| } | |
| fn remove<'a>( | |
| &'a self, | |
| _path: &'a PathUri, | |
| _options: RemoveOptions, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, ()> { | |
| Box::pin(async { Self::unsupported() }) | |
| } | |
| fn copy<'a>( | |
| &'a self, | |
| _source_path: &'a PathUri, | |
| _destination_path: &'a PathUri, | |
| _options: CopyOptions, | |
| _sandbox: Option<&'a FileSystemSandboxContext>, | |
| ) -> ExecutorFileSystemFuture<'a, ()> { | |
| Box::pin(async { Self::unsupported() }) | |
| } | |
| } | |
| fn write_manifest(plugin_root: &Path, relative_path: &str, contents: &str) { | |
| let manifest_path = plugin_root.join(relative_path); | |
| fs::create_dir_all(manifest_path.parent().expect("manifest parent")) | |
| .expect("create manifest parent"); | |
| fs::write(manifest_path, contents).expect("write manifest"); | |
| } | |
| fn selected_root(id: &str, environment_id: &str, path: &Path) -> SelectedCapabilityRoot { | |
| SelectedCapabilityRoot { | |
| id: id.to_string(), | |
| location: CapabilityRootLocation::Environment { | |
| environment_id: environment_id.to_string(), | |
| path: PathUri::from_host_native_path(path).expect("path URI"), | |
| }, | |
| } | |
| } | |
| fn selected_root_uri(id: &str, environment_id: &str, path: PathUri) -> SelectedCapabilityRoot { | |
| SelectedCapabilityRoot { | |
| id: id.to_string(), | |
| location: CapabilityRootLocation::Environment { | |
| environment_id: environment_id.to_string(), | |
| path, | |
| }, | |
| } | |
| } | |
| async fn plugin_root_resolution_uses_supplied_executor_file_system() { | |
| let temp_dir = tempdir().expect("tempdir"); | |
| let plugin_root = temp_dir.path().join("executor-only-plugin"); | |
| assert!(!plugin_root.exists()); | |
| let plugin_root = PathUri::from_host_native_path(&plugin_root).expect("plugin root URI"); | |
| let manifest_path = plugin_root | |
| .join(".codex-plugin/plugin.json") | |
| .expect("manifest URI"); | |
| let parsed_manifest = | |
| parse_plugin_manifest_uri(&plugin_root, &manifest_path, MANIFEST_CONTENTS) | |
| .expect("parse manifest"); | |
| let file_system = SyntheticPluginFileSystem { | |
| plugin_root: plugin_root.clone(), | |
| manifest_path: manifest_path.clone(), | |
| calls: Mutex::new(Vec::new()), | |
| }; | |
| let resolved = resolve_plugin_root( | |
| &selected_root_uri("selected-demo", "executor-test", plugin_root.clone()), | |
| plugin_root.clone(), | |
| &file_system, | |
| ) | |
| .await | |
| .expect("resolve executor plugin"); | |
| assert_eq!( | |
| resolved, | |
| Some( | |
| ResolvedPlugin::from_environment( | |
| "selected-demo".to_string(), | |
| "executor-test".to_string(), | |
| plugin_root.clone(), | |
| manifest_path.clone(), | |
| parsed_manifest, | |
| ) | |
| .expect("valid expected descriptor") | |
| ) | |
| ); | |
| assert_eq!( | |
| *file_system | |
| .calls | |
| .lock() | |
| .unwrap_or_else(std::sync::PoisonError::into_inner), | |
| vec![ | |
| FileSystemCall::Metadata(plugin_root), | |
| FileSystemCall::Metadata(manifest_path.clone()), | |
| FileSystemCall::Read(manifest_path), | |
| ] | |
| ); | |
| } | |
| async fn plugin_root_resolution_accepts_foreign_executor_file_uri() { | |
| let plugin_root = PathUri::parse("file:///C:/plugins/foo").expect("Windows plugin root URI"); | |
| let manifest_path = plugin_root | |
| .join(".codex-plugin/plugin.json") | |
| .expect("manifest URI"); | |
| let parsed_manifest = | |
| parse_plugin_manifest_uri(&plugin_root, &manifest_path, MANIFEST_CONTENTS) | |
| .expect("parse manifest"); | |
| let file_system = SyntheticPluginFileSystem { | |
| plugin_root: plugin_root.clone(), | |
| manifest_path: manifest_path.clone(), | |
| calls: Mutex::new(Vec::new()), | |
| }; | |
| let selected_root = selected_root_uri("selected-demo", "executor-test", plugin_root.clone()); | |
| let resolved = resolve_plugin_root(&selected_root, plugin_root.clone(), &file_system) | |
| .await | |
| .expect("resolve executor plugin"); | |
| assert_eq!( | |
| resolved, | |
| Some( | |
| ResolvedPlugin::from_environment( | |
| "selected-demo".to_string(), | |
| "executor-test".to_string(), | |
| plugin_root.clone(), | |
| manifest_path.clone(), | |
| parsed_manifest, | |
| ) | |
| .expect("valid expected descriptor") | |
| ) | |
| ); | |
| assert_eq!( | |
| *file_system | |
| .calls | |
| .lock() | |
| .unwrap_or_else(std::sync::PoisonError::into_inner), | |
| vec![ | |
| FileSystemCall::Metadata(plugin_root), | |
| FileSystemCall::Metadata(manifest_path.clone()), | |
| FileSystemCall::Read(manifest_path), | |
| ] | |
| ); | |
| } | |
| async fn standalone_capability_root_is_not_a_plugin() { | |
| let temp_dir = tempdir().expect("tempdir"); | |
| let standalone_root = temp_dir.path().join("standalone-skill"); | |
| fs::create_dir_all(&standalone_root).expect("create standalone root"); | |
| let provider = ExecutorPluginProvider::new(Arc::new(EnvironmentManager::default_for_tests())); | |
| let resolved = provider | |
| .resolve(&selected_root( | |
| "standalone", | |
| LOCAL_ENVIRONMENT_ID, | |
| &standalone_root, | |
| )) | |
| .await | |
| .expect("resolve standalone root"); | |
| assert_eq!(resolved, None); | |
| } | |
| async fn root_agent_plugin_manifest_is_not_an_executor_plugin() { | |
| let temp_dir = tempdir().expect("tempdir"); | |
| let plugin_root = temp_dir.path().join("agent-plugin"); | |
| write_manifest( | |
| &plugin_root, | |
| "plugin.json", | |
| r#"{ | |
| "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", | |
| "name": "agent-plugin", | |
| "version": "1.0.0" | |
| }"#, | |
| ); | |
| let provider = ExecutorPluginProvider::new(Arc::new(EnvironmentManager::default_for_tests())); | |
| let resolved = provider | |
| .resolve(&selected_root( | |
| "agent-plugin", | |
| LOCAL_ENVIRONMENT_ID, | |
| &plugin_root, | |
| )) | |
| .await | |
| .expect("resolve selected root"); | |
| assert_eq!(resolved, None); | |
| } | |
| async fn unavailable_environment_does_not_fall_back_to_host_filesystem() { | |
| let temp_dir = tempdir().expect("tempdir"); | |
| let plugin_root = temp_dir.path().join("host-plugin"); | |
| write_manifest(&plugin_root, ".codex-plugin/plugin.json", MANIFEST_CONTENTS); | |
| let provider = | |
| ExecutorPluginProvider::new(Arc::new(environment_manager_without_environments())); | |
| let err = provider | |
| .resolve(&selected_root("host-plugin", "missing", &plugin_root)) | |
| .await | |
| .expect_err("missing environment should fail"); | |
| assert_eq!( | |
| err.to_string(), | |
| "selected capability root `host-plugin` references unavailable environment `missing`" | |
| ); | |
| } | |
| async fn malformed_preferred_manifest_does_not_fall_through_to_alternate() { | |
| let temp_dir = tempdir().expect("tempdir"); | |
| let plugin_root = temp_dir.path().join("demo-plugin"); | |
| write_manifest(&plugin_root, ".codex-plugin/plugin.json", "{not-json"); | |
| write_manifest( | |
| &plugin_root, | |
| ".claude-plugin/plugin.json", | |
| MANIFEST_CONTENTS, | |
| ); | |
| let expected_path = | |
| PathUri::from_host_native_path(plugin_root.join(".codex-plugin/plugin.json")) | |
| .expect("manifest URI"); | |
| let provider = ExecutorPluginProvider::new(Arc::new(EnvironmentManager::default_for_tests())); | |
| let err = provider | |
| .resolve(&selected_root( | |
| "selected-demo", | |
| LOCAL_ENVIRONMENT_ID, | |
| &plugin_root, | |
| )) | |
| .await | |
| .expect_err("malformed preferred manifest should fail"); | |
| let ExecutorPluginProviderError::ParseManifest { | |
| root_id, | |
| path, | |
| source: _, | |
| } = err | |
| else { | |
| panic!("expected parse error"); | |
| }; | |
| assert_eq!( | |
| (root_id, path), | |
| ("selected-demo".to_string(), expected_path) | |
| ); | |
| } | |