mirror of
https://github.com/openai/codex.git
synced 2026-04-26 23:55:25 +00:00
Reshape the exec process seam to mirror the filesystem split style with separate process, local_process, remote_process, and server/process_handler modules, and make Environment own an Arc<dyn ExecProcess>. Co-authored-by: Codex <noreply@openai.com>
173 lines
5.8 KiB
Rust
173 lines
5.8 KiB
Rust
use std::sync::atomic::AtomicBool;
|
|
use std::sync::atomic::Ordering;
|
|
|
|
use crate::protocol::ExecParams;
|
|
use crate::protocol::ExecResponse;
|
|
use crate::protocol::InitializeResponse;
|
|
use crate::protocol::ReadParams;
|
|
use crate::protocol::ReadResponse;
|
|
use crate::protocol::TerminateParams;
|
|
use crate::protocol::TerminateResponse;
|
|
use crate::protocol::WriteParams;
|
|
use crate::protocol::WriteResponse;
|
|
use crate::rpc::RpcNotificationSender;
|
|
use crate::rpc::invalid_request;
|
|
use crate::server::filesystem::ExecServerFileSystem;
|
|
use crate::server::process_handler::ProcessHandler;
|
|
use codex_app_server_protocol::FsCopyParams;
|
|
use codex_app_server_protocol::FsCopyResponse;
|
|
use codex_app_server_protocol::FsCreateDirectoryParams;
|
|
use codex_app_server_protocol::FsCreateDirectoryResponse;
|
|
use codex_app_server_protocol::FsGetMetadataParams;
|
|
use codex_app_server_protocol::FsGetMetadataResponse;
|
|
use codex_app_server_protocol::FsReadDirectoryParams;
|
|
use codex_app_server_protocol::FsReadDirectoryResponse;
|
|
use codex_app_server_protocol::FsReadFileParams;
|
|
use codex_app_server_protocol::FsReadFileResponse;
|
|
use codex_app_server_protocol::FsRemoveParams;
|
|
use codex_app_server_protocol::FsRemoveResponse;
|
|
use codex_app_server_protocol::FsWriteFileParams;
|
|
use codex_app_server_protocol::FsWriteFileResponse;
|
|
use codex_app_server_protocol::JSONRPCErrorError;
|
|
|
|
pub(crate) struct ExecServerHandler {
|
|
file_system: ExecServerFileSystem,
|
|
process_handler: ProcessHandler,
|
|
initialize_requested: AtomicBool,
|
|
initialized: AtomicBool,
|
|
}
|
|
|
|
impl ExecServerHandler {
|
|
pub(crate) fn new(notifications: RpcNotificationSender) -> Self {
|
|
Self {
|
|
file_system: ExecServerFileSystem::default(),
|
|
process_handler: ProcessHandler::new(notifications),
|
|
initialize_requested: AtomicBool::new(false),
|
|
initialized: AtomicBool::new(false),
|
|
}
|
|
}
|
|
|
|
pub(crate) async fn shutdown(&self) {
|
|
self.process_handler.shutdown().await;
|
|
}
|
|
|
|
pub(crate) fn initialize(&self) -> Result<InitializeResponse, JSONRPCErrorError> {
|
|
if self.initialize_requested.swap(true, Ordering::SeqCst) {
|
|
return Err(invalid_request(
|
|
"initialize may only be sent once per connection".to_string(),
|
|
));
|
|
}
|
|
Ok(InitializeResponse {})
|
|
}
|
|
|
|
pub(crate) fn initialized(&self) -> Result<(), String> {
|
|
if !self.initialize_requested.load(Ordering::SeqCst) {
|
|
return Err("received `initialized` notification before `initialize`".into());
|
|
}
|
|
self.initialized.store(true, Ordering::SeqCst);
|
|
Ok(())
|
|
}
|
|
|
|
fn require_initialized_for(&self, method_family: &str) -> Result<(), JSONRPCErrorError> {
|
|
if !self.initialize_requested.load(Ordering::SeqCst) {
|
|
return Err(invalid_request(format!(
|
|
"client must call initialize before using {method_family} methods"
|
|
)));
|
|
}
|
|
if !self.initialized.load(Ordering::SeqCst) {
|
|
return Err(invalid_request(format!(
|
|
"client must send initialized before using {method_family} methods"
|
|
)));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) async fn exec(&self, params: ExecParams) -> Result<ExecResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("exec")?;
|
|
self.process_handler.exec(params).await
|
|
}
|
|
|
|
pub(crate) async fn exec_read(
|
|
&self,
|
|
params: ReadParams,
|
|
) -> Result<ReadResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("exec")?;
|
|
self.process_handler.exec_read(params).await
|
|
}
|
|
|
|
pub(crate) async fn exec_write(
|
|
&self,
|
|
params: WriteParams,
|
|
) -> Result<WriteResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("exec")?;
|
|
self.process_handler.exec_write(params).await
|
|
}
|
|
|
|
pub(crate) async fn terminate(
|
|
&self,
|
|
params: TerminateParams,
|
|
) -> Result<TerminateResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("exec")?;
|
|
self.process_handler.terminate(params).await
|
|
}
|
|
|
|
pub(crate) async fn fs_read_file(
|
|
&self,
|
|
params: FsReadFileParams,
|
|
) -> Result<FsReadFileResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("filesystem")?;
|
|
self.file_system.read_file(params).await
|
|
}
|
|
|
|
pub(crate) async fn fs_write_file(
|
|
&self,
|
|
params: FsWriteFileParams,
|
|
) -> Result<FsWriteFileResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("filesystem")?;
|
|
self.file_system.write_file(params).await
|
|
}
|
|
|
|
pub(crate) async fn fs_create_directory(
|
|
&self,
|
|
params: FsCreateDirectoryParams,
|
|
) -> Result<FsCreateDirectoryResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("filesystem")?;
|
|
self.file_system.create_directory(params).await
|
|
}
|
|
|
|
pub(crate) async fn fs_get_metadata(
|
|
&self,
|
|
params: FsGetMetadataParams,
|
|
) -> Result<FsGetMetadataResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("filesystem")?;
|
|
self.file_system.get_metadata(params).await
|
|
}
|
|
|
|
pub(crate) async fn fs_read_directory(
|
|
&self,
|
|
params: FsReadDirectoryParams,
|
|
) -> Result<FsReadDirectoryResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("filesystem")?;
|
|
self.file_system.read_directory(params).await
|
|
}
|
|
|
|
pub(crate) async fn fs_remove(
|
|
&self,
|
|
params: FsRemoveParams,
|
|
) -> Result<FsRemoveResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("filesystem")?;
|
|
self.file_system.remove(params).await
|
|
}
|
|
|
|
pub(crate) async fn fs_copy(
|
|
&self,
|
|
params: FsCopyParams,
|
|
) -> Result<FsCopyResponse, JSONRPCErrorError> {
|
|
self.require_initialized_for("filesystem")?;
|
|
self.file_system.copy(params).await
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|