From a4358f2c4feb37c3aeed45883a8307fe1e495e3d Mon Sep 17 00:00:00 2001 From: starr-openai Date: Thu, 19 Mar 2026 18:41:58 +0000 Subject: [PATCH] Use Environment as the exec and fs gateway Co-authored-by: Codex --- codex-rs/app-server/src/fs_api.rs | 2 +- codex-rs/core/src/codex.rs | 15 +- codex-rs/core/src/config/mod.rs | 20 --- codex-rs/core/src/config/profile.rs | 2 - .../core/src/tools/handlers/view_image.rs | 1 - codex-rs/core/src/unified_exec/backend.rs | 67 ++------- codex-rs/core/src/unified_exec/mod.rs | 2 +- codex-rs/core/src/unified_exec/mod_tests.rs | 57 ++------ codex-rs/exec-server/src/environment.rs | 83 +++++++++-- codex-rs/exec-server/src/fs.rs | 135 ++++++++++++++++++ codex-rs/exec-server/src/lib.rs | 16 +-- codex-rs/exec-server/src/server/filesystem.rs | 2 +- 12 files changed, 239 insertions(+), 163 deletions(-) diff --git a/codex-rs/app-server/src/fs_api.rs b/codex-rs/app-server/src/fs_api.rs index 9baa2b1dce..1f8a32362f 100644 --- a/codex-rs/app-server/src/fs_api.rs +++ b/codex-rs/app-server/src/fs_api.rs @@ -34,7 +34,7 @@ pub(crate) struct FsApi { impl Default for FsApi { fn default() -> Self { Self { - file_system: Arc::new(Environment::default().get_filesystem()), + file_system: Environment::default().get_filesystem(), } } } diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index ea1b8a807b..01bc599b9e 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -314,7 +314,7 @@ use crate::turn_timing::TurnTimingState; use crate::turn_timing::record_turn_ttfm_metric; use crate::turn_timing::record_turn_ttft_metric; use crate::unified_exec::UnifiedExecProcessManager; -use crate::unified_exec::unified_exec_session_factory_for_config; +use crate::unified_exec::unified_exec_session_factory_for_environment; use crate::util::backoff; use crate::windows_sandbox::WindowsSandboxLevelExt; use codex_async_utils::OrCancelExt; @@ -1774,11 +1774,10 @@ impl Session { }); } - let unified_exec_session_factory = unified_exec_session_factory_for_config( - config.as_ref(), - None, - ) - .await?; + let environment = + Arc::new(Environment::create(config.experimental_exec_server_url.clone()).await?); + let unified_exec_session_factory = + unified_exec_session_factory_for_environment(environment.as_ref()); let services = SessionServices { // Initialize the MCP connection manager with an uninitialized @@ -1834,9 +1833,7 @@ impl Session { code_mode_service: crate::tools::code_mode::CodeModeService::new( config.js_repl_node_path.clone(), ), - environment: Arc::new( - Environment::create(config.experimental_exec_server_url.clone()).await?, - ), + environment, }; let js_repl = Arc::new(JsReplHandle::with_node_path( config.js_repl_node_path.clone(), diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index f489fdb211..8d0d323307 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -543,14 +543,6 @@ pub struct Config { /// If set to `true`, used only the experimental unified exec tool. pub use_experimental_unified_exec_tool: bool, - /// When `true`, route unified-exec process launches through `codex-exec-server` - /// instead of spawning them directly in-process. - pub experimental_unified_exec_use_exec_server: bool, - - /// When `true`, start a session-scoped local `codex-exec-server` subprocess - /// during session startup and route unified-exec calls through it. - pub experimental_unified_exec_spawn_local_exec_server: bool, - /// Maximum poll window for background terminal output (`write_stdin`), in milliseconds. /// Default: `300000` (5 minutes). pub background_terminal_max_timeout: u64, @@ -1521,8 +1513,6 @@ pub struct ConfigToml { pub experimental_instructions_file: Option, pub experimental_compact_prompt_file: Option, pub experimental_use_unified_exec_tool: Option, - pub experimental_unified_exec_use_exec_server: Option, - pub experimental_unified_exec_spawn_local_exec_server: Option, pub experimental_use_freeform_apply_patch: Option, /// Preferred OSS provider for local models, e.g. "lmstudio" or "ollama". pub oss_provider: Option, @@ -2492,14 +2482,6 @@ impl Config { let include_apply_patch_tool_flag = features.enabled(Feature::ApplyPatchFreeform); let use_experimental_unified_exec_tool = features.enabled(Feature::UnifiedExec); - let experimental_unified_exec_use_exec_server = config_profile - .experimental_unified_exec_use_exec_server - .or(cfg.experimental_unified_exec_use_exec_server) - .unwrap_or(false); - let experimental_unified_exec_spawn_local_exec_server = config_profile - .experimental_unified_exec_spawn_local_exec_server - .or(cfg.experimental_unified_exec_spawn_local_exec_server) - .unwrap_or(false); let forced_chatgpt_workspace_id = cfg.forced_chatgpt_workspace_id.as_ref().and_then(|value| { @@ -2795,8 +2777,6 @@ impl Config { web_search_mode: constrained_web_search_mode.value, web_search_config, use_experimental_unified_exec_tool, - experimental_unified_exec_use_exec_server, - experimental_unified_exec_spawn_local_exec_server, background_terminal_max_timeout, ghost_snapshot, features, diff --git a/codex-rs/core/src/config/profile.rs b/codex-rs/core/src/config/profile.rs index fc986779ae..743830ab32 100644 --- a/codex-rs/core/src/config/profile.rs +++ b/codex-rs/core/src/config/profile.rs @@ -49,8 +49,6 @@ pub struct ConfigProfile { pub experimental_compact_prompt_file: Option, pub include_apply_patch_tool: Option, pub experimental_use_unified_exec_tool: Option, - pub experimental_unified_exec_use_exec_server: Option, - pub experimental_unified_exec_spawn_local_exec_server: Option, pub experimental_use_freeform_apply_patch: Option, pub tools_view_image: Option, pub tools: Option, diff --git a/codex-rs/core/src/tools/handlers/view_image.rs b/codex-rs/core/src/tools/handlers/view_image.rs index 9cbe9bbc76..f4015a7624 100644 --- a/codex-rs/core/src/tools/handlers/view_image.rs +++ b/codex-rs/core/src/tools/handlers/view_image.rs @@ -1,5 +1,4 @@ use async_trait::async_trait; -use codex_exec_server::ExecutorFileSystem; use codex_protocol::models::FunctionCallOutputBody; use codex_protocol::models::FunctionCallOutputContentItem; use codex_protocol::models::FunctionCallOutputPayload; diff --git a/codex-rs/core/src/unified_exec/backend.rs b/codex-rs/core/src/unified_exec/backend.rs index 6892d887cd..ec6fa15641 100644 --- a/codex-rs/core/src/unified_exec/backend.rs +++ b/codex-rs/core/src/unified_exec/backend.rs @@ -1,15 +1,10 @@ -use std::path::PathBuf; use std::sync::Arc; use async_trait::async_trait; +use codex_exec_server::Environment; use codex_exec_server::ExecServerClient; -use codex_exec_server::ExecServerClientConnectOptions; -use codex_exec_server::ExecServerLaunchCommand; -use codex_exec_server::SpawnedExecServer; -use codex_exec_server::spawn_local_exec_server; use tracing::debug; -use crate::config::Config; use crate::exec::SandboxType; use crate::sandboxing::ExecRequest; use crate::unified_exec::SpawnLifecycleHandle; @@ -51,32 +46,18 @@ impl UnifiedExecSessionFactory for LocalUnifiedExecSessionFactory { pub(crate) struct ExecServerUnifiedExecSessionFactory { client: ExecServerClient, - _spawned_server: Option>, } impl std::fmt::Debug for ExecServerUnifiedExecSessionFactory { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("ExecServerUnifiedExecSessionFactory") - .field("owns_spawned_server", &self._spawned_server.is_some()) .finish_non_exhaustive() } } impl ExecServerUnifiedExecSessionFactory { pub(crate) fn from_client(client: ExecServerClient) -> UnifiedExecSessionFactoryHandle { - Arc::new(Self { - client, - _spawned_server: None, - }) - } - - pub(crate) fn from_spawned_server( - spawned_server: Arc, - ) -> UnifiedExecSessionFactoryHandle { - Arc::new(Self { - client: spawned_server.client().clone(), - _spawned_server: Some(spawned_server), - }) + Arc::new(Self { client }) } } @@ -118,45 +99,13 @@ impl UnifiedExecSessionFactory for ExecServerUnifiedExecSessionFactory { } } -pub(crate) async fn unified_exec_session_factory_for_config( - config: &Config, - local_exec_server_command: Option, -) -> Result { - if !config.experimental_unified_exec_use_exec_server { - return Ok(local_unified_exec_session_factory()); - } - - if config.experimental_unified_exec_spawn_local_exec_server { - let command = local_exec_server_command.unwrap_or_else(default_local_exec_server_command); - let spawned_server = - spawn_local_exec_server(command, ExecServerClientConnectOptions::default()) - .await - .map_err(|err| UnifiedExecError::create_process(err.to_string()))?; - return Ok(ExecServerUnifiedExecSessionFactory::from_spawned_server( - Arc::new(spawned_server), - )); - } - - let client = ExecServerClient::connect_in_process(ExecServerClientConnectOptions::default()) - .await - .map_err(|err| UnifiedExecError::create_process(err.to_string()))?; - Ok(ExecServerUnifiedExecSessionFactory::from_client(client)) -} - -fn default_local_exec_server_command() -> ExecServerLaunchCommand { - let binary_name = if cfg!(windows) { - "codex-exec-server.exe" +pub(crate) fn unified_exec_session_factory_for_environment( + environment: &Environment, +) -> UnifiedExecSessionFactoryHandle { + if let Some(client) = environment.exec_server_client() { + ExecServerUnifiedExecSessionFactory::from_client(client) } else { - "codex-exec-server" - }; - let program = std::env::current_exe() - .ok() - .map(|current_exe| current_exe.with_file_name(binary_name)) - .filter(|candidate| candidate.exists()) - .unwrap_or_else(|| PathBuf::from(binary_name)); - ExecServerLaunchCommand { - program, - args: Vec::new(), + local_unified_exec_session_factory() } } diff --git a/codex-rs/core/src/unified_exec/mod.rs b/codex-rs/core/src/unified_exec/mod.rs index d797ff90dc..496246af72 100644 --- a/codex-rs/core/src/unified_exec/mod.rs +++ b/codex-rs/core/src/unified_exec/mod.rs @@ -50,7 +50,7 @@ pub(crate) fn set_deterministic_process_ids_for_tests(enabled: bool) { pub(crate) use backend::UnifiedExecSessionFactoryHandle; pub(crate) use backend::local_unified_exec_session_factory; -pub(crate) use backend::unified_exec_session_factory_for_config; +pub(crate) use backend::unified_exec_session_factory_for_environment; pub(crate) use errors::UnifiedExecError; pub(crate) use process::NoopSpawnLifecycle; #[cfg(unix)] diff --git a/codex-rs/core/src/unified_exec/mod_tests.rs b/codex-rs/core/src/unified_exec/mod_tests.rs index 75596b3e22..c15e5c10fd 100644 --- a/codex-rs/core/src/unified_exec/mod_tests.rs +++ b/codex-rs/core/src/unified_exec/mod_tests.rs @@ -11,13 +11,10 @@ use crate::tools::context::ExecCommandToolOutput; use crate::unified_exec::ExecCommandRequest; use crate::unified_exec::WriteStdinRequest; use core_test_support::skip_if_sandbox; -use std::sync::Arc; use std::path::Path; -use std::path::PathBuf; -use std::process::Command; -use tokio::time::Duration; +use std::sync::Arc; use tempfile::TempDir; -use toml::Value as TomlValue; +use tokio::time::Duration; fn test_exec_request(command: Vec, cwd: &Path) -> crate::sandboxing::ExecRequest { crate::sandboxing::ExecRequest { @@ -253,61 +250,25 @@ async fn unified_exec_timeouts() -> anyhow::Result<()> { } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unified_exec_can_spawn_a_local_exec_server_backend() -> anyhow::Result<()> { +async fn unified_exec_can_use_remote_exec_server_environment() -> anyhow::Result<()> { skip_if_sandbox!(Ok(())); let codex_home = TempDir::new()?; let cwd = TempDir::new()?; let config = ConfigBuilder::default() .codex_home(codex_home.path().to_path_buf()) - .cli_overrides(vec![ - ( - "experimental_unified_exec_use_exec_server".to_string(), - TomlValue::Boolean(true), - ), - ( - "experimental_unified_exec_spawn_local_exec_server".to_string(), - TomlValue::Boolean(true), - ), - ]) .harness_overrides(ConfigOverrides { cwd: Some(cwd.path().to_path_buf()), ..Default::default() }) .build() .await?; - let workspace_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .parent() - .expect("core crate should be under codex-rs") - .to_path_buf(); - let cargo = PathBuf::from(env!("CARGO")); - let build_status = Command::new(&cargo) - .current_dir(&workspace_root) - .args([ - "build", - "-p", - "codex-exec-server", - "--bin", - "codex-exec-server", - ]) - .status()?; - assert!(build_status.success(), "failed to build codex-exec-server"); - let target_dir = std::env::var_os("CARGO_TARGET_DIR") - .map(PathBuf::from) - .unwrap_or_else(|| workspace_root.join("target")); - let binary_name = if cfg!(windows) { - "codex-exec-server.exe" - } else { - "codex-exec-server" - }; - let session_factory = unified_exec_session_factory_for_config( - &config, - Some(codex_exec_server::ExecServerLaunchCommand { - program: target_dir.join("debug").join(binary_name), - args: Vec::new(), - }), + let client = codex_exec_server::ExecServerClient::connect_in_process( + codex_exec_server::ExecServerClientConnectOptions::default(), ) .await?; + let environment = codex_exec_server::Environment::from_exec_server_client(client); + let session_factory = unified_exec_session_factory_for_environment(&environment); let manager = UnifiedExecProcessManager::with_session_factory( DEFAULT_MAX_BACKGROUND_TERMINAL_TIMEOUT_MS, session_factory, @@ -319,7 +280,7 @@ async fn unified_exec_can_spawn_a_local_exec_server_backend() -> anyhow::Result< vec![ "bash".to_string(), "-c".to_string(), - "printf unified_exec_spawned_exec_server_backend_marker".to_string(), + "printf unified_exec_remote_exec_server_environment_marker".to_string(), ], cwd.path(), ), @@ -332,7 +293,7 @@ async fn unified_exec_can_spawn_a_local_exec_server_backend() -> anyhow::Result< assert_eq!( String::from_utf8_lossy(&chunk), - "unified_exec_spawned_exec_server_backend_marker" + "unified_exec_remote_exec_server_environment_marker" ); process.terminate(); diff --git a/codex-rs/exec-server/src/environment.rs b/codex-rs/exec-server/src/environment.rs index c8635ec03a..f350b3aba4 100644 --- a/codex-rs/exec-server/src/environment.rs +++ b/codex-rs/exec-server/src/environment.rs @@ -3,11 +3,13 @@ use crate::ExecServerError; use crate::RemoteExecServerConnectArgs; use crate::fs; use crate::fs::ExecutorFileSystem; +use std::sync::Arc; -#[derive(Clone, Default)] +#[derive(Clone)] pub struct Environment { experimental_exec_server_url: Option, - remote_exec_server_client: Option, + exec_server_client: Option, + file_system: Arc, } impl std::fmt::Debug for Environment { @@ -17,19 +19,24 @@ impl std::fmt::Debug for Environment { "experimental_exec_server_url", &self.experimental_exec_server_url, ) - .field( - "has_remote_exec_server_client", - &self.remote_exec_server_client.is_some(), - ) + .field("has_exec_server_client", &self.exec_server_client.is_some()) .finish() } } impl Environment { + pub fn local() -> Self { + Self { + experimental_exec_server_url: None, + exec_server_client: None, + file_system: Arc::new(fs::LocalFileSystem), + } + } + pub async fn create( experimental_exec_server_url: Option, ) -> Result { - let remote_exec_server_client = + let exec_server_client = if let Some(websocket_url) = experimental_exec_server_url.as_deref() { Some( ExecServerClient::connect_websocket(RemoteExecServerConnectArgs::new( @@ -42,35 +49,85 @@ impl Environment { None }; + let file_system: Arc = if let Some(client) = &exec_server_client { + Arc::new(fs::RemoteFileSystem::new(client.clone())) + } else { + Arc::new(fs::LocalFileSystem) + }; + Ok(Self { experimental_exec_server_url, - remote_exec_server_client, + exec_server_client, + file_system, }) } + pub fn from_exec_server_client(client: ExecServerClient) -> Self { + Self { + experimental_exec_server_url: None, + exec_server_client: Some(client.clone()), + file_system: Arc::new(fs::RemoteFileSystem::new(client)), + } + } + pub fn experimental_exec_server_url(&self) -> Option<&str> { self.experimental_exec_server_url.as_deref() } - pub fn remote_exec_server_client(&self) -> Option<&ExecServerClient> { - self.remote_exec_server_client.as_ref() + pub fn exec_server_client(&self) -> Option { + self.exec_server_client.clone() } - pub fn get_filesystem(&self) -> impl ExecutorFileSystem + use<> { - fs::LocalFileSystem + pub fn get_filesystem(&self) -> Arc { + Arc::clone(&self.file_system) + } +} + +impl Default for Environment { + fn default() -> Self { + Self::local() } } #[cfg(test)] mod tests { use super::Environment; + use crate::ExecServerClient; + use crate::ExecServerClientConnectOptions; + use codex_utils_absolute_path::AbsolutePathBuf; use pretty_assertions::assert_eq; + use tempfile::TempDir; #[tokio::test] async fn create_without_remote_exec_server_url_does_not_connect() { let environment = Environment::create(None).await.expect("create environment"); assert_eq!(environment.experimental_exec_server_url(), None); - assert!(environment.remote_exec_server_client().is_none()); + assert!(environment.exec_server_client().is_none()); + } + + #[tokio::test] + async fn environment_uses_remote_filesystem_abstraction_when_client_is_provided() { + let client = + ExecServerClient::connect_in_process(ExecServerClientConnectOptions::default()) + .await + .expect("connect in-process client"); + let environment = Environment::from_exec_server_client(client); + let tempdir = TempDir::new().expect("tempdir"); + let path = AbsolutePathBuf::try_from(tempdir.path().join("marker.txt")).expect("path"); + + environment + .get_filesystem() + .write_file(&path, b"hello".to_vec()) + .await + .expect("write file through environment abstraction"); + + let bytes = environment + .get_filesystem() + .read_file(&path) + .await + .expect("read file through environment abstraction"); + + assert_eq!(bytes, b"hello"); } } diff --git a/codex-rs/exec-server/src/fs.rs b/codex-rs/exec-server/src/fs.rs index 82e0b8e6e6..a4a7f051ee 100644 --- a/codex-rs/exec-server/src/fs.rs +++ b/codex-rs/exec-server/src/fs.rs @@ -1,4 +1,13 @@ use async_trait::async_trait; +use base64::Engine as _; +use base64::engine::general_purpose::STANDARD; +use codex_app_server_protocol::FsCopyParams; +use codex_app_server_protocol::FsCreateDirectoryParams; +use codex_app_server_protocol::FsGetMetadataParams; +use codex_app_server_protocol::FsReadDirectoryParams; +use codex_app_server_protocol::FsReadFileParams; +use codex_app_server_protocol::FsRemoveParams; +use codex_app_server_protocol::FsWriteFileParams; use codex_utils_absolute_path::AbsolutePathBuf; use std::path::Component; use std::path::Path; @@ -7,6 +16,9 @@ use std::time::SystemTime; use std::time::UNIX_EPOCH; use tokio::io; +use crate::ExecServerClient; +use crate::ExecServerError; + const MAX_READ_FILE_BYTES: u64 = 512 * 1024 * 1024; #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -203,6 +215,129 @@ impl ExecutorFileSystem for LocalFileSystem { } } +#[derive(Clone)] +pub(crate) struct RemoteFileSystem { + client: ExecServerClient, +} + +impl RemoteFileSystem { + pub(crate) fn new(client: ExecServerClient) -> Self { + Self { client } + } +} + +#[async_trait] +impl ExecutorFileSystem for RemoteFileSystem { + async fn read_file(&self, path: &AbsolutePathBuf) -> FileSystemResult> { + let response = self + .client + .fs_read_file(FsReadFileParams { path: path.clone() }) + .await + .map_err(map_exec_server_error)?; + STANDARD + .decode(response.data_base64) + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err)) + } + + async fn write_file(&self, path: &AbsolutePathBuf, contents: Vec) -> FileSystemResult<()> { + self.client + .fs_write_file(FsWriteFileParams { + path: path.clone(), + data_base64: STANDARD.encode(contents), + }) + .await + .map_err(map_exec_server_error)?; + Ok(()) + } + + async fn create_directory( + &self, + path: &AbsolutePathBuf, + options: CreateDirectoryOptions, + ) -> FileSystemResult<()> { + self.client + .fs_create_directory(FsCreateDirectoryParams { + path: path.clone(), + recursive: Some(options.recursive), + }) + .await + .map_err(map_exec_server_error)?; + Ok(()) + } + + async fn get_metadata(&self, path: &AbsolutePathBuf) -> FileSystemResult { + let response = self + .client + .fs_get_metadata(FsGetMetadataParams { path: path.clone() }) + .await + .map_err(map_exec_server_error)?; + Ok(FileMetadata { + is_directory: response.is_directory, + is_file: response.is_file, + created_at_ms: response.created_at_ms, + modified_at_ms: response.modified_at_ms, + }) + } + + async fn read_directory( + &self, + path: &AbsolutePathBuf, + ) -> FileSystemResult> { + let response = self + .client + .fs_read_directory(FsReadDirectoryParams { path: path.clone() }) + .await + .map_err(map_exec_server_error)?; + Ok(response + .entries + .into_iter() + .map(|entry| ReadDirectoryEntry { + file_name: entry.file_name, + is_directory: entry.is_directory, + is_file: entry.is_file, + }) + .collect()) + } + + async fn remove(&self, path: &AbsolutePathBuf, options: RemoveOptions) -> FileSystemResult<()> { + self.client + .fs_remove(FsRemoveParams { + path: path.clone(), + recursive: Some(options.recursive), + force: Some(options.force), + }) + .await + .map_err(map_exec_server_error)?; + Ok(()) + } + + async fn copy( + &self, + source_path: &AbsolutePathBuf, + destination_path: &AbsolutePathBuf, + options: CopyOptions, + ) -> FileSystemResult<()> { + self.client + .fs_copy(FsCopyParams { + source_path: source_path.clone(), + destination_path: destination_path.clone(), + recursive: options.recursive, + }) + .await + .map_err(map_exec_server_error)?; + Ok(()) + } +} + +fn map_exec_server_error(err: ExecServerError) -> io::Error { + match err { + ExecServerError::Server { code, message } if matches!(code, -32600 | -32602) => { + io::Error::new(io::ErrorKind::InvalidInput, message) + } + other => io::Error::other(other.to_string()), + } +} + fn copy_dir_recursive(source: &Path, target: &Path) -> io::Result<()> { std::fs::create_dir_all(target)?; for entry in std::fs::read_dir(source)? { diff --git a/codex-rs/exec-server/src/lib.rs b/codex-rs/exec-server/src/lib.rs index df12583809..a450a72f8e 100644 --- a/codex-rs/exec-server/src/lib.rs +++ b/codex-rs/exec-server/src/lib.rs @@ -13,14 +13,6 @@ pub use client::ExecServerError; pub use client_api::ExecServerClientConnectOptions; pub use client_api::ExecServerEvent; pub use client_api::RemoteExecServerConnectArgs; -pub use environment::Environment; -pub use fs::CopyOptions; -pub use fs::CreateDirectoryOptions; -pub use fs::ExecutorFileSystem; -pub use fs::FileMetadata; -pub use fs::FileSystemResult; -pub use fs::ReadDirectoryEntry; -pub use fs::RemoveOptions; pub use codex_app_server_protocol::FsCopyParams; pub use codex_app_server_protocol::FsCopyResponse; pub use codex_app_server_protocol::FsCreateDirectoryParams; @@ -36,6 +28,14 @@ pub use codex_app_server_protocol::FsRemoveParams; pub use codex_app_server_protocol::FsRemoveResponse; pub use codex_app_server_protocol::FsWriteFileParams; pub use codex_app_server_protocol::FsWriteFileResponse; +pub use environment::Environment; +pub use fs::CopyOptions; +pub use fs::CreateDirectoryOptions; +pub use fs::ExecutorFileSystem; +pub use fs::FileMetadata; +pub use fs::FileSystemResult; +pub use fs::ReadDirectoryEntry; +pub use fs::RemoveOptions; pub use local::ExecServerLaunchCommand; pub use local::SpawnedExecServer; pub use local::spawn_local_exec_server; diff --git a/codex-rs/exec-server/src/server/filesystem.rs b/codex-rs/exec-server/src/server/filesystem.rs index 50a2e67094..358db2636f 100644 --- a/codex-rs/exec-server/src/server/filesystem.rs +++ b/codex-rs/exec-server/src/server/filesystem.rs @@ -36,7 +36,7 @@ pub(crate) struct ExecServerFileSystem { impl Default for ExecServerFileSystem { fn default() -> Self { Self { - file_system: Arc::new(Environment.get_filesystem()), + file_system: Environment::default().get_filesystem(), } } }