add multi-host ssh exec registry

This commit is contained in:
Nathan Liebrecht
2026-04-10 11:26:59 -07:00
parent 87328976f6
commit 6a44fb6309
14 changed files with 988 additions and 102 deletions
+29 -1
View File
@@ -5,10 +5,13 @@ use std::time::Duration;
use arc_swap::ArcSwap;
use codex_app_server_protocol::JSONRPCNotification;
use serde_json::Value;
use tokio::io::AsyncRead;
use tokio::io::AsyncWrite;
use tokio::sync::Mutex;
use tokio::sync::watch;
use tokio::time::timeout;
use tokio_tungstenite::client_async;
use tokio_tungstenite::connect_async;
use tracing::debug;
@@ -187,6 +190,31 @@ impl ExecServerClient {
.await
}
pub async fn connect_websocket_stream<S>(
websocket_url: String,
stream: S,
options: ExecServerClientConnectOptions,
) -> Result<Self, ExecServerError>
where
S: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
let (stream, _) = client_async(websocket_url.as_str(), stream)
.await
.map_err(|source| ExecServerError::WebSocketConnect {
url: websocket_url.clone(),
source,
})?;
Self::connect(
JsonRpcConnection::from_websocket(
stream,
format!("exec-server websocket stream {websocket_url}"),
),
options,
)
.await
}
pub async fn initialize(
&self,
options: ExecServerClientConnectOptions,
@@ -209,7 +237,7 @@ impl ExecServerClient {
},
)
.await?;
{
if !response.session_id.is_empty() {
let mut session_id = self
.inner
.session_id
File diff suppressed because it is too large Load Diff
+6
View File
@@ -17,9 +17,15 @@ pub use client::ExecServerClient;
pub use client::ExecServerError;
pub use client_api::ExecServerClientConnectOptions;
pub use client_api::RemoteExecServerConnectArgs;
pub use environment::CODEX_EXEC_SERVER_DEFAULT_HOST_ENV_VAR;
pub use environment::CODEX_EXEC_SERVER_SSH_HOSTS_ENV_VAR;
pub use environment::CODEX_EXEC_SERVER_URL_ENV_VAR;
pub use environment::DEFAULT_HOST_ALIAS;
pub use environment::Environment;
pub use environment::EnvironmentManager;
pub use environment::HostConfig;
pub use environment::HostConnection;
pub use environment::LOCAL_HOST_ID;
pub use file_system::CopyOptions;
pub use file_system::CreateDirectoryOptions;
pub use file_system::ExecutorFileSystem;
+13
View File
@@ -53,6 +53,7 @@ pub struct InitializeParams {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct InitializeResponse {
#[serde(default, alias = "session_id")]
pub session_id: String,
}
@@ -293,3 +294,15 @@ mod base64_bytes {
.map_err(serde::de::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::InitializeResponse;
#[test]
fn initialize_response_accepts_legacy_empty_payload() {
let response: InitializeResponse =
serde_json::from_str("{}").expect("legacy initialize response should deserialize");
assert!(response.session_id.is_empty());
}
}