[codex] Remove async_trait from first-party code (#27475)

## Why

First-party async traits should expose their `Send` contracts explicitly
without requiring `async_trait`. This completes the migration pattern
established in #27303 and #27304.

## What changed

- Replaced the remaining first-party `async_trait` traits with native
return-position `impl Future + Send` where statically dispatched and
explicit boxed `Send` futures where object safety is required.
- Kept implementations behavior-preserving, outlining existing async
bodies into inherent methods where that keeps the diff reviewable.
- Removed all direct first-party `async-trait` dependencies and the
workspace dependency declaration.
- Added a cargo-deny policy that permits `async-trait` only through the
remaining transitive wrapper crates.
- Updated `rand` from 0.8.5 to 0.8.6 to resolve RUSTSEC-2026-0097 and
keep the full cargo-deny check passing.

## Validation

- `just test -p codex-exec-server`: 216 passed, 2 skipped.
- `just test -p codex-model-provider`: 39 passed.
- `just test -p codex-core` and `just test`: changed tests passed;
remaining failures are environment-sensitive suites unrelated to this
migration.
- `cargo deny check`
- `just fix`
- `just fmt`
- `cargo shear`
- `just bazel-lock-check`
This commit is contained in:
Adam Perry @ OpenAI
2026-06-11 18:16:39 -07:00
committed by GitHub
parent 1829ed1122
commit 5a56caf18c
98 changed files with 2010 additions and 1050 deletions
@@ -1,4 +1,5 @@
use async_trait::async_trait;
use std::future::Future;
use std::pin::Pin;
use crate::Environment;
use crate::ExecServerError;
@@ -13,12 +14,14 @@ use crate::environment::REMOTE_ENVIRONMENT_ID;
/// selection. Providers should only return provider-owned remote environments;
/// `include_local` controls whether `EnvironmentManager` should add the local
/// environment to the snapshot.
#[async_trait]
pub trait EnvironmentProvider: Send + Sync {
/// Returns the provider-owned environment startup snapshot.
async fn snapshot(&self) -> Result<EnvironmentProviderSnapshot, ExecServerError>;
fn snapshot(&self) -> EnvironmentProviderFuture<'_>;
}
pub type EnvironmentProviderFuture<'a> =
Pin<Box<dyn Future<Output = Result<EnvironmentProviderSnapshot, ExecServerError>> + Send + 'a>>;
#[derive(Clone, Debug)]
pub struct EnvironmentProviderSnapshot {
pub environments: Vec<(String, Environment)>,
@@ -80,10 +83,9 @@ impl DefaultEnvironmentProvider {
}
}
#[async_trait]
impl EnvironmentProvider for DefaultEnvironmentProvider {
async fn snapshot(&self) -> Result<EnvironmentProviderSnapshot, ExecServerError> {
Ok(self.snapshot_inner())
fn snapshot(&self) -> EnvironmentProviderFuture<'_> {
Box::pin(async { Ok(self.snapshot_inner()) })
}
}
+7 -4
View File
@@ -4,13 +4,13 @@ use std::path::Path;
use std::path::PathBuf;
use std::time::Duration;
use async_trait::async_trait;
use serde::Deserialize;
use tokio_tungstenite::tungstenite::client::IntoClientRequest;
use crate::DefaultEnvironmentProvider;
use crate::Environment;
use crate::EnvironmentProvider;
use crate::EnvironmentProviderFuture;
use crate::ExecServerError;
use crate::client_api::DEFAULT_REMOTE_EXEC_SERVER_CONNECT_TIMEOUT;
use crate::client_api::DEFAULT_REMOTE_EXEC_SERVER_INITIALIZE_TIMEOUT;
@@ -92,10 +92,7 @@ impl TomlEnvironmentProvider {
environments: parsed_environments,
})
}
}
#[async_trait]
impl EnvironmentProvider for TomlEnvironmentProvider {
async fn snapshot(&self) -> Result<EnvironmentProviderSnapshot, ExecServerError> {
let mut environments = Vec::with_capacity(self.environments.len());
for (id, transport_params) in &self.environments {
@@ -116,6 +113,12 @@ impl EnvironmentProvider for TomlEnvironmentProvider {
}
}
impl EnvironmentProvider for TomlEnvironmentProvider {
fn snapshot(&self) -> EnvironmentProviderFuture<'_> {
Box::pin(TomlEnvironmentProvider::snapshot(self))
}
}
fn parse_environment_toml(
item: EnvironmentToml,
config_dir: Option<&Path>,
+4
View File
@@ -33,6 +33,7 @@ pub use client_api::RemoteExecServerConnectArgs;
pub use codex_file_system::CopyOptions;
pub use codex_file_system::CreateDirectoryOptions;
pub use codex_file_system::ExecutorFileSystem;
pub use codex_file_system::ExecutorFileSystemFuture;
pub use codex_file_system::FileMetadata;
pub use codex_file_system::FileSystemResult;
pub use codex_file_system::FileSystemSandboxContext;
@@ -45,14 +46,17 @@ pub use environment::LOCAL_ENVIRONMENT_ID;
pub use environment::REMOTE_ENVIRONMENT_ID;
pub use environment_provider::DefaultEnvironmentProvider;
pub use environment_provider::EnvironmentProvider;
pub use environment_provider::EnvironmentProviderFuture;
pub use fs_helper::CODEX_FS_HELPER_ARG1;
pub use fs_helper_main::main as run_fs_helper_main;
pub use local_file_system::LOCAL_FS;
pub use local_file_system::LocalFileSystem;
pub use process::ExecBackend;
pub use process::ExecBackendFuture;
pub use process::ExecProcess;
pub use process::ExecProcessEvent;
pub use process::ExecProcessEventReceiver;
pub use process::ExecProcessFuture;
pub use process::StartedExecProcess;
pub use process_id::ProcessId;
pub use protocol::EnvironmentInfo;
+243 -7
View File
@@ -1,4 +1,3 @@
use async_trait::async_trait;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_path_uri::PathUri;
use std::path::Path;
@@ -13,6 +12,7 @@ use crate::CopyOptions;
use crate::CreateDirectoryOptions;
use crate::ExecServerRuntimePaths;
use crate::ExecutorFileSystem;
use crate::ExecutorFileSystemFuture;
use crate::FileMetadata;
use crate::FileSystemResult;
use crate::FileSystemSandboxContext;
@@ -78,8 +78,7 @@ impl LocalFileSystem {
}
}
#[async_trait]
impl ExecutorFileSystem for LocalFileSystem {
impl LocalFileSystem {
async fn canonicalize(
&self,
path: &PathUri,
@@ -160,8 +159,86 @@ impl ExecutorFileSystem for LocalFileSystem {
}
}
#[async_trait]
impl ExecutorFileSystem for UnsandboxedFileSystem {
impl ExecutorFileSystem for LocalFileSystem {
fn canonicalize<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, PathUri> {
Box::pin(LocalFileSystem::canonicalize(self, path, sandbox))
}
fn read_file<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<u8>> {
Box::pin(LocalFileSystem::read_file(self, path, sandbox))
}
fn write_file<'a>(
&'a self,
path: &'a PathUri,
contents: Vec<u8>,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(LocalFileSystem::write_file(self, path, contents, sandbox))
}
fn create_directory<'a>(
&'a self,
path: &'a PathUri,
options: CreateDirectoryOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(LocalFileSystem::create_directory(
self, path, options, sandbox,
))
}
fn get_metadata<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, FileMetadata> {
Box::pin(LocalFileSystem::get_metadata(self, path, sandbox))
}
fn read_directory<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<ReadDirectoryEntry>> {
Box::pin(LocalFileSystem::read_directory(self, path, sandbox))
}
fn remove<'a>(
&'a self,
path: &'a PathUri,
options: RemoveOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(LocalFileSystem::remove(self, path, options, sandbox))
}
fn copy<'a>(
&'a self,
source_path: &'a PathUri,
destination_path: &'a PathUri,
options: CopyOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(LocalFileSystem::copy(
self,
source_path,
destination_path,
options,
sandbox,
))
}
}
impl UnsandboxedFileSystem {
async fn canonicalize(
&self,
path: &PathUri,
@@ -255,8 +332,88 @@ impl ExecutorFileSystem for UnsandboxedFileSystem {
}
}
#[async_trait]
impl ExecutorFileSystem for DirectFileSystem {
impl ExecutorFileSystem for UnsandboxedFileSystem {
fn canonicalize<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, PathUri> {
Box::pin(UnsandboxedFileSystem::canonicalize(self, path, sandbox))
}
fn read_file<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<u8>> {
Box::pin(UnsandboxedFileSystem::read_file(self, path, sandbox))
}
fn write_file<'a>(
&'a self,
path: &'a PathUri,
contents: Vec<u8>,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(UnsandboxedFileSystem::write_file(
self, path, contents, sandbox,
))
}
fn create_directory<'a>(
&'a self,
path: &'a PathUri,
options: CreateDirectoryOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(UnsandboxedFileSystem::create_directory(
self, path, options, sandbox,
))
}
fn get_metadata<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, FileMetadata> {
Box::pin(UnsandboxedFileSystem::get_metadata(self, path, sandbox))
}
fn read_directory<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<ReadDirectoryEntry>> {
Box::pin(UnsandboxedFileSystem::read_directory(self, path, sandbox))
}
fn remove<'a>(
&'a self,
path: &'a PathUri,
options: RemoveOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(UnsandboxedFileSystem::remove(self, path, options, sandbox))
}
fn copy<'a>(
&'a self,
source_path: &'a PathUri,
destination_path: &'a PathUri,
options: CopyOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(UnsandboxedFileSystem::copy(
self,
source_path,
destination_path,
options,
sandbox,
))
}
}
impl DirectFileSystem {
async fn canonicalize(
&self,
path: &PathUri,
@@ -434,6 +591,85 @@ impl ExecutorFileSystem for DirectFileSystem {
}
}
impl ExecutorFileSystem for DirectFileSystem {
fn canonicalize<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, PathUri> {
Box::pin(DirectFileSystem::canonicalize(self, path, sandbox))
}
fn read_file<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<u8>> {
Box::pin(DirectFileSystem::read_file(self, path, sandbox))
}
fn write_file<'a>(
&'a self,
path: &'a PathUri,
contents: Vec<u8>,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(DirectFileSystem::write_file(self, path, contents, sandbox))
}
fn create_directory<'a>(
&'a self,
path: &'a PathUri,
options: CreateDirectoryOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(DirectFileSystem::create_directory(
self, path, options, sandbox,
))
}
fn get_metadata<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, FileMetadata> {
Box::pin(DirectFileSystem::get_metadata(self, path, sandbox))
}
fn read_directory<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<ReadDirectoryEntry>> {
Box::pin(DirectFileSystem::read_directory(self, path, sandbox))
}
fn remove<'a>(
&'a self,
path: &'a PathUri,
options: RemoveOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(DirectFileSystem::remove(self, path, options, sandbox))
}
fn copy<'a>(
&'a self,
source_path: &'a PathUri,
destination_path: &'a PathUri,
options: CopyOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(DirectFileSystem::copy(
self,
source_path,
destination_path,
options,
sandbox,
))
}
}
fn reject_sandbox_context(sandbox: Option<&FileSystemSandboxContext>) -> io::Result<()> {
if sandbox.is_some() {
return Err(io::Error::new(
+43 -15
View File
@@ -4,7 +4,6 @@ use std::collections::hash_map::Entry;
use std::sync::Arc;
use std::time::Duration;
use async_trait::async_trait;
use codex_app_server_protocol::JSONRPCErrorError;
use codex_protocol::config_types::EnvironmentVariablePattern;
use codex_protocol::config_types::ShellEnvironmentPolicy;
@@ -18,9 +17,11 @@ use tokio::sync::mpsc;
use tokio::sync::watch;
use crate::ExecBackend;
use crate::ExecBackendFuture;
use crate::ExecProcess;
use crate::ExecProcessEvent;
use crate::ExecProcessEventReceiver;
use crate::ExecProcessFuture;
use crate::ExecServerError;
use crate::ProcessId;
use crate::StartedExecProcess;
@@ -460,8 +461,7 @@ fn shell_environment_policy(env_policy: &ExecEnvPolicy) -> ShellEnvironmentPolic
}
}
#[async_trait]
impl ExecBackend for LocalProcess {
impl LocalProcess {
async fn start(&self, params: ExecParams) -> Result<StartedExecProcess, ExecServerError> {
let (response, wake_tx, events) = self
.start_process(params)
@@ -478,20 +478,13 @@ impl ExecBackend for LocalProcess {
}
}
#[async_trait]
impl ExecProcess for LocalExecProcess {
fn process_id(&self) -> &ProcessId {
&self.process_id
}
fn subscribe_wake(&self) -> watch::Receiver<u64> {
self.wake_tx.subscribe()
}
fn subscribe_events(&self) -> ExecProcessEventReceiver {
self.events.subscribe()
impl ExecBackend for LocalProcess {
fn start(&self, params: ExecParams) -> ExecBackendFuture<'_> {
Box::pin(LocalProcess::start(self, params))
}
}
impl LocalExecProcess {
async fn read(
&self,
after_seq: Option<u64>,
@@ -516,6 +509,41 @@ impl ExecProcess for LocalExecProcess {
}
}
impl ExecProcess for LocalExecProcess {
fn process_id(&self) -> &ProcessId {
&self.process_id
}
fn subscribe_wake(&self) -> watch::Receiver<u64> {
self.wake_tx.subscribe()
}
fn subscribe_events(&self) -> ExecProcessEventReceiver {
self.events.subscribe()
}
fn read(
&self,
after_seq: Option<u64>,
max_bytes: Option<usize>,
wait_ms: Option<u64>,
) -> ExecProcessFuture<'_, ReadResponse> {
Box::pin(LocalExecProcess::read(self, after_seq, max_bytes, wait_ms))
}
fn write(&self, chunk: Vec<u8>) -> ExecProcessFuture<'_, WriteResponse> {
Box::pin(LocalExecProcess::write(self, chunk))
}
fn signal(&self, signal: ProcessSignal) -> ExecProcessFuture<'_, ()> {
Box::pin(LocalExecProcess::signal(self, signal))
}
fn terminate(&self) -> ExecProcessFuture<'_, ()> {
Box::pin(LocalExecProcess::terminate(self))
}
}
impl LocalProcess {
async fn read(
&self,
+14 -9
View File
@@ -1,8 +1,9 @@
use std::collections::VecDeque;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::sync::Mutex as StdMutex;
use async_trait::async_trait;
use tokio::sync::broadcast;
use tokio::sync::watch;
@@ -162,7 +163,6 @@ impl ExecProcessEventReceiver {
/// `read` is the request/response API for callers that want to page through
/// buffered output, while `subscribe_events` is the streaming API for callers
/// that want output and lifecycle changes delivered as they happen.
#[async_trait]
pub trait ExecProcess: Send + Sync {
fn process_id(&self) -> &ProcessId;
@@ -170,25 +170,30 @@ pub trait ExecProcess: Send + Sync {
fn subscribe_events(&self) -> ExecProcessEventReceiver;
async fn read(
fn read(
&self,
after_seq: Option<u64>,
max_bytes: Option<usize>,
wait_ms: Option<u64>,
) -> Result<ReadResponse, ExecServerError>;
) -> ExecProcessFuture<'_, ReadResponse>;
async fn write(&self, chunk: Vec<u8>) -> Result<WriteResponse, ExecServerError>;
fn write(&self, chunk: Vec<u8>) -> ExecProcessFuture<'_, WriteResponse>;
async fn signal(&self, signal: ProcessSignal) -> Result<(), ExecServerError>;
fn signal(&self, signal: ProcessSignal) -> ExecProcessFuture<'_, ()>;
async fn terminate(&self) -> Result<(), ExecServerError>;
fn terminate(&self) -> ExecProcessFuture<'_, ()>;
}
#[async_trait]
pub type ExecProcessFuture<'a, T> =
Pin<Box<dyn Future<Output = Result<T, ExecServerError>> + Send + 'a>>;
pub trait ExecBackend: Send + Sync {
async fn start(&self, params: ExecParams) -> Result<StartedExecProcess, ExecServerError>;
fn start(&self, params: ExecParams) -> ExecBackendFuture<'_>;
}
pub type ExecBackendFuture<'a> =
Pin<Box<dyn Future<Output = Result<StartedExecProcess, ExecServerError>> + Send + 'a>>;
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
+80 -4
View File
@@ -1,4 +1,3 @@
use async_trait::async_trait;
use base64::Engine as _;
use base64::engine::general_purpose::STANDARD;
use codex_utils_path_uri::PathUri;
@@ -9,6 +8,7 @@ use crate::CopyOptions;
use crate::CreateDirectoryOptions;
use crate::ExecServerError;
use crate::ExecutorFileSystem;
use crate::ExecutorFileSystemFuture;
use crate::FileMetadata;
use crate::FileSystemResult;
use crate::FileSystemSandboxContext;
@@ -36,10 +36,7 @@ impl RemoteFileSystem {
trace!("remote fs new");
Self { client }
}
}
#[async_trait]
impl ExecutorFileSystem for RemoteFileSystem {
async fn canonicalize(
&self,
path: &PathUri,
@@ -207,6 +204,85 @@ impl ExecutorFileSystem for RemoteFileSystem {
}
}
impl ExecutorFileSystem for RemoteFileSystem {
fn canonicalize<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, PathUri> {
Box::pin(RemoteFileSystem::canonicalize(self, path, sandbox))
}
fn read_file<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<u8>> {
Box::pin(RemoteFileSystem::read_file(self, path, sandbox))
}
fn write_file<'a>(
&'a self,
path: &'a PathUri,
contents: Vec<u8>,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(RemoteFileSystem::write_file(self, path, contents, sandbox))
}
fn create_directory<'a>(
&'a self,
path: &'a PathUri,
options: CreateDirectoryOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(RemoteFileSystem::create_directory(
self, path, options, sandbox,
))
}
fn get_metadata<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, FileMetadata> {
Box::pin(RemoteFileSystem::get_metadata(self, path, sandbox))
}
fn read_directory<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<ReadDirectoryEntry>> {
Box::pin(RemoteFileSystem::read_directory(self, path, sandbox))
}
fn remove<'a>(
&'a self,
path: &'a PathUri,
options: RemoveOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(RemoteFileSystem::remove(self, path, options, sandbox))
}
fn copy<'a>(
&'a self,
source_path: &'a PathUri,
destination_path: &'a PathUri,
options: CopyOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(RemoteFileSystem::copy(
self,
source_path,
destination_path,
options,
sandbox,
))
}
}
fn remote_sandbox_context(
sandbox: Option<&FileSystemSandboxContext>,
) -> Option<FileSystemSandboxContext> {
+47 -19
View File
@@ -1,13 +1,13 @@
use std::sync::Arc;
use async_trait::async_trait;
use tokio::sync::watch;
use tracing::trace;
use crate::ExecBackend;
use crate::ExecBackendFuture;
use crate::ExecProcess;
use crate::ExecProcessEventReceiver;
use crate::ExecServerError;
use crate::ExecProcessFuture;
use crate::StartedExecProcess;
use crate::client::LazyRemoteExecServerClient;
use crate::client::Session;
@@ -30,11 +30,11 @@ impl RemoteProcess {
trace!("remote process new");
Self { client }
}
}
#[async_trait]
impl ExecBackend for RemoteProcess {
async fn start(&self, params: ExecParams) -> Result<StartedExecProcess, ExecServerError> {
async fn start(
&self,
params: ExecParams,
) -> Result<StartedExecProcess, crate::ExecServerError> {
let process_id = params.process_id.clone();
let client = self.client.get().await?;
let session = client.register_session(&process_id).await?;
@@ -49,7 +49,38 @@ impl ExecBackend for RemoteProcess {
}
}
#[async_trait]
impl ExecBackend for RemoteProcess {
fn start(&self, params: ExecParams) -> ExecBackendFuture<'_> {
Box::pin(RemoteProcess::start(self, params))
}
}
impl RemoteExecProcess {
async fn read(
&self,
after_seq: Option<u64>,
max_bytes: Option<usize>,
wait_ms: Option<u64>,
) -> Result<ReadResponse, crate::ExecServerError> {
self.session.read(after_seq, max_bytes, wait_ms).await
}
async fn write(&self, chunk: Vec<u8>) -> Result<WriteResponse, crate::ExecServerError> {
trace!("exec process write");
self.session.write(chunk).await
}
async fn signal(&self, signal: ProcessSignal) -> Result<(), crate::ExecServerError> {
trace!("exec process signal");
self.session.signal(signal).await
}
async fn terminate(&self) -> Result<(), crate::ExecServerError> {
trace!("exec process terminate");
self.session.terminate().await
}
}
impl ExecProcess for RemoteExecProcess {
fn process_id(&self) -> &crate::ProcessId {
self.session.process_id()
@@ -63,28 +94,25 @@ impl ExecProcess for RemoteExecProcess {
self.session.subscribe_events()
}
async fn read(
fn read(
&self,
after_seq: Option<u64>,
max_bytes: Option<usize>,
wait_ms: Option<u64>,
) -> Result<ReadResponse, ExecServerError> {
self.session.read(after_seq, max_bytes, wait_ms).await
) -> ExecProcessFuture<'_, ReadResponse> {
Box::pin(RemoteExecProcess::read(self, after_seq, max_bytes, wait_ms))
}
async fn write(&self, chunk: Vec<u8>) -> Result<WriteResponse, ExecServerError> {
trace!("exec process write");
self.session.write(chunk).await
fn write(&self, chunk: Vec<u8>) -> ExecProcessFuture<'_, WriteResponse> {
Box::pin(RemoteExecProcess::write(self, chunk))
}
async fn signal(&self, signal: ProcessSignal) -> Result<(), ExecServerError> {
trace!("exec process signal");
self.session.signal(signal).await
fn signal(&self, signal: ProcessSignal) -> ExecProcessFuture<'_, ()> {
Box::pin(RemoteExecProcess::signal(self, signal))
}
async fn terminate(&self) -> Result<(), ExecServerError> {
trace!("exec process terminate");
self.session.terminate().await
fn terminate(&self) -> ExecProcessFuture<'_, ()> {
Box::pin(RemoteExecProcess::terminate(self))
}
}
@@ -1,4 +1,3 @@
use async_trait::async_trait;
use base64::Engine as _;
use base64::engine::general_purpose::STANDARD;
use codex_app_server_protocol::JSONRPCErrorError;
@@ -9,6 +8,7 @@ use crate::CopyOptions;
use crate::CreateDirectoryOptions;
use crate::ExecServerRuntimePaths;
use crate::ExecutorFileSystem;
use crate::ExecutorFileSystemFuture;
use crate::FileMetadata;
use crate::FileSystemResult;
use crate::FileSystemSandboxContext;
@@ -50,8 +50,7 @@ impl SandboxedFileSystem {
}
}
#[async_trait]
impl ExecutorFileSystem for SandboxedFileSystem {
impl SandboxedFileSystem {
async fn canonicalize(
&self,
path: &PathUri,
@@ -248,6 +247,92 @@ impl ExecutorFileSystem for SandboxedFileSystem {
}
}
impl ExecutorFileSystem for SandboxedFileSystem {
fn canonicalize<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, PathUri> {
Box::pin(SandboxedFileSystem::canonicalize(self, path, sandbox))
}
fn read_file<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<u8>> {
Box::pin(SandboxedFileSystem::read_file(self, path, sandbox))
}
fn write_file<'a>(
&'a self,
path: &'a PathUri,
contents: Vec<u8>,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(SandboxedFileSystem::write_file(
self, path, contents, sandbox,
))
}
fn create_directory<'a>(
&'a self,
path: &'a PathUri,
options: CreateDirectoryOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(SandboxedFileSystem::create_directory(
self, path, options, sandbox,
))
}
fn get_metadata<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, FileMetadata> {
Box::pin(SandboxedFileSystem::get_metadata(self, path, sandbox))
}
fn read_directory<'a>(
&'a self,
path: &'a PathUri,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, Vec<ReadDirectoryEntry>> {
Box::pin(SandboxedFileSystem::read_directory(self, path, sandbox))
}
fn remove<'a>(
&'a self,
path: &'a PathUri,
remove_options: RemoveOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(SandboxedFileSystem::remove(
self,
path,
remove_options,
sandbox,
))
}
fn copy<'a>(
&'a self,
source_path: &'a PathUri,
destination_path: &'a PathUri,
options: CopyOptions,
sandbox: Option<&'a FileSystemSandboxContext>,
) -> ExecutorFileSystemFuture<'a, ()> {
Box::pin(SandboxedFileSystem::copy(
self,
source_path,
destination_path,
options,
sandbox,
))
}
}
fn validate_native_path(path: &PathUri) -> FileSystemResult<()> {
path.to_abs_path().map(drop)
}