mirror of
https://github.com/openai/codex.git
synced 2026-04-24 06:35:50 +00:00
Fix tui_app_server resume-by-name lookup regression (#16050)
Addresses #16049 `codex resume <name>` and `/resume <name>` could fail in the app-server TUI path because name lookup pre-filtered `thread/list` with the backend `search_term`, but saved thread names are hydrated after listing and are not part of that search index. Resolve names by scanning listed threads client-side instead, and add a regression test for saved sessions whose rollout title does not match the thread name.
This commit is contained in:
@@ -520,7 +520,10 @@ async fn lookup_session_target_by_name_with_app_server(
|
||||
source_kinds: Some(vec![ThreadSourceKind::Cli, ThreadSourceKind::VsCode]),
|
||||
archived: Some(false),
|
||||
cwd: None,
|
||||
search_term: Some(name.to_string()),
|
||||
// Thread names are hydrated after `thread/list` resolves rollout metadata, so
|
||||
// name-based resume must scan the filtered list client-side instead of relying on
|
||||
// the backend search index.
|
||||
search_term: None,
|
||||
})
|
||||
.await?;
|
||||
if let Some(thread) = response
|
||||
@@ -1890,6 +1893,67 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn lookup_session_target_by_name_ignores_backend_search_term_mismatch()
|
||||
-> color_eyre::Result<()> {
|
||||
let temp_dir = TempDir::new()?;
|
||||
let config = build_config(&temp_dir).await?;
|
||||
let thread_id = ThreadId::new();
|
||||
let rollout_path = temp_dir
|
||||
.path()
|
||||
.join("sessions/2025/02/01")
|
||||
.join(format!("rollout-2025-02-01T10-00-00-{thread_id}.jsonl"));
|
||||
let rollout_dir = rollout_path.parent().expect("rollout parent");
|
||||
std::fs::create_dir_all(rollout_dir)?;
|
||||
std::fs::write(&rollout_path, "")?;
|
||||
|
||||
let state_runtime = codex_state::StateRuntime::init(
|
||||
config.codex_home.clone(),
|
||||
config.model_provider_id.clone(),
|
||||
)
|
||||
.await
|
||||
.map_err(std::io::Error::other)?;
|
||||
state_runtime
|
||||
.mark_backfill_complete(None)
|
||||
.await
|
||||
.map_err(std::io::Error::other)?;
|
||||
|
||||
let session_cwd = temp_dir.path().join("project");
|
||||
std::fs::create_dir_all(&session_cwd)?;
|
||||
let created_at = chrono::DateTime::parse_from_rfc3339("2025-02-01T10:00:00Z")
|
||||
.expect("timestamp should parse")
|
||||
.with_timezone(&chrono::Utc);
|
||||
let mut builder = codex_state::ThreadMetadataBuilder::new(
|
||||
thread_id,
|
||||
rollout_path.clone(),
|
||||
created_at,
|
||||
SessionSource::Cli,
|
||||
);
|
||||
builder.cwd = session_cwd;
|
||||
let mut metadata = builder.build(config.model_provider_id.as_str());
|
||||
metadata.title = "Different rollout title".to_string();
|
||||
metadata.first_user_message = Some("preview text".to_string());
|
||||
state_runtime
|
||||
.upsert_thread(&metadata)
|
||||
.await
|
||||
.map_err(std::io::Error::other)?;
|
||||
|
||||
codex_core::append_thread_name(&config.codex_home, thread_id, "saved-session").await?;
|
||||
|
||||
let mut app_server =
|
||||
AppServerSession::new(codex_app_server_client::AppServerClient::InProcess(
|
||||
start_test_embedded_app_server(config).await?,
|
||||
));
|
||||
let target =
|
||||
lookup_session_target_by_name_with_app_server(&mut app_server, "saved-session").await?;
|
||||
let target = target.expect("name lookup should find the saved thread");
|
||||
assert_eq!(target.path, Some(rollout_path));
|
||||
assert_eq!(target.thread_id, thread_id);
|
||||
|
||||
app_server.shutdown().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn embedded_app_server_start_failure_is_returned() -> color_eyre::Result<()> {
|
||||
let temp_dir = TempDir::new()?;
|
||||
|
||||
Reference in New Issue
Block a user