Support renaming ACP threads (#56446)

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

Closes #54689

Release Notes:

- Support editing the thread title for external agent threads
This commit is contained in:
Bennet Bo Fenner authored and GitHub committed 2026-05-11 19:21:10 +00:00
1 parent 8875562192
commit 22c3a5ad9a
6 files changed
+198 -39

No files matched your search

+2
View File
@@ -679,6 +679,7 @@ fn thread_metadata_to_debug_json(
"session_id": metadata.session_id.as_ref().map(|s| s.0.to_string()),
"agent_id": metadata.agent_id.0.to_string(),
"title": metadata.title.as_ref().map(|t| t.to_string()),
"title_override": metadata.title_override.as_ref().map(|t| t.to_string()),
"updated_at": format_timestamp_human(&metadata.updated_at),
"created_at": metadata.created_at.as_ref().map(format_timestamp_human),
"interacted_at": metadata.interacted_at.as_ref().map(format_timestamp_human),
@@ -5295,6 +5296,7 @@ mod tests {
session_id: Some(resume_session_id.clone()),
agent_id: ProjectAgentId::new("Flaky"),
title: Some("Persistent chat".into()),
title_override: None,
updated_at: Utc::now(),
created_at: Some(Utc::now()),
interacted_at: None,
+11 -20
View File
@@ -792,7 +792,7 @@ impl ConversationView {
.and_then(|id| {
let store = ThreadMetadataStore::try_global(cx)?;
let entry = store.read(cx).entry_by_session(id)?;
Some((Some(entry.folder_paths().clone()), entry.title.clone()))
Some((Some(entry.folder_paths().clone()), entry.title()))
})
.unwrap_or((None, None));
(session_id, work_dirs, title)
@@ -1186,6 +1186,7 @@ impl ConversationView {
let weak = cx.weak_entity();
cx.new(|cx| {
ThreadView::new(
self.thread_id,
thread,
conversation,
weak,
@@ -1614,7 +1615,14 @@ impl ConversationView {
);
}
AcpThreadEvent::TitleUpdated => {
if let Some(title) = thread.read(cx).title()
let override_title = ThreadMetadataStore::try_global(cx).and_then(|store| {
store
.read(cx)
.entry(self.thread_id)
.and_then(|m| m.title_override.clone())
});
let title = override_title.or_else(|| thread.read(cx).title());
if let Some(title) = title
&& let Some(active_thread) = self.thread_view(&session_id)
{
let title_editor = active_thread.read(cx).title_editor.clone();
@@ -3589,6 +3597,7 @@ pub(crate) mod tests {
session_id: Some(resume_session_id.clone()),
agent_id: ProjectAgentId::new("Flaky"),
title: Some(stored_title.clone()),
title_override: None,
updated_at: Utc::now(),
created_at: Some(Utc::now()),
interacted_at: None,
@@ -7119,24 +7128,6 @@ pub(crate) mod tests {
});
}
#[gpui::test]
async fn test_title_editor_is_read_only_when_set_title_unsupported(cx: &mut TestAppContext) {
init_test(cx);
let (conversation_view, cx) =
setup_conversation_view(StubAgentServer::new(ResumeOnlyAgentConnection), cx).await;
let active = active_thread(&conversation_view, cx);
let title_editor = cx.read(|cx| active.read(cx).title_editor.clone());
title_editor.read_with(cx, |editor, cx| {
assert!(
editor.read_only(cx),
"Title editor should be read-only when the connection does not support set_title"
);
});
}
#[gpui::test]
async fn test_max_tokens_error_is_rendered(cx: &mut TestAppContext) {
init_test(cx);
@@ -1,6 +1,7 @@
use crate::{
DEFAULT_THREAD_TITLE, SelectPermissionGranularity,
agent_configuration::configure_context_server_modal::default_markdown_style,
thread_metadata_store::{ThreadId, ThreadMetadataStore},
};
use agent_client_protocol::schema as acp;
use std::cell::RefCell;
@@ -264,6 +265,7 @@ impl PermissionSelection {
}
pub struct ThreadView {
pub(crate) root_thread_id: ThreadId,
pub session_id: acp::SessionId,
pub parent_session_id: Option<acp::SessionId>,
pub thread: Entity<AcpThread>,
@@ -353,6 +355,7 @@ pub struct TurnFields {
impl ThreadView {
pub(crate) fn new(
root_thread_id: ThreadId,
thread: Entity<AcpThread>,
conversation: Entity<super::Conversation>,
server_view: WeakEntity<ConversationView>,
@@ -438,15 +441,17 @@ impl ThreadView {
&& agent_id.as_ref() == "Codex";
let title_editor = {
let can_edit = thread.update(cx, |thread, cx| thread.can_set_title(cx));
let metadata = ThreadMetadataStore::try_global(cx)
.and_then(|store| store.read(cx).entry(root_thread_id).cloned());
let initial_title = if parent_session_id.is_none() {
metadata.as_ref().and_then(|m| m.title())
} else {
thread.read(cx).title()
}
.unwrap_or_else(|| DEFAULT_THREAD_TITLE.into());
let editor = cx.new(|cx| {
let mut editor = Editor::single_line(window, cx);
if let Some(title) = thread.read(cx).title() {
editor.set_text(title, window, cx);
} else {
editor.set_text(DEFAULT_THREAD_TITLE, window, cx);
}
editor.set_read_only(!can_edit);
editor.set_text(initial_title, window, cx);
editor
});
subscriptions.push(cx.subscribe_in(&editor, window, Self::handle_title_editor_event));
@@ -490,6 +495,7 @@ impl ThreadView {
}));
let mut this = Self {
root_thread_id,
session_id,
parent_session_id,
focus_handle: cx.focus_handle(),
@@ -1647,11 +1653,23 @@ impl ThreadView {
}
let new_title = title_editor.read(cx).text(cx);
if new_title.is_empty() {
return;
}
let title = SharedString::from(new_title);
if let Some(store) = ThreadMetadataStore::try_global(cx)
&& !self.is_subagent()
{
let thread_id = self.root_thread_id;
store.update(cx, |store, cx| {
store.set_title_override(thread_id, title.clone(), cx);
});
}
thread.update(cx, |thread, cx| {
thread
.set_title(new_title.into(), cx)
.detach_and_log_err(cx);
})
if thread.can_set_title(cx) {
thread.set_title(title, cx).detach_and_log_err(cx);
}
});
}
EditorEvent::Blurred => {
if title_editor.read(cx).text(cx).is_empty() {
+1
View File
@@ -590,6 +590,7 @@ fn collect_importable_threads(
session_id: Some(session.session_id),
agent_id: agent_id.clone(),
title: session.title,
title_override: None,
updated_at: session.updated_at.unwrap_or_else(|| Utc::now()),
created_at: session.created_at,
interacted_at: None,
+131 -8
View File
@@ -135,6 +135,7 @@ fn migrate_thread_metadata(cx: &mut App) -> Task<anyhow::Result<()>> {
} else {
Some(entry.title)
},
title_override: None,
updated_at: entry.updated_at,
created_at: entry.created_at,
interacted_at: None,
@@ -310,6 +311,10 @@ pub struct ThreadMetadata {
pub session_id: Option<acp::SessionId>,
pub agent_id: AgentId,
pub title: Option<SharedString>,
/// User-supplied title that takes precedence over `title`. Set when the
/// user renames a thread, so that subsequent agent-driven title updates
/// (e.g. from `SessionInfoUpdate`) don't clobber the user's choice.
pub title_override: Option<SharedString>,
pub updated_at: DateTime<Utc>,
pub created_at: Option<DateTime<Utc>>,
/// When a user last interacted to send a message (including queueing).
@@ -328,11 +333,14 @@ impl ThreadMetadata {
}
pub fn display_title(&self) -> SharedString {
self.title
.clone()
self.title()
.unwrap_or_else(|| crate::DEFAULT_THREAD_TITLE.into())
}
pub fn title(&self) -> Option<SharedString> {
self.title_override.clone().or_else(|| self.title.clone())
}
pub fn folder_paths(&self) -> &PathList {
self.worktree_paths.folder_path_list()
}
@@ -422,7 +430,7 @@ impl From<&ThreadMetadata> for acp_thread::AgentSessionInfo {
Self {
session_id,
work_dirs: Some(meta.folder_paths().clone()),
title: meta.title.clone(),
title: meta.title(),
updated_at: Some(meta.updated_at),
created_at: meta.created_at,
meta: None,
@@ -674,6 +682,26 @@ impl ThreadMetadataStore {
cx.notify();
}
/// Set or clear the user-supplied title for a thread.
pub fn set_title_override(
&mut self,
thread_id: ThreadId,
title_override: SharedString,
cx: &mut Context<Self>,
) {
let Some(existing) = self.entry(thread_id) else {
return;
};
if existing.title_override.as_ref() == Some(&title_override) {
return;
}
let metadata = ThreadMetadata {
title_override: Some(title_override),
..existing.clone()
};
self.save(metadata, cx);
}
fn save_internal(&mut self, metadata: ThreadMetadata) {
if let Some(thread) = self.threads.get(&metadata.thread_id) {
if thread.folder_paths() != metadata.folder_paths() {
@@ -1196,6 +1224,7 @@ impl ThreadMetadataStore {
Some(thread_ref.session_id().clone())
};
let title = thread_ref.title();
let title_override = existing_thread.and_then(|t| t.title_override.clone());
let updated_at = Utc::now();
@@ -1249,6 +1278,7 @@ impl ThreadMetadataStore {
session_id,
agent_id,
title,
title_override,
created_at: Some(created_at),
interacted_at,
updated_at,
@@ -1364,6 +1394,9 @@ impl Domain for ThreadMetadataDb {
sql!(
ALTER TABLE sidebar_threads ADD COLUMN interacted_at TEXT;
),
sql!(
ALTER TABLE sidebar_threads ADD COLUMN title_override TEXT;
),
];
}
@@ -1380,7 +1413,7 @@ impl ThreadMetadataDb {
const LIST_QUERY: &str = "SELECT thread_id, session_id, agent_id, title, updated_at, \
created_at, interacted_at, folder_paths, folder_paths_order, archived, main_worktree_paths, \
main_worktree_paths_order, remote_connection \
main_worktree_paths_order, remote_connection, title_override \
FROM sidebar_threads \
ORDER BY updated_at DESC";
@@ -1430,12 +1463,13 @@ impl ThreadMetadataDb {
.map(serde_json::to_string)
.transpose()
.context("serialize thread metadata remote connection")?;
let title_override = row.title_override.as_ref().map(|t| t.to_string());
let thread_id = row.thread_id;
let archived = row.archived;
self.write(move |conn| {
let sql = "INSERT INTO sidebar_threads(thread_id, session_id, agent_id, title, updated_at, created_at, interacted_at, folder_paths, folder_paths_order, archived, main_worktree_paths, main_worktree_paths_order, remote_connection) \
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13) \
let sql = "INSERT INTO sidebar_threads(thread_id, session_id, agent_id, title, updated_at, created_at, interacted_at, folder_paths, folder_paths_order, archived, main_worktree_paths, main_worktree_paths_order, remote_connection, title_override) \
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14) \
ON CONFLICT(thread_id) DO UPDATE SET \
session_id = excluded.session_id, \
agent_id = excluded.agent_id, \
@@ -1448,7 +1482,8 @@ impl ThreadMetadataDb {
archived = excluded.archived, \
main_worktree_paths = excluded.main_worktree_paths, \
main_worktree_paths_order = excluded.main_worktree_paths_order, \
remote_connection = excluded.remote_connection";
remote_connection = excluded.remote_connection, \
title_override = excluded.title_override";
let mut stmt = Statement::prepare(conn, sql)?;
let mut i = stmt.bind(&thread_id, 1)?;
i = stmt.bind(&session_id, i)?;
@@ -1462,7 +1497,8 @@ impl ThreadMetadataDb {
i = stmt.bind(&archived, i)?;
i = stmt.bind(&main_worktree_paths, i)?;
i = stmt.bind(&main_worktree_paths_order, i)?;
stmt.bind(&remote_connection, i)?;
i = stmt.bind(&remote_connection, i)?;
stmt.bind(&title_override, i)?;
stmt.exec()
})
.await
@@ -1619,6 +1655,7 @@ impl Column for ThreadMetadata {
Column::column(statement, next)?;
let (remote_connection_json, next): (Option<String>, i32) =
Column::column(statement, next)?;
let (title_override, next): (Option<String>, i32) = Column::column(statement, next)?;
let agent_id = agent_id
.map(|id| AgentId::new(id))
@@ -1676,6 +1713,9 @@ impl Column for ThreadMetadata {
} else {
Some(title.into())
},
title_override: title_override
.filter(|t| !t.is_empty())
.map(SharedString::from),
updated_at,
created_at,
interacted_at,
@@ -1765,6 +1805,7 @@ mod tests {
} else {
Some(title.to_string().into())
},
title_override: None,
updated_at,
created_at: Some(updated_at),
interacted_at: None,
@@ -1821,6 +1862,83 @@ mod tests {
cx.run_until_parked();
}
#[test]
fn test_thread_metadata_title_prefers_override() {
let mut metadata = make_metadata(
"session-1",
"Agent Generated Title",
Utc::now(),
PathList::default(),
);
metadata.title_override = Some("User Title".into());
assert_eq!(metadata.title().as_deref(), Some("User Title"));
assert_eq!(metadata.display_title().as_ref(), "User Title");
metadata.title_override = None;
assert_eq!(metadata.title().as_deref(), Some("Agent Generated Title"));
assert_eq!(metadata.display_title().as_ref(), "Agent Generated Title");
}
#[gpui::test]
async fn test_database_round_trips_title_override(_cx: &mut TestAppContext) {
let now = Utc::now();
let mut metadata = make_metadata(
"session-1",
"Agent Generated Title",
now,
PathList::new(&[Path::new("/project-a")]),
);
metadata.title_override = Some("User Title".into());
let thread = std::thread::current();
let test_name = thread.name().unwrap_or("unknown_test");
let db_name = format!("THREAD_METADATA_DB_{}", test_name);
let db = ThreadMetadataDb(gpui::block_on(db::open_test_db::<ThreadMetadataDb>(
&db_name,
)));
db.save(metadata).await.unwrap();
let rows = db.list().unwrap();
assert_eq!(rows.len(), 1);
assert_eq!(rows[0].title.as_deref(), Some("Agent Generated Title"));
assert_eq!(rows[0].title_override.as_deref(), Some("User Title"));
assert_eq!(rows[0].title().as_deref(), Some("User Title"));
}
#[gpui::test]
async fn test_store_set_title_override_updates_cached_metadata(cx: &mut TestAppContext) {
init_test(cx);
let metadata = make_metadata(
"session-1",
"Agent Generated Title",
Utc::now(),
PathList::default(),
);
let thread_id = metadata.thread_id;
cx.update(|cx| {
let store = ThreadMetadataStore::global(cx);
store.update(cx, |store, cx| {
store.save(metadata, cx);
store.set_title_override(thread_id, "User Title".into(), cx);
});
});
cx.run_until_parked();
cx.update(|cx| {
let store = ThreadMetadataStore::global(cx);
let store = store.read(cx);
let metadata = store.entry(thread_id).expect("metadata should be cached");
assert_eq!(metadata.title.as_deref(), Some("Agent Generated Title"));
assert_eq!(metadata.title_override.as_deref(), Some("User Title"));
assert_eq!(metadata.display_title().as_ref(), "User Title");
});
}
#[gpui::test]
async fn test_store_initializes_cache_from_database(cx: &mut TestAppContext) {
let first_paths = PathList::new(&[Path::new("/project-a")]);
@@ -1947,6 +2065,7 @@ mod tests {
session_id: Some(acp::SessionId::new("session-1")),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("First Thread".into()),
title_override: None,
updated_at: updated_time,
created_at: Some(updated_time),
interacted_at: None,
@@ -2031,6 +2150,7 @@ mod tests {
session_id: Some(acp::SessionId::new("a-session-0")),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Existing Metadata".into()),
title_override: None,
updated_at: now - chrono::Duration::seconds(10),
created_at: Some(now - chrono::Duration::seconds(10)),
interacted_at: None,
@@ -2156,6 +2276,7 @@ mod tests {
session_id: Some(acp::SessionId::new("existing-session")),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Existing Metadata".into()),
title_override: None,
updated_at: existing_updated_at,
created_at: Some(existing_updated_at),
interacted_at: None,
@@ -2900,6 +3021,7 @@ mod tests {
session_id: Some(acp::SessionId::new("local-linked")),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Local Linked".into()),
title_override: None,
updated_at: now,
created_at: Some(now),
interacted_at: None,
@@ -2913,6 +3035,7 @@ mod tests {
session_id: Some(acp::SessionId::new("remote-linked")),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Remote Linked".into()),
title_override: None,
updated_at: now - chrono::Duration::seconds(1),
created_at: Some(now - chrono::Duration::seconds(1)),
interacted_at: None,
+24
View File
@@ -377,6 +377,7 @@ fn save_thread_metadata(
session_id: Some(session_id),
agent_id: agent::ZED_AGENT_ID.clone(),
title,
title_override: None,
updated_at,
created_at,
interacted_at,
@@ -412,6 +413,7 @@ fn save_thread_metadata_with_main_paths(
session_id: Some(session_id),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some(title),
title_override: None,
updated_at,
created_at: None,
interacted_at: None,
@@ -891,6 +893,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
agent_id: AgentId::new("zed-agent"),
worktree_paths: WorktreePaths::default(),
title: Some("Completed thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: Some(Utc::now()),
interacted_at: None,
@@ -917,6 +920,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
agent_id: AgentId::new("zed-agent"),
worktree_paths: WorktreePaths::default(),
title: Some("Running thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: Some(Utc::now()),
interacted_at: None,
@@ -943,6 +947,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
agent_id: AgentId::new("zed-agent"),
worktree_paths: WorktreePaths::default(),
title: Some("Error thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: Some(Utc::now()),
interacted_at: None,
@@ -970,6 +975,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
agent_id: AgentId::new("zed-agent"),
worktree_paths: WorktreePaths::default(),
title: Some("Waiting thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: Some(Utc::now()),
interacted_at: None,
@@ -997,6 +1003,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
agent_id: AgentId::new("zed-agent"),
worktree_paths: WorktreePaths::default(),
title: Some("Notified thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: Some(Utc::now()),
interacted_at: None,
@@ -4986,6 +4993,7 @@ async fn test_sidebar_keeps_multi_root_thread_with_stale_main_paths(cx: &mut Tes
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Stale Multi-Root Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -5066,6 +5074,7 @@ async fn test_activate_archived_thread_with_saved_paths_activates_matching_works
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Archived Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -5135,6 +5144,7 @@ async fn test_activate_archived_thread_cwd_fallback_with_matching_workspace(
session_id: Some(acp::SessionId::new(Arc::from("unknown-session"))),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("CWD Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -5202,6 +5212,7 @@ async fn test_activate_archived_thread_no_paths_no_cwd_uses_active_workspace(
session_id: Some(acp::SessionId::new(Arc::from("no-context-session"))),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Contextless Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -5259,6 +5270,7 @@ async fn test_activate_archived_thread_saved_paths_opens_new_workspace(cx: &mut
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("New WS Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -5315,6 +5327,7 @@ async fn test_activate_archived_thread_reuses_workspace_in_another_window(cx: &m
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Cross Window Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -5393,6 +5406,7 @@ async fn test_activate_archived_thread_reuses_workspace_in_another_window_with_t
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Cross Window Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -5475,6 +5489,7 @@ async fn test_activate_archived_thread_prefers_current_window_for_matching_paths
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Current Window Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -6412,6 +6427,7 @@ async fn test_archive_last_worktree_thread_not_blocked_by_remote_thread_at_same_
session_id: Some(acp::SessionId::new(Arc::from("remote-wt-thread"))),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Remote Worktree Thread".into()),
title_override: None,
updated_at: chrono::TimeZone::with_ymd_and_hms(&Utc, 2024, 1, 1, 0, 0, 0).unwrap(),
created_at: None,
interacted_at: None,
@@ -7226,6 +7242,7 @@ async fn test_unarchive_first_thread_in_group_does_not_create_spurious_draft(
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Unarchived Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -7319,6 +7336,7 @@ async fn test_unarchive_into_new_workspace_does_not_create_duplicate_real_thread
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Unarchived Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -7545,6 +7563,7 @@ async fn test_unarchive_into_inactive_existing_workspace_does_not_leave_active_d
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Restored In Inactive Workspace".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -8395,6 +8414,7 @@ async fn test_unarchive_linked_worktree_thread_into_project_group_shows_only_res
session_id: Some(session_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Unarchived Linked Thread".into()),
title_override: None,
updated_at: Utc::now(),
created_at: None,
interacted_at: None,
@@ -8945,6 +8965,7 @@ async fn test_legacy_thread_with_canonical_path_opens_main_repo_workspace(cx: &m
session_id: Some(legacy_session.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Legacy Main Thread".into()),
title_override: None,
updated_at: chrono::TimeZone::with_ymd_and_hms(&Utc, 2024, 1, 1, 0, 0, 0).unwrap(),
created_at: None,
interacted_at: None,
@@ -9934,6 +9955,7 @@ mod property_test {
session_id: Some(session_id),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some(title),
title_override: None,
updated_at,
created_at: None,
interacted_at: None,
@@ -10846,6 +10868,7 @@ async fn test_remote_project_integration_does_not_briefly_render_as_separate_pro
session_id: Some(remote_thread_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Worktree Thread".into()),
title_override: None,
updated_at: chrono::TimeZone::with_ymd_and_hms(&Utc, 2024, 1, 1, 0, 0, 1).unwrap(),
created_at: None,
interacted_at: None,
@@ -11567,6 +11590,7 @@ async fn test_remote_archive_thread_with_active_connection(
session_id: Some(wt_thread_id.clone()),
agent_id: agent::ZED_AGENT_ID.clone(),
title: Some("Worktree Thread".into()),
title_override: None,
updated_at: chrono::TimeZone::with_ymd_and_hms(&chrono::Utc, 2024, 1, 1, 0, 0, 0)
.unwrap(),
created_at: None,