mirror of
https://github.com/openai/codex.git
synced 2026-05-01 03:42:05 +03:00
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:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user