mirror of
https://github.com/openai/codex.git
synced 2026-10-20 00:18:49 +00:00
Preserve the remote cwd filter in the in-app resume picker (#53728)
## Why Opening the in-app resume picker created a new app-server session without the active session's remote working directory override, dropping the remote directory filter from the thread list. ## What changed Pass the active session's remote working directory override to the picker session so its `thread/list` request retains the `cwd` filter. ## Testing Add a regression test that opens the in-app picker against a recording remote server and verifies that `thread/list` includes the remote working directory in `cwd`. GitOrigin-RevId: 0073ed77e9d9b0ffdd647fcb9f157d20ea2aa599
This commit is contained in:
@@ -41,6 +41,8 @@ impl App {
|
||||
return Ok(AppRunControl::Continue);
|
||||
}
|
||||
};
|
||||
picker_app_server = picker_app_server
|
||||
.with_remote_cwd_override(app_server.remote_cwd_override().map(Path::to_path_buf));
|
||||
picker_app_server.model_provider_override = self.harness_overrides.model_provider.clone();
|
||||
let selection =
|
||||
crate::resume_picker::run_resume_picker_from_existing_session_with_app_server(
|
||||
|
||||
@@ -926,6 +926,89 @@ async fn make_history_test_app() -> Result<(Box<App>, tempfile::TempDir)> {
|
||||
Ok((app, codex_home))
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn in_app_remote_resume_picker_preserves_remote_cwd_filter() -> Result<()> {
|
||||
let (mut app, _codex_home) = make_history_test_app().await?;
|
||||
let remote_root = tempdir()?;
|
||||
let remote_cwd = remote_root.path().join("project");
|
||||
std::fs::create_dir(&remote_cwd)?;
|
||||
let (app_server, _requests, active_proxy) =
|
||||
start_recording_remote_app_server(&app.config).await?;
|
||||
let mut app_server = app_server.with_remote_cwd_override(Some(remote_cwd.clone()));
|
||||
app.harness_overrides.model_provider = Some(app.config.model_provider_id.clone());
|
||||
|
||||
let listener = TcpListener::bind("127.0.0.1:0").await?;
|
||||
app.app_server_target = AppServerTarget::Remote {
|
||||
endpoint: crate::resolve_remote_addr(&format!("ws://{}", listener.local_addr()?))?,
|
||||
};
|
||||
let (request_tx, request_rx) = oneshot::channel();
|
||||
let (release_tx, release_rx) = oneshot::channel::<()>();
|
||||
let codex_home = app.config.codex_home.display().to_string();
|
||||
let recorder = tokio::spawn(async move {
|
||||
let (socket, _) = listener.accept().await?;
|
||||
let mut websocket = accept_async(socket).await?;
|
||||
while let Some(frame) = websocket.next().await {
|
||||
let Message::Text(text) = frame? else {
|
||||
continue;
|
||||
};
|
||||
match serde_json::from_str::<JSONRPCMessage>(&text)? {
|
||||
JSONRPCMessage::Request(request) if request.method == "initialize" => {
|
||||
let response = JSONRPCMessage::Response(JSONRPCResponse {
|
||||
id: request.id,
|
||||
result: serde_json::json!({
|
||||
"userAgent": "codex-tui-test",
|
||||
"codexHome": codex_home,
|
||||
}),
|
||||
});
|
||||
websocket
|
||||
.send(Message::Text(serde_json::to_string(&response)?.into()))
|
||||
.await?;
|
||||
}
|
||||
JSONRPCMessage::Request(request) if request.method == "thread/list" => {
|
||||
let _ = request_tx.send(request.params.unwrap_or_default());
|
||||
let _ = release_rx.await;
|
||||
return Ok::<(), color_eyre::Report>(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Err(color_eyre::eyre::eyre!(
|
||||
"picker disconnected before requesting its thread list"
|
||||
))
|
||||
});
|
||||
|
||||
let mut tui = crate::tui::test_support::make_test_tui()?;
|
||||
tui.set_alt_screen_enabled(/*enabled*/ false);
|
||||
tui.pause_events();
|
||||
let mut picker = Box::pin(app.open_resume_picker(&mut tui, &mut app_server));
|
||||
let params = tokio::time::timeout(std::time::Duration::from_secs(/*secs*/ 5), async {
|
||||
tokio::select! {
|
||||
biased;
|
||||
params = request_rx => params.map_err(|_| {
|
||||
color_eyre::eyre::eyre!("picker request recorder closed")
|
||||
}),
|
||||
result = &mut picker => {
|
||||
result?;
|
||||
Err(color_eyre::eyre::eyre!(
|
||||
"picker exited before requesting its thread list"
|
||||
))
|
||||
}
|
||||
}
|
||||
})
|
||||
.await??;
|
||||
drop(picker);
|
||||
let _ = release_tx.send(());
|
||||
recorder.await??;
|
||||
app_server.shutdown().await?;
|
||||
active_proxy.await??;
|
||||
|
||||
assert_eq!(
|
||||
params["cwd"],
|
||||
serde_json::Value::String(remote_cwd.display().to_string())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn delete_current_thread_navigates_only_after_success() -> Result<()> {
|
||||
let endpoint = crate::resolve_remote_addr("ws://127.0.0.1:4500")?;
|
||||
|
||||
Reference in New Issue
Block a user