mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
protocol: separate app and exec RPC ownership (#29714)
## Why The app-server and exec-server expose separate JSON-RPC APIs, but exec-server currently sources its serialized protocol and envelope types through app-server-oriented code. Giving each API an explicit owner makes the crate boundary legible without introducing shared generic envelopes. ## What changed - Added `codex-exec-server-protocol` to own exec DTOs, process IDs, and JSON-RPC envelopes. - Updated exec-server clients, transports, handlers, and tests to use the new crate. - Exposed app-server's existing JSON-RPC types through a public `rpc` module while retaining root re-exports. - Preserved existing wire shapes, including exec `PathUri` behavior. ## Stack This is PR 1 of 6. Next: [PR #29721](https://github.com/openai/codex/pull/29721), which moves auth mode below the app wire boundary. ## Validation - Exec-server protocol and server coverage passed in the focused protocol test runs. - App-server protocol schema fixtures passed.
This commit is contained in:
committed by
GitHub
Unverified
parent
220f5b76b2
commit
829f5b6b59
@@ -9,7 +9,7 @@ use std::sync::atomic::Ordering;
|
||||
use std::time::Duration;
|
||||
|
||||
use arc_swap::ArcSwap;
|
||||
use codex_app_server_protocol::JSONRPCNotification;
|
||||
use codex_exec_server_protocol::JSONRPCNotification;
|
||||
use futures::FutureExt;
|
||||
use futures::future::BoxFuture;
|
||||
use serde_json::Value;
|
||||
@@ -1187,9 +1187,9 @@ async fn handle_server_notification(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_app_server_protocol::JSONRPCNotification;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCNotification;
|
||||
use codex_exec_server_protocol::JSONRPCResponse;
|
||||
use futures::SinkExt;
|
||||
use futures::StreamExt;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
use std::error::Error as StdError;
|
||||
use std::time::Duration;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_client::build_reqwest_client_with_custom_ca;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
use futures::FutureExt;
|
||||
use futures::StreamExt;
|
||||
use futures::future::BoxFuture;
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::time::Duration;
|
||||
|
||||
use axum::extract::ws::Message as AxumWebSocketMessage;
|
||||
use axum::extract::ws::WebSocket as AxumWebSocket;
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use futures::Sink;
|
||||
use futures::SinkExt;
|
||||
use futures::Stream;
|
||||
@@ -597,8 +597,8 @@ mod tests {
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCRequest;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_exec_server_protocol::JSONRPCRequest;
|
||||
use codex_exec_server_protocol::RequestId;
|
||||
use futures::channel::mpsc as futures_mpsc;
|
||||
use futures::task::AtomicWaker;
|
||||
use tokio::net::TcpListener;
|
||||
@@ -667,7 +667,6 @@ mod tests {
|
||||
id: RequestId::Integer(1),
|
||||
method: "test".to_string(),
|
||||
params: None,
|
||||
trace: None,
|
||||
});
|
||||
|
||||
server_websocket
|
||||
@@ -732,7 +731,6 @@ mod tests {
|
||||
id: RequestId::Integer(1),
|
||||
method: "test".to_string(),
|
||||
params: None,
|
||||
trace: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,9 @@ use crate::local_file_system::LocalFileSystem;
|
||||
use crate::local_process::LocalProcess;
|
||||
use crate::process::ExecBackend;
|
||||
use crate::protocol::EnvironmentInfo;
|
||||
use crate::protocol::ShellInfo;
|
||||
use crate::remote::NoiseRendezvousEnvironmentConfig;
|
||||
use crate::remote_file_system::RemoteFileSystem;
|
||||
use crate::remote_process::RemoteProcess;
|
||||
use codex_shell_command::shell_detect::DetectedShell;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use tokio_util::task::AbortOnDropHandle;
|
||||
|
||||
pub const CODEX_EXEC_SERVER_URL_ENV_VAR: &str = "CODEX_EXEC_SERVER_URL";
|
||||
@@ -605,26 +602,6 @@ impl Environment {
|
||||
}
|
||||
}
|
||||
|
||||
impl EnvironmentInfo {
|
||||
pub(crate) fn local() -> Self {
|
||||
Self {
|
||||
shell: codex_shell_command::shell_detect::default_user_shell().into(),
|
||||
cwd: std::env::current_dir()
|
||||
.ok()
|
||||
.and_then(|cwd| PathUri::from_host_native_path(cwd).ok()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DetectedShell> for ShellInfo {
|
||||
fn from(shell: DetectedShell) -> Self {
|
||||
Self {
|
||||
name: shell.name().to_string(),
|
||||
path: shell.shell_path.to_string_lossy().into_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use base64::Engine as _;
|
||||
use base64::engine::general_purpose::STANDARD;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use tokio::io;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::permissions::FileSystemAccessMode;
|
||||
use codex_protocol::permissions::FileSystemPath;
|
||||
|
||||
@@ -15,9 +15,7 @@ mod local_process;
|
||||
mod noise_channel;
|
||||
mod noise_relay;
|
||||
mod process;
|
||||
mod process_id;
|
||||
mod process_sandbox;
|
||||
mod protocol;
|
||||
mod regular_file;
|
||||
mod relay;
|
||||
mod relay_proto;
|
||||
@@ -29,6 +27,8 @@ mod runtime_paths;
|
||||
mod sandboxed_file_system;
|
||||
mod server;
|
||||
|
||||
use codex_exec_server_protocol as protocol;
|
||||
|
||||
pub use client::ExecServerClient;
|
||||
pub use client::ExecServerError;
|
||||
pub use client::http_client::HttpResponseBodyStream;
|
||||
@@ -39,6 +39,7 @@ pub use client_api::NoiseRendezvousConnectArgs;
|
||||
pub use client_api::NoiseRendezvousConnectBundle;
|
||||
pub use client_api::NoiseRendezvousConnectProvider;
|
||||
pub use client_api::RemoteExecServerConnectArgs;
|
||||
pub use codex_exec_server_protocol::ProcessId;
|
||||
pub use codex_file_system::CopyOptions;
|
||||
pub use codex_file_system::CreateDirectoryOptions;
|
||||
pub use codex_file_system::ExecutorFileSystem;
|
||||
@@ -78,7 +79,6 @@ pub use process::ExecProcessEvent;
|
||||
pub use process::ExecProcessEventReceiver;
|
||||
pub use process::ExecProcessFuture;
|
||||
pub use process::StartedExecProcess;
|
||||
pub use process_id::ProcessId;
|
||||
pub use protocol::ByteChunk;
|
||||
pub use protocol::EnvironmentInfo;
|
||||
pub use protocol::ExecClosedNotification;
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::sync::atomic::AtomicU64;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::time::Duration;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
use codex_protocol::config_types::EnvironmentVariablePattern;
|
||||
use codex_protocol::config_types::ShellEnvironmentPolicy;
|
||||
use codex_protocol::exec_output::ExecToolCallOutput;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCResponse;
|
||||
use codex_exec_server_protocol::RequestId;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::time::timeout;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
|
||||
use crate::ExecServerError;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_app_server_protocol::JSONRPCNotification;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCNotification;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::JsonRpcMessageDecoder;
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
use std::borrow::Borrow;
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct ProcessId(String);
|
||||
|
||||
impl ProcessId {
|
||||
pub fn new(value: impl Into<String>) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> String {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ProcessId {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for ProcessId {
|
||||
fn borrow(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ProcessId {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ProcessId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for ProcessId {
|
||||
fn from(value: String) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for ProcessId {
|
||||
fn from(value: &str) -> Self {
|
||||
Self(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&String> for ProcessId {
|
||||
fn from(value: &String) -> Self {
|
||||
Self(value.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProcessId> for String {
|
||||
fn from(value: ProcessId) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
use codex_network_proxy::CUSTOM_CA_ENV_KEYS;
|
||||
use codex_network_proxy::is_managed_mitm_ca_trust_bundle_path;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
|
||||
@@ -1,662 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
|
||||
use codex_file_system::FileSystemSandboxContext;
|
||||
use codex_network_proxy::ManagedNetworkSandboxContext;
|
||||
use codex_protocol::config_types::ShellEnvironmentPolicyInherit;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ProcessId;
|
||||
|
||||
pub const INITIALIZE_METHOD: &str = "initialize";
|
||||
pub const INITIALIZED_METHOD: &str = "initialized";
|
||||
pub const EXEC_METHOD: &str = "process/start";
|
||||
pub const EXEC_READ_METHOD: &str = "process/read";
|
||||
pub const EXEC_WRITE_METHOD: &str = "process/write";
|
||||
pub const EXEC_SIGNAL_METHOD: &str = "process/signal";
|
||||
pub const EXEC_TERMINATE_METHOD: &str = "process/terminate";
|
||||
pub const EXEC_OUTPUT_DELTA_METHOD: &str = "process/output";
|
||||
pub const EXEC_EXITED_METHOD: &str = "process/exited";
|
||||
pub const EXEC_CLOSED_METHOD: &str = "process/closed";
|
||||
pub const ENVIRONMENT_INFO_METHOD: &str = "environment/info";
|
||||
pub const FS_READ_FILE_METHOD: &str = "fs/readFile";
|
||||
pub(crate) const FS_OPEN_METHOD: &str = "fs/open";
|
||||
pub(crate) const FS_READ_BLOCK_METHOD: &str = "fs/readBlock";
|
||||
pub(crate) const FS_CLOSE_METHOD: &str = "fs/close";
|
||||
pub const FS_WRITE_FILE_METHOD: &str = "fs/writeFile";
|
||||
pub const FS_CREATE_DIRECTORY_METHOD: &str = "fs/createDirectory";
|
||||
pub const FS_GET_METADATA_METHOD: &str = "fs/getMetadata";
|
||||
pub const FS_CANONICALIZE_METHOD: &str = "fs/canonicalize";
|
||||
pub const FS_READ_DIRECTORY_METHOD: &str = "fs/readDirectory";
|
||||
pub const FS_REMOVE_METHOD: &str = "fs/remove";
|
||||
pub const FS_COPY_METHOD: &str = "fs/copy";
|
||||
/// JSON-RPC request method for executor-side HTTP requests.
|
||||
pub const HTTP_REQUEST_METHOD: &str = "http/request";
|
||||
/// JSON-RPC notification method for streamed executor HTTP response bodies.
|
||||
pub const HTTP_REQUEST_BODY_DELTA_METHOD: &str = "http/request/bodyDelta";
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct ByteChunk(#[serde(with = "base64_bytes")] pub Vec<u8>);
|
||||
|
||||
impl ByteChunk {
|
||||
pub fn into_inner(self) -> Vec<u8> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for ByteChunk {
|
||||
fn from(value: Vec<u8>) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct InitializeParams {
|
||||
pub client_name: String,
|
||||
#[serde(default)]
|
||||
pub resume_session_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct InitializeResponse {
|
||||
pub session_id: String,
|
||||
}
|
||||
|
||||
/// Information about an execution/filesystem environment.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EnvironmentInfo {
|
||||
pub shell: ShellInfo,
|
||||
/// Working directory inherited by the exec-server process.
|
||||
#[serde(default)]
|
||||
pub cwd: Option<PathUri>,
|
||||
}
|
||||
|
||||
/// Shell detected for an execution/filesystem environment.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ShellInfo {
|
||||
/// Stable shell name, for example `zsh`, `bash`, `powershell`, `sh`, or `cmd`.
|
||||
pub name: String,
|
||||
/// Target-native shell executable path or command name. Fallbacks such as `cmd.exe` need not
|
||||
/// be absolute, so this is not a [`PathUri`].
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecParams {
|
||||
/// Client-chosen logical process handle scoped to this connection/session.
|
||||
/// This is a protocol key, not an OS pid.
|
||||
pub process_id: ProcessId,
|
||||
pub argv: Vec<String>,
|
||||
/// Working directory URI, interpreted using the exec-server host's path rules at launch time.
|
||||
pub cwd: PathUri,
|
||||
#[serde(default)]
|
||||
pub env_policy: Option<ExecEnvPolicy>,
|
||||
pub env: HashMap<String, String>,
|
||||
pub tty: bool,
|
||||
/// Keep non-tty stdin writable through `process/write`.
|
||||
#[serde(default)]
|
||||
pub pipe_stdin: bool,
|
||||
/// Optional process-visible argv0 override. Values such as `codex-linux-sandbox` are command
|
||||
/// names rather than paths, so this is not a [`PathUri`].
|
||||
pub arg0: Option<String>,
|
||||
/// Portable sandbox intent. Concrete wrapper argv is resolved by the exec-server.
|
||||
#[serde(default)]
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
/// Whether the eventual executor-side sandbox must enforce managed networking.
|
||||
#[serde(default)]
|
||||
pub enforce_managed_network: bool,
|
||||
/// Optional details for enforcing managed networking without a live proxy object.
|
||||
///
|
||||
/// When `enforce_managed_network` is true and these details are absent, the executor must
|
||||
/// continue to fail closed. This preserves compatibility with older clients.
|
||||
#[serde(default)]
|
||||
pub managed_network: Option<ManagedNetworkSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecEnvPolicy {
|
||||
pub inherit: ShellEnvironmentPolicyInherit,
|
||||
pub ignore_default_excludes: bool,
|
||||
pub exclude: Vec<String>,
|
||||
pub r#set: HashMap<String, String>,
|
||||
pub include_only: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecResponse {
|
||||
pub process_id: ProcessId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ReadParams {
|
||||
pub process_id: ProcessId,
|
||||
pub after_seq: Option<u64>,
|
||||
pub max_bytes: Option<usize>,
|
||||
pub wait_ms: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ProcessOutputChunk {
|
||||
pub seq: u64,
|
||||
pub stream: ExecOutputStream,
|
||||
pub chunk: ByteChunk,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ReadResponse {
|
||||
pub chunks: Vec<ProcessOutputChunk>,
|
||||
pub next_seq: u64,
|
||||
pub exited: bool,
|
||||
pub exit_code: Option<i32>,
|
||||
pub closed: bool,
|
||||
pub failure: Option<String>,
|
||||
/// Whether the executor classified the process failure as a sandbox denial.
|
||||
#[serde(default)]
|
||||
pub sandbox_denied: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct WriteParams {
|
||||
pub process_id: ProcessId,
|
||||
pub chunk: ByteChunk,
|
||||
pub write_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum WriteStatus {
|
||||
Accepted,
|
||||
UnknownProcess,
|
||||
StdinClosed,
|
||||
Starting,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct WriteResponse {
|
||||
pub status: WriteStatus,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ProcessSignal {
|
||||
Interrupt,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SignalParams {
|
||||
pub process_id: ProcessId,
|
||||
pub signal: ProcessSignal,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SignalResponse {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TerminateParams {
|
||||
pub process_id: ProcessId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TerminateResponse {
|
||||
pub running: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsReadFileParams {
|
||||
pub path: PathUri,
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsReadFileResponse {
|
||||
pub data_base64: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsOpenParams {
|
||||
pub handle_id: String,
|
||||
pub path: PathUri,
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsOpenResponse {
|
||||
pub handle_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsReadBlockParams {
|
||||
pub handle_id: String,
|
||||
pub offset: u64,
|
||||
pub len: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsReadBlockResponse {
|
||||
pub chunk: ByteChunk,
|
||||
pub eof: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsCloseParams {
|
||||
pub handle_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsCloseResponse {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsWriteFileParams {
|
||||
pub path: PathUri,
|
||||
pub data_base64: String,
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsWriteFileResponse {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsCreateDirectoryParams {
|
||||
pub path: PathUri,
|
||||
pub recursive: Option<bool>,
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsCreateDirectoryResponse {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsGetMetadataParams {
|
||||
pub path: PathUri,
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsGetMetadataResponse {
|
||||
pub is_directory: bool,
|
||||
pub is_file: bool,
|
||||
pub is_symlink: bool,
|
||||
pub size: u64,
|
||||
pub created_at_ms: i64,
|
||||
pub modified_at_ms: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsCanonicalizeParams {
|
||||
pub path: PathUri,
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsCanonicalizeResponse {
|
||||
pub path: PathUri,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsReadDirectoryParams {
|
||||
pub path: PathUri,
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsReadDirectoryEntry {
|
||||
pub file_name: String,
|
||||
pub is_directory: bool,
|
||||
pub is_file: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsReadDirectoryResponse {
|
||||
pub entries: Vec<FsReadDirectoryEntry>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsRemoveParams {
|
||||
pub path: PathUri,
|
||||
pub recursive: Option<bool>,
|
||||
pub force: Option<bool>,
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsRemoveResponse {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsCopyParams {
|
||||
pub source_path: PathUri,
|
||||
pub destination_path: PathUri,
|
||||
pub recursive: bool,
|
||||
pub sandbox: Option<FileSystemSandboxContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FsCopyResponse {}
|
||||
|
||||
/// HTTP header represented in the executor protocol.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HttpHeader {
|
||||
/// Header name as it appears on the HTTP wire.
|
||||
pub name: String,
|
||||
/// Header value after UTF-8 conversion.
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
/// Executor-side HTTP request envelope.
|
||||
///
|
||||
/// This intentionally stays transport-shaped rather than MCP-shaped so callers
|
||||
/// can use it for Streamable HTTP, OAuth discovery, and future executor-owned
|
||||
/// HTTP probes without introducing one protocol method per higher-level use.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HttpRequestParams {
|
||||
/// HTTP method, for example `GET`, `POST`, or `DELETE`.
|
||||
pub method: String,
|
||||
/// Absolute `http://` or `https://` URL.
|
||||
pub url: String,
|
||||
/// Ordered request headers. Repeated header names are preserved.
|
||||
#[serde(default)]
|
||||
pub headers: Vec<HttpHeader>,
|
||||
/// Optional request body bytes.
|
||||
#[serde(default, rename = "bodyBase64")]
|
||||
pub body: Option<ByteChunk>,
|
||||
/// Request timeout in milliseconds.
|
||||
///
|
||||
/// Omitted or `null` disables the timeout. A number applies that exact
|
||||
/// millisecond deadline.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub timeout_ms: Option<u64>,
|
||||
/// Caller-chosen stream id for `http/request/bodyDelta` notifications.
|
||||
///
|
||||
/// The id must remain unique on a connection until the terminal body delta
|
||||
/// arrives, even if the caller stops reading the stream earlier. Buffered
|
||||
/// requests still send an id so callers can keep one consistent request
|
||||
/// envelope shape.
|
||||
pub request_id: String,
|
||||
/// Return after response headers and stream the response body as deltas.
|
||||
#[serde(default)]
|
||||
pub stream_response: bool,
|
||||
}
|
||||
|
||||
/// HTTP response envelope returned from an executor `http/request` call.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HttpRequestResponse {
|
||||
/// Numeric HTTP response status code.
|
||||
pub status: u16,
|
||||
/// Ordered response headers. Repeated header names are preserved.
|
||||
pub headers: Vec<HttpHeader>,
|
||||
/// Buffered response body bytes. Empty when `streamResponse` is true.
|
||||
#[serde(rename = "bodyBase64")]
|
||||
pub body: ByteChunk,
|
||||
}
|
||||
|
||||
/// Ordered response-body frame for `streamResponse` HTTP requests.
|
||||
///
|
||||
/// Headers are returned in the `http/request` response so the caller can choose
|
||||
/// a parser immediately; body bytes then arrive on this notification stream.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HttpRequestBodyDeltaNotification {
|
||||
/// Request id from the streamed `http/request` call.
|
||||
pub request_id: String,
|
||||
/// Monotonic one-based body frame sequence number.
|
||||
pub seq: u64,
|
||||
/// Response-body bytes carried by this frame.
|
||||
#[serde(rename = "deltaBase64")]
|
||||
pub delta: ByteChunk,
|
||||
/// Marks response-body EOF. No later deltas are expected for this request.
|
||||
#[serde(default)]
|
||||
pub done: bool,
|
||||
/// Terminal stream error. Set only on the final notification.
|
||||
#[serde(default)]
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ExecOutputStream {
|
||||
Stdout,
|
||||
Stderr,
|
||||
Pty,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecOutputDeltaNotification {
|
||||
pub process_id: ProcessId,
|
||||
pub seq: u64,
|
||||
pub stream: ExecOutputStream,
|
||||
pub chunk: ByteChunk,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecExitedNotification {
|
||||
pub process_id: ProcessId,
|
||||
pub seq: u64,
|
||||
pub exit_code: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecClosedNotification {
|
||||
pub process_id: ProcessId,
|
||||
pub seq: u64,
|
||||
}
|
||||
|
||||
mod base64_bytes {
|
||||
use super::BASE64_STANDARD;
|
||||
use base64::Engine as _;
|
||||
use serde::Deserialize;
|
||||
use serde::Deserializer;
|
||||
use serde::Serializer;
|
||||
|
||||
pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&BASE64_STANDARD.encode(bytes))
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let encoded = String::deserialize(deserializer)?;
|
||||
BASE64_STANDARD
|
||||
.decode(encoded)
|
||||
.map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::EnvironmentInfo;
|
||||
use super::ExecParams;
|
||||
use super::FsReadFileParams;
|
||||
use super::HttpRequestParams;
|
||||
use super::ProcessId;
|
||||
use super::ShellInfo;
|
||||
use codex_file_system::FileSystemSandboxContext;
|
||||
use codex_network_proxy::ManagedNetworkSandboxContext;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn exec_params_managed_network_context_round_trips_and_defaults_for_legacy_peers() {
|
||||
let cwd =
|
||||
PathUri::from_host_native_path(std::env::current_dir().expect("current directory"))
|
||||
.expect("cwd URI");
|
||||
let params = ExecParams {
|
||||
process_id: ProcessId::from("managed-network"),
|
||||
argv: vec!["true".to_string()],
|
||||
cwd,
|
||||
env_policy: None,
|
||||
env: HashMap::new(),
|
||||
tty: false,
|
||||
pipe_stdin: false,
|
||||
arg0: None,
|
||||
sandbox: None,
|
||||
enforce_managed_network: true,
|
||||
managed_network: Some(ManagedNetworkSandboxContext {
|
||||
loopback_ports: vec![43123, 48081],
|
||||
allow_local_binding: false,
|
||||
}),
|
||||
};
|
||||
|
||||
let mut serialized = serde_json::to_value(¶ms).expect("serialize exec params");
|
||||
assert_eq!(
|
||||
serialized["managedNetwork"],
|
||||
serde_json::json!({
|
||||
"loopbackPorts": [43123, 48081],
|
||||
"allowLocalBinding": false,
|
||||
})
|
||||
);
|
||||
let round_trip: ExecParams =
|
||||
serde_json::from_value(serialized.clone()).expect("deserialize exec params");
|
||||
assert_eq!(round_trip, params);
|
||||
|
||||
serialized
|
||||
.as_object_mut()
|
||||
.expect("exec params object")
|
||||
.remove("managedNetwork");
|
||||
let legacy: ExecParams =
|
||||
serde_json::from_value(serialized).expect("deserialize legacy exec params");
|
||||
assert!(legacy.enforce_managed_network);
|
||||
assert_eq!(legacy.managed_network, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn environment_info_accepts_legacy_response_without_cwd() {
|
||||
let info: EnvironmentInfo = serde_json::from_value(serde_json::json!({
|
||||
"shell": { "name": "zsh", "path": "/bin/zsh" }
|
||||
}))
|
||||
.expect("legacy environment info should deserialize");
|
||||
|
||||
assert_eq!(
|
||||
info,
|
||||
EnvironmentInfo {
|
||||
shell: ShellInfo {
|
||||
name: "zsh".to_string(),
|
||||
path: "/bin/zsh".to_string(),
|
||||
},
|
||||
cwd: None,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filesystem_protocol_rejects_native_absolute_paths() {
|
||||
let native_path = std::env::current_dir()
|
||||
.expect("current directory")
|
||||
.join("native-file.txt");
|
||||
let native_cwd = std::env::current_dir().expect("current directory");
|
||||
|
||||
serde_json::from_value::<FsReadFileParams>(serde_json::json!({
|
||||
"path": native_path.to_string_lossy(),
|
||||
"sandbox": null,
|
||||
}))
|
||||
.expect_err("native absolute path should not deserialize as a URI");
|
||||
|
||||
let sandbox = FileSystemSandboxContext::from_permission_profile_with_cwd(
|
||||
PermissionProfile::default(),
|
||||
PathUri::from_host_native_path(&native_cwd).expect("cwd URI"),
|
||||
);
|
||||
let mut native_path_sandbox =
|
||||
serde_json::to_value(sandbox).expect("sandbox should serialize");
|
||||
native_path_sandbox["cwd"] = serde_json::json!(native_cwd.to_string_lossy());
|
||||
|
||||
serde_json::from_value::<FsReadFileParams>(serde_json::json!({
|
||||
"path": PathUri::from_host_native_path(native_path)
|
||||
.expect("path URI")
|
||||
.to_string(),
|
||||
"sandbox": native_path_sandbox,
|
||||
}))
|
||||
.expect_err("native absolute sandbox cwd should not deserialize as a URI");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn http_request_timeout_treats_omitted_and_null_as_no_timeout() {
|
||||
let omitted: HttpRequestParams = serde_json::from_value(serde_json::json!({
|
||||
"method": "GET",
|
||||
"url": "https://example.test",
|
||||
"requestId": "req-omitted-timeout",
|
||||
}))
|
||||
.expect("omitted timeout should deserialize");
|
||||
let null_timeout: HttpRequestParams = serde_json::from_value(serde_json::json!({
|
||||
"method": "GET",
|
||||
"url": "https://example.test",
|
||||
"requestId": "req-null-timeout",
|
||||
"timeoutMs": null,
|
||||
}))
|
||||
.expect("null timeout should deserialize");
|
||||
let explicit_timeout: HttpRequestParams = serde_json::from_value(serde_json::json!({
|
||||
"method": "GET",
|
||||
"url": "https://example.test",
|
||||
"requestId": "req-explicit-timeout",
|
||||
"timeoutMs": 1234,
|
||||
}))
|
||||
.expect("numeric timeout should deserialize");
|
||||
|
||||
assert_eq!(
|
||||
(omitted.request_id.as_str(), omitted.timeout_ms),
|
||||
("req-omitted-timeout", None)
|
||||
);
|
||||
assert_eq!(
|
||||
(null_timeout.request_id.as_str(), null_timeout.timeout_ms),
|
||||
("req-null-timeout", None)
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
explicit_timeout.request_id.as_str(),
|
||||
explicit_timeout.timeout_ms
|
||||
),
|
||||
("req-explicit-timeout", Some(1234))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use futures::Sink;
|
||||
use futures::SinkExt;
|
||||
use futures::Stream;
|
||||
@@ -847,8 +847,8 @@ mod tests {
|
||||
use std::task::Poll;
|
||||
use std::time::Duration;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCRequest;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_exec_server_protocol::JSONRPCRequest;
|
||||
use codex_exec_server_protocol::RequestId;
|
||||
use futures::Sink;
|
||||
use futures::Stream;
|
||||
use futures::channel::mpsc as futures_mpsc;
|
||||
@@ -1101,7 +1101,6 @@ mod tests {
|
||||
id: RequestId::Integer(1),
|
||||
method: "test".to_string(),
|
||||
params: None,
|
||||
trace: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![allow(clippy::expect_used)]
|
||||
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCResponse;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::permissions::FileSystemAccessMode;
|
||||
use codex_protocol::permissions::FileSystemPath;
|
||||
|
||||
@@ -6,13 +6,13 @@ use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicI64;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCError;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_app_server_protocol::JSONRPCNotification;
|
||||
use codex_app_server_protocol::JSONRPCRequest;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_exec_server_protocol::JSONRPCError;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCNotification;
|
||||
use codex_exec_server_protocol::JSONRPCRequest;
|
||||
use codex_exec_server_protocol::JSONRPCResponse;
|
||||
use codex_exec_server_protocol::RequestId;
|
||||
use serde::Serialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde_json::Value;
|
||||
@@ -362,7 +362,6 @@ impl RpcClient {
|
||||
id: request_id.clone(),
|
||||
method: method.to_string(),
|
||||
params: Some(params),
|
||||
trace: None,
|
||||
}))
|
||||
.await
|
||||
.is_err()
|
||||
@@ -552,8 +551,8 @@ async fn drain_pending(pending: &Mutex<HashMap<RequestId, PendingRequest>>) {
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCResponse;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tokio::io::AsyncBufReadExt;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use base64::Engine as _;
|
||||
use base64::engine::general_purpose::STANDARD;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use tokio::io;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::io;
|
||||
|
||||
use base64::Engine as _;
|
||||
use base64::engine::general_purpose::STANDARD;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
|
||||
use crate::CopyOptions;
|
||||
use crate::CreateDirectoryOptions;
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::sync::Mutex as StdMutex;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::RequestId;
|
||||
use serde_json::to_value;
|
||||
use std::collections::HashSet;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
|
||||
use crate::ExecServerRuntimePaths;
|
||||
use crate::local_process::LocalProcess;
|
||||
|
||||
@@ -89,7 +89,7 @@ async fn run_connection(
|
||||
warn!("ignoring malformed exec-server message: {reason}");
|
||||
if outgoing_tx
|
||||
.send(RpcServerOutboundMessage::Error {
|
||||
request_id: codex_app_server_protocol::RequestId::Integer(-1),
|
||||
request_id: codex_exec_server_protocol::RequestId::Integer(-1),
|
||||
error: invalid_request(reason),
|
||||
})
|
||||
.await
|
||||
@@ -99,7 +99,7 @@ async fn run_connection(
|
||||
}
|
||||
}
|
||||
JsonRpcConnectionEvent::Message(message) => match message {
|
||||
codex_app_server_protocol::JSONRPCMessage::Request(request) => {
|
||||
codex_exec_server_protocol::JSONRPCMessage::Request(request) => {
|
||||
if let Some(route) = router.request_route(request.method.as_str()) {
|
||||
let message = tokio::select! {
|
||||
message = route(Arc::clone(&handler), request) => message,
|
||||
@@ -127,7 +127,7 @@ async fn run_connection(
|
||||
break;
|
||||
}
|
||||
}
|
||||
codex_app_server_protocol::JSONRPCMessage::Notification(notification) => {
|
||||
codex_exec_server_protocol::JSONRPCMessage::Notification(notification) => {
|
||||
let Some(route) = router.notification_route(notification.method.as_str())
|
||||
else {
|
||||
warn!(
|
||||
@@ -150,14 +150,14 @@ async fn run_connection(
|
||||
break;
|
||||
}
|
||||
}
|
||||
codex_app_server_protocol::JSONRPCMessage::Response(response) => {
|
||||
codex_exec_server_protocol::JSONRPCMessage::Response(response) => {
|
||||
warn!(
|
||||
"closing exec-server connection after unexpected client response: {:?}",
|
||||
response.id
|
||||
);
|
||||
break;
|
||||
}
|
||||
codex_app_server_protocol::JSONRPCMessage::Error(error) => {
|
||||
codex_exec_server_protocol::JSONRPCMessage::Error(error) => {
|
||||
warn!(
|
||||
"closing exec-server connection after unexpected client error: {:?}",
|
||||
error.id
|
||||
@@ -190,11 +190,11 @@ mod tests {
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_app_server_protocol::JSONRPCNotification;
|
||||
use codex_app_server_protocol::JSONRPCRequest;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCNotification;
|
||||
use codex_exec_server_protocol::JSONRPCRequest;
|
||||
use codex_exec_server_protocol::JSONRPCResponse;
|
||||
use codex_exec_server_protocol::RequestId;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde::Serialize;
|
||||
@@ -382,7 +382,6 @@ mod tests {
|
||||
id: RequestId::Integer(id),
|
||||
method: method.to_string(),
|
||||
params: Some(serde_json::to_value(params).expect("serialize params")),
|
||||
trace: None,
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||
use std::sync::Mutex as StdMutex;
|
||||
use std::time::Duration;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_exec_server_protocol::JSONRPCErrorError;
|
||||
use tokio::sync::Mutex;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::net::SocketAddr;
|
||||
use std::time::Duration;
|
||||
|
||||
use codex_app_server_protocol::JSONRPCMessage;
|
||||
use codex_app_server_protocol::JSONRPCNotification;
|
||||
use codex_app_server_protocol::JSONRPCRequest;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_exec_server_protocol::JSONRPCMessage;
|
||||
use codex_exec_server_protocol::JSONRPCNotification;
|
||||
use codex_exec_server_protocol::JSONRPCRequest;
|
||||
use codex_exec_server_protocol::JSONRPCResponse;
|
||||
use codex_exec_server_protocol::RequestId;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tokio::io::AsyncBufReadExt;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
@@ -74,7 +74,6 @@ async fn stdio_listen_transport_serves_initialize() {
|
||||
})
|
||||
.expect("initialize params should serialize"),
|
||||
),
|
||||
trace: None,
|
||||
});
|
||||
write_jsonrpc_line(&mut client_writer, &initialize).await;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user