Rename `ThreadMetadataStore` to `SidebarThreadMetadataStore ` (#51913)

Bennet Bo Fenner created

## Context

Renamed ThreadMetadataStore to SidebarThreadMetadataStore.
There was some confusion yesterday on what metadata should be stored in
`ThreadMetadataStore.
Only threads that should show up in the sidebar should be stored here
(effectively all non-archived ones). Hopefully the rename + doc comment
added makes this clearer.
Unfortunately we cannot move it into the sidebar crate since we need it
in the archived history view too.

## How to Review

This is purely a cosmetical change

## Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- N/A

Change summary

crates/agent_ui/src/conversation_view.rs     |  6 ++--
crates/agent_ui/src/thread_metadata_store.rs | 32 ++++++++++++---------
crates/agent_ui/src/threads_archive_view.rs  |  6 +--
crates/sidebar/src/sidebar.rs                | 25 +++++++++-------
4 files changed, 37 insertions(+), 32 deletions(-)

Detailed changes

crates/agent_ui/src/conversation_view.rs 🔗

@@ -75,7 +75,7 @@ use crate::agent_diff::AgentDiff;
 use crate::entry_view_state::{EntryViewEvent, ViewEvent};
 use crate::message_editor::{MessageEditor, MessageEditorEvent};
 use crate::profile_selector::{ProfileProvider, ProfileSelector};
-use crate::thread_metadata_store::ThreadMetadataStore;
+use crate::thread_metadata_store::SidebarThreadMetadataStore;
 use crate::ui::{AgentNotification, AgentNotificationEvent};
 use crate::{
     Agent, AgentDiffPane, AgentInitialContent, AgentPanel, AllowAlways, AllowOnce,
@@ -2615,7 +2615,7 @@ impl ConversationView {
         let task = history.update(cx, |history, cx| history.delete_session(&session_id, cx));
         task.detach_and_log_err(cx);
 
-        if let Some(store) = ThreadMetadataStore::try_global(cx) {
+        if let Some(store) = SidebarThreadMetadataStore::try_global(cx) {
             store
                 .update(cx, |store, cx| store.delete(session_id.clone(), cx))
                 .detach_and_log_err(cx);
@@ -4291,7 +4291,7 @@ pub(crate) mod tests {
         cx.update(|cx| {
             let settings_store = SettingsStore::test(cx);
             cx.set_global(settings_store);
-            ThreadMetadataStore::init_global(cx);
+            SidebarThreadMetadataStore::init_global(cx);
             theme::init(theme::LoadThemes::JustBase, cx);
             editor::init(cx);
             agent_panel::init(cx);

crates/agent_ui/src/thread_metadata_store.rs 🔗

@@ -20,7 +20,7 @@ use ui::{App, Context, SharedString};
 use workspace::PathList;
 
 pub fn init(cx: &mut App) {
-    ThreadMetadataStore::init_global(cx);
+    SidebarThreadMetadataStore::init_global(cx);
 
     if cx.has_flag::<AgentV2FeatureFlag>() {
         migrate_thread_metadata(cx);
@@ -37,7 +37,7 @@ pub fn init(cx: &mut App) {
 ///
 /// TODO: Remove this after N weeks of shipping the sidebar
 fn migrate_thread_metadata(cx: &mut App) {
-    ThreadMetadataStore::global(cx).update(cx, |store, cx| {
+    SidebarThreadMetadataStore::global(cx).update(cx, |store, cx| {
         let list = store.list(cx);
         cx.spawn(async move |this, cx| {
             let Ok(list) = list.await else {
@@ -68,7 +68,7 @@ fn migrate_thread_metadata(cx: &mut App) {
     });
 }
 
-struct GlobalThreadMetadataStore(Entity<ThreadMetadataStore>);
+struct GlobalThreadMetadataStore(Entity<SidebarThreadMetadataStore>);
 impl Global for GlobalThreadMetadataStore {}
 
 /// Lightweight metadata for any thread (native or ACP), enough to populate
@@ -140,12 +140,16 @@ impl ThreadMetadata {
     }
 }
 
-pub struct ThreadMetadataStore {
+/// The store holds all metadata needed to show threads in the sidebar.
+/// Effectively, all threads stored in here are "non-archived".
+///
+/// Automatically listens to AcpThread events and updates metadata if it has changed.
+pub struct SidebarThreadMetadataStore {
     db: ThreadMetadataDb,
     session_subscriptions: HashMap<acp::SessionId, Subscription>,
 }
 
-impl ThreadMetadataStore {
+impl SidebarThreadMetadataStore {
     #[cfg(not(any(test, feature = "test-support")))]
     pub fn init_global(cx: &mut App) {
         if cx.has_global::<Self>() {
@@ -290,7 +294,7 @@ impl ThreadMetadataStore {
     }
 }
 
-impl Global for ThreadMetadataStore {}
+impl Global for SidebarThreadMetadataStore {}
 
 struct ThreadMetadataDb(ThreadSafeConnection);
 
@@ -468,12 +472,12 @@ mod tests {
     async fn test_migrate_thread_metadata(cx: &mut TestAppContext) {
         cx.update(|cx| {
             ThreadStore::init_global(cx);
-            ThreadMetadataStore::init_global(cx);
+            SidebarThreadMetadataStore::init_global(cx);
         });
 
         // Verify the list is empty before migration
         let metadata_list = cx.update(|cx| {
-            let store = ThreadMetadataStore::global(cx);
+            let store = SidebarThreadMetadataStore::global(cx);
             store.read(cx).list(cx)
         });
 
@@ -520,7 +524,7 @@ mod tests {
 
         // Verify the metadata was migrated
         let metadata_list = cx.update(|cx| {
-            let store = ThreadMetadataStore::global(cx);
+            let store = SidebarThreadMetadataStore::global(cx);
             store.read(cx).list(cx)
         });
 
@@ -546,7 +550,7 @@ mod tests {
     async fn test_migrate_thread_metadata_skips_when_data_exists(cx: &mut TestAppContext) {
         cx.update(|cx| {
             ThreadStore::init_global(cx);
-            ThreadMetadataStore::init_global(cx);
+            SidebarThreadMetadataStore::init_global(cx);
         });
 
         // Pre-populate the metadata store with existing data
@@ -560,7 +564,7 @@ mod tests {
         };
 
         cx.update(|cx| {
-            let store = ThreadMetadataStore::global(cx);
+            let store = SidebarThreadMetadataStore::global(cx);
             store.update(cx, |store, cx| {
                 store.save(existing_metadata, cx).detach();
             });
@@ -592,7 +596,7 @@ mod tests {
 
         // Verify only the existing metadata is present (migration was skipped)
         let metadata_list = cx.update(|cx| {
-            let store = ThreadMetadataStore::global(cx);
+            let store = SidebarThreadMetadataStore::global(cx);
             store.read(cx).list(cx)
         });
 
@@ -608,7 +612,7 @@ mod tests {
             cx.set_global(settings_store);
             cx.update_flags(true, vec!["agent-v2".to_string()]);
             ThreadStore::init_global(cx);
-            ThreadMetadataStore::init_global(cx);
+            SidebarThreadMetadataStore::init_global(cx);
         });
 
         let fs = FakeFs::new(cx.executor());
@@ -666,7 +670,7 @@ mod tests {
 
         // List all metadata from the store.
         let metadata_list = cx.update(|cx| {
-            let store = ThreadMetadataStore::global(cx);
+            let store = SidebarThreadMetadataStore::global(cx);
             store.read(cx).list(cx)
         });
 

crates/agent_ui/src/threads_archive_view.rs 🔗

@@ -2,7 +2,7 @@ use std::sync::Arc;
 
 use crate::{
     Agent, RemoveSelectedThread, agent_connection_store::AgentConnectionStore,
-    thread_history::ThreadHistory, thread_metadata_store::ThreadMetadataStore,
+    thread_history::ThreadHistory, thread_metadata_store::SidebarThreadMetadataStore,
 };
 use acp_thread::AgentSessionInfo;
 use agent::ThreadStore;
@@ -247,9 +247,7 @@ impl ThreadsArchiveView {
         let today = Local::now().naive_local().date();
 
         self._update_items_task.take();
-        let unarchived_ids_task = ThreadMetadataStore::global(cx)
-            .read(cx)
-            .list_sidebar_ids(cx);
+        let unarchived_ids_task = SidebarThreadMetadataStore::global(cx).read(cx).list_ids(cx);
         self._update_items_task = Some(cx.spawn(async move |this, cx| {
             let unarchived_session_ids = unarchived_ids_task.await.unwrap_or_default();
 

crates/sidebar/src/sidebar.rs 🔗

@@ -1,7 +1,7 @@
 use acp_thread::ThreadStatus;
 use action_log::DiffStats;
 use agent_client_protocol::{self as acp};
-use agent_ui::thread_metadata_store::{ThreadMetadata, ThreadMetadataStore};
+use agent_ui::thread_metadata_store::{SidebarThreadMetadataStore, ThreadMetadata};
 use agent_ui::threads_archive_view::{
     ThreadsArchiveView, ThreadsArchiveViewEvent, format_history_entry_timestamp,
 };
@@ -300,9 +300,12 @@ impl Sidebar {
         })
         .detach();
 
-        cx.observe(&ThreadMetadataStore::global(cx), |this, _store, cx| {
-            this.list_threads(cx);
-        })
+        cx.observe(
+            &SidebarThreadMetadataStore::global(cx),
+            |this, _store, cx| {
+                this.list_threads(cx);
+            },
+        )
         .detach();
 
         cx.observe_flag::<AgentV2FeatureFlag, _>(window, |_is_enabled, this, _window, cx| {
@@ -1006,7 +1009,7 @@ impl Sidebar {
     }
 
     fn list_threads(&mut self, cx: &mut Context<Self>) {
-        let list_task = ThreadMetadataStore::global(cx).read(cx).list(cx);
+        let list_task = SidebarThreadMetadataStore::global(cx).read(cx).list(cx);
         self._list_threads_task = Some(cx.spawn(async move |this, cx| {
             let Some(thread_entries) = list_task.await.log_err() else {
                 return;
@@ -1835,7 +1838,7 @@ impl Sidebar {
         cx: &mut Context<Self>,
     ) {
         // Eagerly save thread metadata so that the sidebar is updated immediately
-        ThreadMetadataStore::global(cx)
+        SidebarThreadMetadataStore::global(cx)
             .update(cx, |store, cx| {
                 store.save(
                     ThreadMetadata::from_session_info(agent.id(), &session_info),
@@ -2107,7 +2110,7 @@ impl Sidebar {
             }
         }
 
-        ThreadMetadataStore::global(cx)
+        SidebarThreadMetadataStore::global(cx)
             .update(cx, |store, cx| store.delete(session_id.clone(), cx))
             .detach_and_log_err(cx);
     }
@@ -2840,7 +2843,7 @@ mod tests {
             editor::init(cx);
             cx.update_flags(false, vec!["agent-v2".into()]);
             ThreadStore::init_global(cx);
-            ThreadMetadataStore::init_global(cx);
+            SidebarThreadMetadataStore::init_global(cx);
             language_model::LanguageModelRegistry::test(cx);
             prompt_store::init(cx);
         });
@@ -2944,7 +2947,7 @@ mod tests {
             folder_paths: path_list,
         };
         let task = cx.update(|cx| {
-            ThreadMetadataStore::global(cx).update(cx, |store, cx| store.save(metadata, cx))
+            SidebarThreadMetadataStore::global(cx).update(cx, |store, cx| store.save(metadata, cx))
         });
         task.await.unwrap();
     }
@@ -3901,7 +3904,7 @@ mod tests {
         cx.update(|cx| {
             cx.update_flags(false, vec!["agent-v2".into()]);
             ThreadStore::init_global(cx);
-            ThreadMetadataStore::init_global(cx);
+            SidebarThreadMetadataStore::init_global(cx);
             language_model::LanguageModelRegistry::test(cx);
             prompt_store::init(cx);
         });
@@ -5200,7 +5203,7 @@ mod tests {
         cx.update(|cx| {
             cx.update_flags(false, vec!["agent-v2".into()]);
             ThreadStore::init_global(cx);
-            ThreadMetadataStore::init_global(cx);
+            SidebarThreadMetadataStore::init_global(cx);
             language_model::LanguageModelRegistry::test(cx);
             prompt_store::init(cx);
         });