chore: merge name and title (#17116)

Merge title and name concept to leverage the sqlite title column and
have more efficient queries

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
jif-oai
2026-04-09 18:44:26 +01:00
committed by GitHub
parent c0b5d8d24a
commit 12f0e0b0eb
16 changed files with 539 additions and 145 deletions

View File

@@ -33,6 +33,7 @@ use codex_core::config_loader::CloudRequirementsLoader;
use codex_core::config_loader::ConfigLoadError;
use codex_core::config_loader::LoaderOverrides;
use codex_core::config_loader::format_config_error_with_source;
use codex_core::find_thread_meta_by_name_str;
use codex_core::format_exec_policy_error_with_source;
use codex_core::path_utils;
use codex_core::read_session_meta_line;
@@ -492,6 +493,7 @@ fn session_target_from_app_server_thread(
async fn lookup_session_target_by_name_with_app_server(
app_server: &mut AppServerSession,
codex_home: &Path,
name: &str,
) -> color_eyre::Result<Option<resume_picker::SessionTarget>> {
let mut cursor = None;
@@ -505,10 +507,7 @@ async fn lookup_session_target_by_name_with_app_server(
source_kinds: Some(vec![ThreadSourceKind::Cli, ThreadSourceKind::VsCode]),
archived: Some(false),
cwd: None,
// 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,
search_term: Some(name.to_string()),
})
.await?;
if let Some(thread) = response
@@ -519,7 +518,15 @@ async fn lookup_session_target_by_name_with_app_server(
return Ok(session_target_from_app_server_thread(thread));
}
if response.next_cursor.is_none() {
return Ok(None);
if app_server.is_remote() {
return Ok(None);
}
return Ok(find_thread_meta_by_name_str(codex_home, name).await?.map(
|(path, session_meta)| resume_picker::SessionTarget {
path: Some(path),
thread_id: session_meta.meta.id,
},
));
}
cursor = response.next_cursor;
}
@@ -527,6 +534,7 @@ async fn lookup_session_target_by_name_with_app_server(
async fn lookup_session_target_with_app_server(
app_server: &mut AppServerSession,
codex_home: &Path,
id_or_name: &str,
) -> color_eyre::Result<Option<resume_picker::SessionTarget>> {
if Uuid::parse_str(id_or_name).is_ok() {
@@ -557,7 +565,7 @@ async fn lookup_session_target_with_app_server(
};
}
lookup_session_target_by_name_with_app_server(app_server, id_or_name).await
lookup_session_target_by_name_with_app_server(app_server, codex_home, id_or_name).await
}
async fn lookup_latest_session_target_with_app_server(
@@ -1163,7 +1171,13 @@ async fn run_ratatui_app(
let Some(startup_app_server) = app_server.as_mut() else {
unreachable!("app server should be initialized for --fork <id>");
};
match lookup_session_target_with_app_server(startup_app_server, id_str).await? {
match lookup_session_target_with_app_server(
startup_app_server,
config.codex_home.as_path(),
id_str,
)
.await?
{
Some(target_session) => resume_picker::SessionSelection::Fork(target_session),
None => {
shutdown_app_server_if_present(app_server.take()).await;
@@ -1224,7 +1238,13 @@ async fn run_ratatui_app(
let Some(startup_app_server) = app_server.as_mut() else {
unreachable!("app server should be initialized for --resume <id>");
};
match lookup_session_target_with_app_server(startup_app_server, id_str).await? {
match lookup_session_target_with_app_server(
startup_app_server,
config.codex_home.as_path(),
id_str,
)
.await?
{
Some(target_session) => resume_picker::SessionSelection::Resume(target_session),
None => {
shutdown_app_server_if_present(app_server.take()).await;
@@ -1997,8 +2017,7 @@ mod tests {
}
#[tokio::test]
async fn lookup_session_target_by_name_ignores_backend_search_term_mismatch()
-> color_eyre::Result<()> {
async fn lookup_session_target_by_name_uses_backend_title_search() -> color_eyre::Result<()> {
let temp_dir = TempDir::new()?;
let config = build_config(&temp_dir).await?;
let thread_id = ThreadId::new();
@@ -2034,22 +2053,76 @@ mod tests {
);
builder.cwd = session_cwd;
let mut metadata = builder.build(config.model_provider_id.as_str());
metadata.title = "Different rollout title".to_string();
metadata.title = "saved-session".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,
temp_dir.path(),
"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 lookup_session_target_by_name_falls_back_to_legacy_index() -> 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"));
std::fs::create_dir_all(rollout_path.parent().expect("rollout parent"))?;
let session_meta = SessionMeta {
id: thread_id,
timestamp: "2025-02-01T10:00:00Z".to_string(),
model_provider: Some(config.model_provider_id.clone()),
..SessionMeta::default()
};
let line = RolloutLine {
timestamp: session_meta.timestamp.clone(),
item: RolloutItem::SessionMeta(SessionMetaLine {
meta: session_meta,
git: None,
}),
};
std::fs::write(
&rollout_path,
format!("{}\n", serde_json::to_string(&line)?),
)?;
std::fs::write(
temp_dir.path().join("session_index.jsonl"),
format!(
"{{\"id\":\"{thread_id}\",\"thread_name\":\"hello\",\"updated_at\":\"2025-02-02T10:00:00Z\"}}\n"
),
)?;
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");
let target = lookup_session_target_by_name_with_app_server(
&mut app_server,
temp_dir.path(),
"hello",
)
.await?;
let target = target.expect("legacy name lookup should find the saved thread");
assert_eq!(target.path, Some(rollout_path));
assert_eq!(target.thread_id, thread_id);