From e661af17eb66a355ad8e94d34f60575c1521e969 Mon Sep 17 00:00:00 2001 From: Tom Wiltzius Date: Tue, 5 May 2026 16:03:35 -0700 Subject: [PATCH] Move thread names through ThreadStore --- codex-rs/app-server/src/request_processors.rs | 1 - .../request_processors/thread_processor.rs | 46 +++++-------------- codex-rs/core/src/session/mod.rs | 39 ++++++++++------ codex-rs/core/src/session/session.rs | 6 ++- 4 files changed, 41 insertions(+), 51 deletions(-) diff --git a/codex-rs/app-server/src/request_processors.rs b/codex-rs/app-server/src/request_processors.rs index be6d5598662..27cbb5cb33f 100644 --- a/codex-rs/app-server/src/request_processors.rs +++ b/codex-rs/app-server/src/request_processors.rs @@ -266,7 +266,6 @@ use codex_core::exec::ExecCapturePolicy; use codex_core::exec::ExecExpiration; use codex_core::exec::ExecParams; use codex_core::exec_env::create_env; -use codex_core::find_thread_name_by_id; use codex_core::find_thread_path_by_id_str; use codex_core::path_utils; #[cfg(test)] diff --git a/codex-rs/app-server/src/request_processors/thread_processor.rs b/codex-rs/app-server/src/request_processors/thread_processor.rs index 321d1703dcd..c78b2fc88aa 100644 --- a/codex-rs/app-server/src/request_processors/thread_processor.rs +++ b/codex-rs/app-server/src/request_processors/thread_processor.rs @@ -2849,10 +2849,19 @@ impl ThreadRequestProcessor { } async fn attach_thread_name(&self, thread_id: ThreadId, thread: &mut Thread) { - if let Some(title) = - title_from_state_db(&self.config, self.state_db.as_ref(), thread_id).await + if let Ok(stored_thread) = self + .thread_store + .read_thread(StoreReadThreadParams { + thread_id, + include_archived: true, + include_history: false, + }) + .await + && let Some(title) = stored_thread.name.as_deref().map(str::trim) + && !title.is_empty() + && stored_thread.preview.trim() != title { - set_thread_name_from_title(thread, title); + set_thread_name_from_title(thread, title.to_string()); } } @@ -3555,37 +3564,6 @@ fn thread_store_archive_error(operation: &str, err: ThreadStoreError) -> JSONRPC } } -async fn title_from_state_db( - config: &Config, - state_db_ctx: Option<&StateDbHandle>, - thread_id: ThreadId, -) -> Option { - if let Some(state_db_ctx) = state_db_ctx - && let Some(metadata) = state_db_ctx.get_thread(thread_id).await.ok().flatten() - && let Some(title) = distinct_title(&metadata) - { - return Some(title); - } - find_thread_name_by_id(&config.codex_home, &thread_id) - .await - .ok() - .flatten() -} - -fn non_empty_title(metadata: &ThreadMetadata) -> Option { - let title = metadata.title.trim(); - (!title.is_empty()).then(|| title.to_string()) -} - -fn distinct_title(metadata: &ThreadMetadata) -> Option { - let title = non_empty_title(metadata)?; - if metadata.first_user_message.as_deref().map(str::trim) == Some(title.as_str()) { - None - } else { - Some(title) - } -} - fn set_thread_name_from_title(thread: &mut Thread, title: String) { if title.trim().is_empty() || thread.preview.trim() == title.trim() { return; diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs index 948678067ef..397a75ba231 100644 --- a/codex-rs/core/src/session/mod.rs +++ b/codex-rs/core/src/session/mod.rs @@ -36,7 +36,6 @@ use crate::installation_id::resolve_installation_id; use crate::parse_turn_item; use crate::path_utils::normalize_for_native_workdir; use crate::realtime_conversation::RealtimeConversationManager; -use crate::rollout::find_thread_name_by_id; use crate::session_prefix::format_subagent_notification_message; use crate::skills::SkillRenderSideEffects; use crate::skills_load_input_from_config; @@ -133,6 +132,7 @@ use codex_terminal_detection::user_agent; use codex_thread_store::CreateThreadParams; use codex_thread_store::LiveThread; use codex_thread_store::LiveThreadInitGuard; +use codex_thread_store::ReadThreadParams; use codex_thread_store::ResumeThreadParams; use codex_thread_store::ThreadEventPersistenceMode; use codex_thread_store::ThreadPersistenceMetadata; @@ -819,24 +819,33 @@ pub(crate) fn session_loop_termination_from_handle( .shared() } -async fn thread_title_from_state_db( - state_db: Option<&state_db::StateDbHandle>, - codex_home: &AbsolutePathBuf, +async fn thread_title_from_thread_store( + live_thread: Option<&LiveThread>, + thread_store: &Arc, conversation_id: ThreadId, ) -> Option { - if let Some(metadata) = state_db - && let Some(metadata) = metadata.get_thread(conversation_id).await.ok().flatten() - { - let title = metadata.title.trim(); - if !title.is_empty() && metadata.first_user_message.as_deref().map(str::trim) != Some(title) - { - return Some(title.to_string()); + let thread = match live_thread { + Some(live_thread) => { + live_thread + .read_thread( + /*include_archived*/ true, /*include_history*/ false, + ) + .await + } + None => { + thread_store + .read_thread(ReadThreadParams { + thread_id: conversation_id, + include_archived: true, + include_history: false, + }) + .await } } - find_thread_name_by_id(codex_home, &conversation_id) - .await - .ok() - .flatten() + .ok()?; + + let title = thread.name.as_deref()?.trim(); + (!title.is_empty() && thread.preview.trim() != title).then(|| title.to_string()) } impl Session { diff --git a/codex-rs/core/src/session/session.rs b/codex-rs/core/src/session/session.rs index d593544b496..615b88fbdab 100644 --- a/codex-rs/core/src/session/session.rs +++ b/codex-rs/core/src/session/session.rs @@ -698,7 +698,11 @@ impl Session { tx }; let thread_name = - thread_title_from_state_db(state_db_ctx.as_ref(), &config.codex_home, conversation_id) + thread_title_from_thread_store( + live_thread_init.as_ref(), + &thread_store, + conversation_id, + ) .instrument(info_span!( "session_init.thread_name_lookup", otel.name = "session_init.thread_name_lookup",