From 081bb237f432a02bcfb24a2b6a5ba2d81fdcee82 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 28 Jan 2026 14:03:52 -0500 Subject: [PATCH] Improve Zed agent thread history to update across all open windows (#47803) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, each Agent panel created its own `ThreadStore` instance, so thread history updates wouldn't sync between open windows. Users had to close and reopen windows to see threads created in other windows. Now `ThreadStore` is initialized once as a global and shared across all windows. When any window saves a thread, ThreadStore::reload() calls cx.notify(), which notifies all NativeAgentSessionList observers, causing all windows' history views to refresh. Note: This only works for the native Zed agent. It also is only improving the history view (thread titles)—this PR does not sync edits between multiple windows when the same thread is open in each. Release Notes: - Improved Zed agent thread history to update across all open windows --- crates/agent/src/thread_store.rs | 15 ++++++++++++++- crates/agent_ui/src/agent_panel.rs | 2 +- crates/agent_ui/src/agent_ui.rs | 1 + crates/agent_ui_v2/src/agents_panel.rs | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/crates/agent/src/thread_store.rs b/crates/agent/src/thread_store.rs index 3a8dd6690f9dd82868877828113f8d7d03cad4d5..cd7c03de546f2fff2e603c59739816640d24e9f5 100644 --- a/crates/agent/src/thread_store.rs +++ b/crates/agent/src/thread_store.rs @@ -1,10 +1,14 @@ use crate::{DbThread, DbThreadMetadata, ThreadsDatabase}; use agent_client_protocol as acp; use anyhow::{Result, anyhow}; -use gpui::{App, Context, Entity, Task, prelude::*}; +use gpui::{App, Context, Entity, Global, Task, prelude::*}; use project::Project; use std::rc::Rc; +struct GlobalThreadStore(Entity); + +impl Global for GlobalThreadStore {} + // TODO: Remove once ACP thread loading is fully handled elsewhere. pub fn load_agent_thread( session_id: acp::SessionId, @@ -37,6 +41,15 @@ pub struct ThreadStore { } impl ThreadStore { + pub fn init_global(cx: &mut App) { + let thread_store = cx.new(|cx| Self::new(cx)); + cx.set_global(GlobalThreadStore(thread_store)); + } + + pub fn global(cx: &App) -> Entity { + cx.global::().0.clone() + } + pub fn new(cx: &mut Context) -> Self { let this = Self { threads: Vec::new(), diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index 766744907b65b96995e2f78a2b9926537ef0d464..aca4386a147d3dee254070102c41c8904f71206a 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -507,7 +507,7 @@ impl AgentPanel { let context_server_registry = cx.new(|cx| ContextServerRegistry::new(project.read(cx).context_server_store(), cx)); - let thread_store = cx.new(|cx| ThreadStore::new(cx)); + let thread_store = ThreadStore::global(cx); let acp_history = cx.new(|cx| AcpThreadHistory::new(None, window, cx)); let text_thread_history = cx.new(|cx| TextThreadHistory::new(text_thread_store.clone(), window, cx)); diff --git a/crates/agent_ui/src/agent_ui.rs b/crates/agent_ui/src/agent_ui.rs index bb39ce96c343d96b81331957d478ed5fccedd026..62d22c9a22faf0a5939dfe96473152db890ef333 100644 --- a/crates/agent_ui/src/agent_ui.rs +++ b/crates/agent_ui/src/agent_ui.rs @@ -256,6 +256,7 @@ pub fn init( is_eval: bool, cx: &mut App, ) { + agent::ThreadStore::init_global(cx); assistant_text_thread::init(client, cx); rules_library::init(cx); if !is_eval { diff --git a/crates/agent_ui_v2/src/agents_panel.rs b/crates/agent_ui_v2/src/agents_panel.rs index f8e223ffbf8a05aa8e78af6baf7ec95265afaf45..3f56704850b5cad0d3af349ad92efe8698a923ef 100644 --- a/crates/agent_ui_v2/src/agents_panel.rs +++ b/crates/agent_ui_v2/src/agents_panel.rs @@ -124,7 +124,7 @@ impl AgentsPanel { ) -> Self { let focus_handle = cx.focus_handle(); - let thread_store = cx.new(|cx| ThreadStore::new(cx)); + let thread_store = ThreadStore::global(cx); let history = cx.new(|cx| AcpThreadHistory::new(None, window, cx)); let history_handle = history.clone();