Add the ability to follow the agent as it makes edits (#29839)

Nathan here: I also tacked on a bunch of UI refinement.

Release Notes:

- Introduced the ability to follow the agent around as it reads and
edits files.

---------

Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Antonio Scandurra 2025-05-04 10:28:39 +02:00 committed by GitHub
parent 425f32e068
commit 545ae27079
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 1255 additions and 567 deletions

View file

@ -28,7 +28,6 @@ use crate::{
scroll::scroll_amount::ScrollAmount,
};
use buffer_diff::{DiffHunkStatus, DiffHunkStatusKind};
use client::ParticipantIndex;
use collections::{BTreeMap, HashMap};
use feature_flags::{DebuggerFeatureFlag, FeatureFlagAppExt};
use file_icons::FileIcons;
@ -82,7 +81,7 @@ use theme::{ActiveTheme, Appearance, BufferLineHeight, PlayerColor};
use ui::{ButtonLike, KeyBinding, POPOVER_Y_PADDING, Tooltip, h_flex, prelude::*};
use unicode_segmentation::UnicodeSegmentation;
use util::{RangeExt, ResultExt, debug_panic};
use workspace::{Workspace, item::Item, notifications::NotifyTaskExt};
use workspace::{CollaboratorId, Workspace, item::Item, notifications::NotifyTaskExt};
const INLINE_BLAME_PADDING_EM_WIDTHS: f32 = 7.;
@ -1126,7 +1125,7 @@ impl EditorElement {
editor.cursor_shape,
&snapshot.display_snapshot,
is_newest,
editor.leader_peer_id.is_none(),
editor.leader_id.is_none(),
None,
);
if is_newest {
@ -1150,18 +1149,29 @@ impl EditorElement {
if let Some(collaboration_hub) = &editor.collaboration_hub {
// When following someone, render the local selections in their color.
if let Some(leader_id) = editor.leader_peer_id {
if let Some(collaborator) = collaboration_hub.collaborators(cx).get(&leader_id)
{
if let Some(participant_index) = collaboration_hub
.user_participant_indices(cx)
.get(&collaborator.user_id)
{
if let Some(leader_id) = editor.leader_id {
match leader_id {
CollaboratorId::PeerId(peer_id) => {
if let Some(collaborator) =
collaboration_hub.collaborators(cx).get(&peer_id)
{
if let Some(participant_index) = collaboration_hub
.user_participant_indices(cx)
.get(&collaborator.user_id)
{
if let Some((local_selection_style, _)) = selections.first_mut()
{
*local_selection_style = cx
.theme()
.players()
.color_for_participant(participant_index.0);
}
}
}
}
CollaboratorId::Agent => {
if let Some((local_selection_style, _)) = selections.first_mut() {
*local_selection_style = cx
.theme()
.players()
.color_for_participant(participant_index.0);
*local_selection_style = cx.theme().players().agent();
}
}
}
@ -1173,12 +1183,9 @@ impl EditorElement {
collaboration_hub.as_ref(),
cx,
) {
let selection_style =
Self::get_participant_color(selection.participant_index, cx);
// Don't re-render the leader's selections, since the local selections
// match theirs.
if Some(selection.peer_id) == editor.leader_peer_id {
if Some(selection.collaborator_id) == editor.leader_id {
continue;
}
let key = HoveredCursor {
@ -1191,7 +1198,7 @@ impl EditorElement {
remote_selections
.entry(selection.replica_id)
.or_insert((selection_style, Vec::new()))
.or_insert((selection.color, Vec::new()))
.1
.push(SelectionLayout::new(
selection.selection,
@ -1246,9 +1253,11 @@ impl EditorElement {
collaboration_hub.deref(),
cx,
) {
let color = Self::get_participant_color(remote_selection.participant_index, cx);
add_cursor(remote_selection.selection.head(), color.cursor);
if Some(remote_selection.peer_id) == editor.leader_peer_id {
add_cursor(
remote_selection.selection.head(),
remote_selection.color.cursor,
);
if Some(remote_selection.collaborator_id) == editor.leader_id {
skip_local = true;
}
}
@ -2446,14 +2455,6 @@ impl EditorElement {
Some(button)
}
fn get_participant_color(participant_index: Option<ParticipantIndex>, cx: &App) -> PlayerColor {
if let Some(index) = participant_index {
cx.theme().players().color_for_participant(index.0)
} else {
cx.theme().players().absent()
}
}
fn calculate_relative_line_numbers(
&self,
snapshot: &EditorSnapshot,