Fix remote goal file materialization

This commit is contained in:
Eric Traut
2026-06-10 12:26:34 -07:00
parent 2c4dfc0dec
commit 77cf2eeea4
7 changed files with 136 additions and 11 deletions
+17
View File
@@ -53,6 +53,7 @@ pub use codex_exec_server::EnvironmentManager;
pub use codex_exec_server::ExecServerRuntimePaths;
use codex_feedback::CodexFeedback;
use codex_protocol::protocol::SessionSource;
use codex_utils_absolute_path::AbsolutePathBuf;
use serde::de::DeserializeOwned;
use tokio::sync::mpsc;
use tokio::sync::oneshot;
@@ -899,6 +900,13 @@ impl AppServerClient {
}
}
pub fn remote_codex_home(&self) -> Option<&AbsolutePathBuf> {
match self {
Self::InProcess(_) => None,
Self::Remote(client) => client.codex_home(),
}
}
pub fn request_handle(&self) -> AppServerRequestHandle {
match self {
Self::InProcess(client) => AppServerRequestHandle::InProcess(client.request_handle()),
@@ -1104,6 +1112,9 @@ mod tests {
id: request.id,
result: serde_json::json!({
"userAgent": "codex_cli_rs/9.8.7-test (Test OS; x86_64) rust",
"codexHome": test_remote_codex_home().display().to_string(),
"platformFamily": "unix",
"platformOs": "linux",
}),
}),
)
@@ -1116,6 +1127,11 @@ mod tests {
assert_eq!(notification.method, "initialized");
}
fn test_remote_codex_home() -> AbsolutePathBuf {
AbsolutePathBuf::from_absolute_path(std::env::temp_dir().join("codex-remote-home"))
.expect("test remote codex home should be absolute")
}
async fn read_websocket_message<S>(
websocket: &mut tokio_tungstenite::WebSocketStream<S>,
) -> JSONRPCMessage
@@ -1440,6 +1456,7 @@ mod tests {
.expect("remote client should connect");
assert_eq!(client.server_version(), Some("9.8.7-test"));
assert_eq!(client.codex_home(), Some(&test_remote_codex_home()));
let response: GetAccountResponse = client
.request_typed(ClientRequest::GetAccount {
request_id: RequestId::Integer(1),
+25 -6
View File
@@ -151,9 +151,16 @@ pub struct RemoteAppServerClient {
event_rx: mpsc::UnboundedReceiver<AppServerEvent>,
pending_events: VecDeque<AppServerEvent>,
server_version: Option<String>,
codex_home: Option<AbsolutePathBuf>,
worker_handle: tokio::task::JoinHandle<()>,
}
#[derive(Debug, Default)]
struct RemoteInitializeInfo {
server_version: Option<String>,
codex_home: Option<AbsolutePathBuf>,
}
#[derive(Clone)]
pub struct RemoteAppServerRequestHandle {
command_tx: mpsc::Sender<RemoteClientCommand>,
@@ -185,6 +192,10 @@ impl RemoteAppServerClient {
self.server_version.as_deref()
}
pub fn codex_home(&self) -> Option<&AbsolutePathBuf> {
self.codex_home.as_ref()
}
async fn connect_with_stream<S>(
channel_capacity: usize,
endpoint: String,
@@ -195,7 +206,7 @@ impl RemoteAppServerClient {
S: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
let mut stream = stream;
let (pending_events, server_version) = initialize_remote_connection(
let (pending_events, initialize_info) = initialize_remote_connection(
&mut stream,
&endpoint,
initialize_params,
@@ -471,7 +482,8 @@ impl RemoteAppServerClient {
command_tx,
event_rx,
pending_events: pending_events.into(),
server_version,
server_version: initialize_info.server_version,
codex_home: initialize_info.codex_home,
worker_handle,
})
}
@@ -613,6 +625,7 @@ impl RemoteAppServerClient {
event_rx,
pending_events: _pending_events,
server_version: _server_version,
codex_home: _codex_home,
worker_handle,
} = self;
let mut worker_handle = worker_handle;
@@ -800,13 +813,13 @@ async fn initialize_remote_connection<S>(
endpoint: &str,
params: InitializeParams,
initialize_timeout: Duration,
) -> IoResult<(Vec<AppServerEvent>, Option<String>)>
) -> IoResult<(Vec<AppServerEvent>, RemoteInitializeInfo)>
where
S: AsyncRead + AsyncWrite + Unpin,
{
let initialize_request_id = RequestId::String("initialize".to_string());
let mut pending_events = Vec::new();
let mut server_version = None;
let mut initialize_info = RemoteInitializeInfo::default();
write_jsonrpc_message(
stream,
JSONRPCMessage::Request(jsonrpc_request_from_client_request(
@@ -830,7 +843,7 @@ where
})?;
match message {
JSONRPCMessage::Response(response) if response.id == initialize_request_id => {
server_version = response
initialize_info.server_version = response
.result
.get("userAgent")
.and_then(serde_json::Value::as_str)
@@ -838,6 +851,11 @@ where
let (_, rest) = user_agent.split_once('/')?;
rest.split_whitespace().next().map(str::to_string)
});
initialize_info.codex_home = response
.result
.get("codexHome")
.cloned()
.and_then(|value| serde_json::from_value(value).ok());
break Ok(());
}
JSONRPCMessage::Error(error) if error.id == initialize_request_id => {
@@ -929,7 +947,7 @@ where
)
.await?;
Ok((pending_events, server_version))
Ok((pending_events, initialize_info))
}
fn app_server_event_from_notification(notification: JSONRPCNotification) -> Option<AppServerEvent> {
@@ -1024,6 +1042,7 @@ mod tests {
event_rx,
pending_events: VecDeque::new(),
server_version: None,
codex_home: None,
worker_handle,
};