Download codex-rs/exec-server/src/fs_helper.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 16.8 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/exec-server/src/fs_helper.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/exec-server/src/fs_helper.rs
-
curl -L -o fs_helper.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/exec-server/src/fs_helper.rs
16.8 kB
| use base64::Engine as _; | |
| use base64::engine::general_purpose::STANDARD; | |
| use codex_exec_server_protocol::JSONRPCErrorError; | |
| use serde::Deserialize; | |
| use serde::Serialize; | |
| use tokio::io; | |
| use crate::CapabilityRootsDiscoverParams; | |
| use crate::CapabilityRootsDiscoverResponse; | |
| use crate::CopyOptions; | |
| use crate::CreateDirectoryOptions; | |
| use crate::ExecutorFileSystem; | |
| use crate::GetMetadataOptions; | |
| use crate::ReadFileOptions; | |
| use crate::RemoveOptions; | |
| use crate::WriteFileOptions; | |
| use crate::local_file_system::DirectFileSystem; | |
| use crate::protocol::CAPABILITY_ROOTS_DISCOVER_METHOD; | |
| use crate::protocol::FS_CANONICALIZE_METHOD; | |
| use crate::protocol::FS_COPY_METHOD; | |
| use crate::protocol::FS_CREATE_DIRECTORY_METHOD; | |
| use crate::protocol::FS_GET_METADATA_METHOD; | |
| use crate::protocol::FS_OPEN_METHOD; | |
| use crate::protocol::FS_READ_DIRECTORY_METHOD; | |
| use crate::protocol::FS_READ_FILE_METHOD; | |
| use crate::protocol::FS_REMOVE_METHOD; | |
| use crate::protocol::FS_WALK_METHOD; | |
| use crate::protocol::FS_WRITE_FILE_METHOD; | |
| use crate::protocol::FsCanonicalizeParams; | |
| use crate::protocol::FsCanonicalizeResponse; | |
| use crate::protocol::FsCopyParams; | |
| use crate::protocol::FsCopyResponse; | |
| use crate::protocol::FsCreateDirectoryParams; | |
| use crate::protocol::FsCreateDirectoryResponse; | |
| use crate::protocol::FsGetMetadataParams; | |
| use crate::protocol::FsGetMetadataResponse; | |
| use crate::protocol::FsReadDirectoryEntry; | |
| use crate::protocol::FsReadDirectoryParams; | |
| use crate::protocol::FsReadDirectoryResponse; | |
| use crate::protocol::FsReadFileParams; | |
| use crate::protocol::FsReadFileResponse; | |
| use crate::protocol::FsRemoveParams; | |
| use crate::protocol::FsRemoveResponse; | |
| use crate::protocol::FsWalkParams; | |
| use crate::protocol::FsWalkResponse; | |
| use crate::protocol::FsWriteFileParams; | |
| use crate::protocol::FsWriteFileResponse; | |
| use crate::rpc::internal_error; | |
| use crate::rpc::invalid_request; | |
| use crate::rpc::not_found; | |
| pub const CODEX_FS_HELPER_ARG1: &str = "--codex-run-as-fs-helper"; | |
| pub(crate) enum FsHelperRequest { | |
| DiscoverCapabilityRoots(CapabilityRootsDiscoverParams), | |
| Open(FsReadFileParams), | |
| ReadFile(FsReadFileParams), | |
| WriteFile(FsWriteFileParams), | |
| CreateDirectory(FsCreateDirectoryParams), | |
| GetMetadata(FsGetMetadataParams), | |
| Canonicalize(FsCanonicalizeParams), | |
| ReadDirectory(FsReadDirectoryParams), | |
| Walk(FsWalkParams), | |
| Remove(FsRemoveParams), | |
| Copy(FsCopyParams), | |
| } | |
| pub(crate) enum FsHelperResponse { | |
| Ok(FsHelperPayload), | |
| Error(JSONRPCErrorError), | |
| } | |
| pub(crate) struct FsHelperOpenResponse { | |
| // Windows duplicates the handle from the helper process. | |
| pub(crate) process_id: u32, | |
| // Unix passes the fd directly instead. | |
| pub(crate) file_handle: u64, | |
| } | |
| pub(crate) enum FsHelperPayload { | |
| DiscoverCapabilityRoots(CapabilityRootsDiscoverResponse), | |
| Open(FsHelperOpenResponse), | |
| ReadFile(FsReadFileResponse), | |
| WriteFile(FsWriteFileResponse), | |
| CreateDirectory(FsCreateDirectoryResponse), | |
| GetMetadata(FsGetMetadataResponse), | |
| Canonicalize(FsCanonicalizeResponse), | |
| ReadDirectory(FsReadDirectoryResponse), | |
| Walk(FsWalkResponse), | |
| Remove(FsRemoveResponse), | |
| Copy(FsCopyResponse), | |
| } | |
| impl FsHelperPayload { | |
| fn operation(&self) -> &'static str { | |
| match self { | |
| Self::DiscoverCapabilityRoots(_) => CAPABILITY_ROOTS_DISCOVER_METHOD, | |
| Self::Open(_) => FS_OPEN_METHOD, | |
| Self::ReadFile(_) => FS_READ_FILE_METHOD, | |
| Self::WriteFile(_) => FS_WRITE_FILE_METHOD, | |
| Self::CreateDirectory(_) => FS_CREATE_DIRECTORY_METHOD, | |
| Self::GetMetadata(_) => FS_GET_METADATA_METHOD, | |
| Self::Canonicalize(_) => FS_CANONICALIZE_METHOD, | |
| Self::ReadDirectory(_) => FS_READ_DIRECTORY_METHOD, | |
| Self::Walk(_) => FS_WALK_METHOD, | |
| Self::Remove(_) => FS_REMOVE_METHOD, | |
| Self::Copy(_) => FS_COPY_METHOD, | |
| } | |
| } | |
| pub(crate) fn expect_capability_roots_discover( | |
| self, | |
| ) -> Result<CapabilityRootsDiscoverResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::DiscoverCapabilityRoots(response) => Ok(response), | |
| other => Err(unexpected_response( | |
| CAPABILITY_ROOTS_DISCOVER_METHOD, | |
| other.operation(), | |
| )), | |
| } | |
| } | |
| pub(crate) fn expect_read_file(self) -> Result<FsReadFileResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::ReadFile(response) => Ok(response), | |
| other => Err(unexpected_response(FS_READ_FILE_METHOD, other.operation())), | |
| } | |
| } | |
| pub(crate) fn expect_write_file(self) -> Result<FsWriteFileResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::WriteFile(response) => Ok(response), | |
| other => Err(unexpected_response(FS_WRITE_FILE_METHOD, other.operation())), | |
| } | |
| } | |
| pub(crate) fn expect_create_directory( | |
| self, | |
| ) -> Result<FsCreateDirectoryResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::CreateDirectory(response) => Ok(response), | |
| other => Err(unexpected_response( | |
| FS_CREATE_DIRECTORY_METHOD, | |
| other.operation(), | |
| )), | |
| } | |
| } | |
| pub(crate) fn expect_get_metadata(self) -> Result<FsGetMetadataResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::GetMetadata(response) => Ok(response), | |
| other => Err(unexpected_response( | |
| FS_GET_METADATA_METHOD, | |
| other.operation(), | |
| )), | |
| } | |
| } | |
| pub(crate) fn expect_canonicalize(self) -> Result<FsCanonicalizeResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::Canonicalize(response) => Ok(response), | |
| other => Err(unexpected_response( | |
| FS_CANONICALIZE_METHOD, | |
| other.operation(), | |
| )), | |
| } | |
| } | |
| pub(crate) fn expect_read_directory( | |
| self, | |
| ) -> Result<FsReadDirectoryResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::ReadDirectory(response) => Ok(response), | |
| other => Err(unexpected_response( | |
| FS_READ_DIRECTORY_METHOD, | |
| other.operation(), | |
| )), | |
| } | |
| } | |
| pub(crate) fn expect_walk(self) -> Result<FsWalkResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::Walk(response) => Ok(response), | |
| other => Err(unexpected_response(FS_WALK_METHOD, other.operation())), | |
| } | |
| } | |
| pub(crate) fn expect_remove(self) -> Result<FsRemoveResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::Remove(response) => Ok(response), | |
| other => Err(unexpected_response(FS_REMOVE_METHOD, other.operation())), | |
| } | |
| } | |
| pub(crate) fn expect_copy(self) -> Result<FsCopyResponse, JSONRPCErrorError> { | |
| match self { | |
| Self::Copy(response) => Ok(response), | |
| other => Err(unexpected_response(FS_COPY_METHOD, other.operation())), | |
| } | |
| } | |
| } | |
| fn unexpected_response(expected: &str, actual: &str) -> JSONRPCErrorError { | |
| internal_error(format!( | |
| "unexpected fs sandbox helper response: expected {expected}, got {actual}" | |
| )) | |
| } | |
| pub(crate) async fn run_direct_request( | |
| request: FsHelperRequest, | |
| ) -> Result<FsHelperPayload, JSONRPCErrorError> { | |
| let file_system = DirectFileSystem; | |
| match request { | |
| FsHelperRequest::DiscoverCapabilityRoots(params) => { | |
| let response = crate::discover_capability_roots(&file_system, params) | |
| .await | |
| .map_err(|error| invalid_request(error.to_string()))?; | |
| Ok(FsHelperPayload::DiscoverCapabilityRoots(response)) | |
| } | |
| FsHelperRequest::Open(_) => Err(invalid_request( | |
| "opening a file requires descriptor handoff".to_string(), | |
| )), | |
| FsHelperRequest::ReadFile(params) => { | |
| let data = file_system | |
| .read_file( | |
| ¶ms.path, | |
| ReadFileOptions { | |
| follow_symlinks: params.follow_symlinks.unwrap_or(true), | |
| }, | |
| /*sandbox*/ None, | |
| ) | |
| .await | |
| .map_err(map_fs_error)?; | |
| Ok(FsHelperPayload::ReadFile(FsReadFileResponse { | |
| data_base64: STANDARD.encode(data), | |
| })) | |
| } | |
| FsHelperRequest::WriteFile(params) => { | |
| let bytes = STANDARD.decode(params.data_base64).map_err(|err| { | |
| invalid_request(format!( | |
| "{FS_WRITE_FILE_METHOD} requires valid base64 dataBase64: {err}" | |
| )) | |
| })?; | |
| file_system | |
| .write_file( | |
| ¶ms.path, | |
| bytes, | |
| WriteFileOptions { | |
| follow_symlinks: params.follow_symlinks.unwrap_or(true), | |
| }, | |
| /*sandbox*/ None, | |
| ) | |
| .await | |
| .map_err(map_fs_error)?; | |
| Ok(FsHelperPayload::WriteFile(FsWriteFileResponse {})) | |
| } | |
| FsHelperRequest::CreateDirectory(params) => { | |
| file_system | |
| .create_directory( | |
| ¶ms.path, | |
| CreateDirectoryOptions { | |
| recursive: params.recursive.unwrap_or(true), | |
| follow_symlinks: params.follow_symlinks.unwrap_or(true), | |
| }, | |
| /*sandbox*/ None, | |
| ) | |
| .await | |
| .map_err(map_fs_error)?; | |
| Ok(FsHelperPayload::CreateDirectory( | |
| FsCreateDirectoryResponse {}, | |
| )) | |
| } | |
| FsHelperRequest::GetMetadata(params) => { | |
| let metadata = file_system | |
| .get_metadata( | |
| ¶ms.path, | |
| GetMetadataOptions { | |
| follow_symlinks: params.follow_symlinks.unwrap_or(true), | |
| }, | |
| /*sandbox*/ None, | |
| ) | |
| .await | |
| .map_err(map_fs_error)?; | |
| Ok(FsHelperPayload::GetMetadata(FsGetMetadataResponse { | |
| is_directory: metadata.is_directory, | |
| is_file: metadata.is_file, | |
| is_symlink: metadata.is_symlink, | |
| size: metadata.size, | |
| created_at_ms: metadata.created_at_ms, | |
| modified_at_ms: metadata.modified_at_ms, | |
| })) | |
| } | |
| FsHelperRequest::Canonicalize(params) => { | |
| let path = file_system | |
| .canonicalize(¶ms.path, /*sandbox*/ None) | |
| .await | |
| .map_err(map_fs_error)?; | |
| Ok(FsHelperPayload::Canonicalize(FsCanonicalizeResponse { | |
| path, | |
| })) | |
| } | |
| FsHelperRequest::ReadDirectory(params) => { | |
| let entries = file_system | |
| .read_directory(¶ms.path, /*sandbox*/ None) | |
| .await | |
| .map_err(map_fs_error)? | |
| .into_iter() | |
| .map(|entry| FsReadDirectoryEntry { | |
| file_name: entry.file_name, | |
| is_directory: entry.is_directory, | |
| is_file: entry.is_file, | |
| }) | |
| .collect(); | |
| Ok(FsHelperPayload::ReadDirectory(FsReadDirectoryResponse { | |
| entries, | |
| })) | |
| } | |
| FsHelperRequest::Walk(params) => { | |
| let outcome = file_system | |
| .walk(¶ms.path, params.options, /*sandbox*/ None) | |
| .await | |
| .map_err(map_fs_error)?; | |
| Ok(FsHelperPayload::Walk(outcome)) | |
| } | |
| FsHelperRequest::Remove(params) => { | |
| file_system | |
| .remove( | |
| ¶ms.path, | |
| RemoveOptions { | |
| recursive: params.recursive.unwrap_or(true), | |
| force: params.force.unwrap_or(true), | |
| follow_symlinks: params.follow_symlinks.unwrap_or(true), | |
| }, | |
| /*sandbox*/ None, | |
| ) | |
| .await | |
| .map_err(map_fs_error)?; | |
| Ok(FsHelperPayload::Remove(FsRemoveResponse {})) | |
| } | |
| FsHelperRequest::Copy(params) => { | |
| file_system | |
| .copy( | |
| ¶ms.source_path, | |
| ¶ms.destination_path, | |
| CopyOptions { | |
| recursive: params.recursive, | |
| }, | |
| /*sandbox*/ None, | |
| ) | |
| .await | |
| .map_err(map_fs_error)?; | |
| Ok(FsHelperPayload::Copy(FsCopyResponse {})) | |
| } | |
| } | |
| } | |
| pub(crate) fn map_fs_error(err: io::Error) -> JSONRPCErrorError { | |
| match err.kind() { | |
| io::ErrorKind::NotFound => not_found(err.to_string()), | |
| io::ErrorKind::InvalidInput | io::ErrorKind::PermissionDenied => { | |
| invalid_request(err.to_string()) | |
| } | |
| _ => internal_error(err.to_string()), | |
| } | |
| } | |
| mod tests { | |
| use codex_utils_path_uri::PathUri; | |
| use pretty_assertions::assert_eq; | |
| use serde_json::json; | |
| use super::*; | |
| fn helper_protocol_uses_path_uris() -> serde_json::Result<()> { | |
| let local_path = | |
| PathUri::from_host_native_path(std::env::current_dir().expect("cwd").join("file")) | |
| .expect("path URI"); | |
| let paths = [ | |
| local_path, | |
| PathUri::parse("file://server/share/file").expect("path URI"), | |
| ]; | |
| for path in paths { | |
| let expected_path = path.to_string(); | |
| let request = serde_json::to_value(FsHelperRequest::WriteFile(FsWriteFileParams { | |
| path: path.clone(), | |
| data_base64: String::new(), | |
| follow_symlinks: None, | |
| sandbox: None, | |
| }))?; | |
| assert_eq!( | |
| request, | |
| json!({ | |
| "operation": FS_WRITE_FILE_METHOD, | |
| "params": { | |
| "path": expected_path.as_str(), | |
| "dataBase64": "", | |
| "sandbox": null, | |
| }, | |
| }), | |
| ); | |
| let request_path = request["params"]["path"] | |
| .as_str() | |
| .expect("request path should be a string"); | |
| assert_eq!(request_path, expected_path); | |
| assert!(request_path.starts_with("file:")); | |
| let response = serde_json::to_value(FsHelperResponse::Ok( | |
| FsHelperPayload::Canonicalize(FsCanonicalizeResponse { path }), | |
| ))?; | |
| assert_eq!( | |
| response, | |
| json!({ | |
| "status": "ok", | |
| "payload": { | |
| "operation": FS_CANONICALIZE_METHOD, | |
| "response": { | |
| "path": expected_path.as_str(), | |
| }, | |
| }, | |
| }), | |
| ); | |
| let response_path = response["payload"]["response"]["path"] | |
| .as_str() | |
| .expect("canonicalize response path should be a string"); | |
| assert_eq!(response_path, expected_path); | |
| assert!(response_path.starts_with("file:")); | |
| } | |
| Ok(()) | |
| } | |
| } | |