From e2f35dd8c8427782b0ab6138400916b5bbfca2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=80=E1=B4=8D=E1=B4=9B=E1=B4=8F=E1=B4=80=E1=B4=87?= =?UTF-8?q?=CA=80?= Date: Sun, 26 Jul 2026 04:42:21 +0800 Subject: [PATCH] agent_ui: Fix selection mentions from "Add to Agent Thread" not opening files (#61621) # Objective Fixes #59333. Selection mentions created with "Add to Agent Thread" could not be clicked to open the referenced file, while selection mentions created by pasting were navigable. ## Solution The ready selection-mention crease did not receive its `MentionUri` or `Workspace`, so `MentionCrease` could not install its click handler. Pass the workspace through the action-completion callback and provide both values to the shared crease renderer, enabling its existing navigation behavior. ## Testing I tested these changes locally. ## 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 adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase Before: https://github.com/user-attachments/assets/8dd4a2d0-4b22-4fb3-8777-cf97b6436b91 After: https://github.com/user-attachments/assets/cff1cdb3-804a-45d8-a9c5-fdd8b35b6f8f --- Release Notes: - Fixed selection mentions added with "Add to Agent Thread" not opening their referenced files. --- crates/agent_ui/src/completion_provider.rs | 16 +++++++++++++++- crates/agent_ui/src/inline_prompt_editor.rs | 2 ++ crates/agent_ui/src/mention_set.rs | 18 +++++++++++++++++- crates/agent_ui/src/message_editor.rs | 1 + 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/crates/agent_ui/src/completion_provider.rs b/crates/agent_ui/src/completion_provider.rs index ff6f4ca13b..6b6196c438 100644 --- a/crates/agent_ui/src/completion_provider.rs +++ b/crates/agent_ui/src/completion_provider.rs @@ -528,7 +528,14 @@ impl PromptCompletionProvider { AgentContextSource::from_active(workspace, cx)? .read_selection(workspace, false, cx) }); - Self::completion_for_action(action, source_range, editor, mention_set, selection) + Self::completion_for_action( + action, + source_range, + editor, + mention_set, + workspace.downgrade(), + selection, + ) } } } @@ -815,6 +822,7 @@ impl PromptCompletionProvider { source_range: Range, editor: WeakEntity, mention_set: WeakEntity, + workspace: WeakEntity, selection: Option, ) -> Option { let (new_text, on_action) = match action { @@ -824,6 +832,7 @@ impl PromptCompletionProvider { source_range.clone(), editor, mention_set, + workspace, editor_selections, ) } @@ -2702,6 +2711,7 @@ fn completion_text_for_editor_selections( source_range: Range, editor: WeakEntity, mention_set: WeakEntity, + workspace: WeakEntity, editor_selections: Vec<(Entity, Range)>, ) -> (String, ConfirmCallback) { const EDITOR_PLACEHOLDER: &str = "selection "; @@ -2725,6 +2735,7 @@ fn completion_text_for_editor_selections( let editor = editor.clone(); let selections = selections.clone(); let mention_set = mention_set.clone(); + let workspace = workspace.clone(); let source_range = source_range.clone(); window.defer(cx, move |window, cx| { if let Some(editor) = editor.upgrade() @@ -2736,6 +2747,7 @@ fn completion_text_for_editor_selections( source_range.clone(), selections, editor.clone(), + workspace, window, cx, ) @@ -2794,6 +2806,8 @@ fn completion_text_for_terminal_selections( mention_uri.name().into(), mention_uri.icon_path(cx), None, + None, + None, range, editor.downgrade(), ); diff --git a/crates/agent_ui/src/inline_prompt_editor.rs b/crates/agent_ui/src/inline_prompt_editor.rs index b5fca12fc5..a541baa7cb 100644 --- a/crates/agent_ui/src/inline_prompt_editor.rs +++ b/crates/agent_ui/src/inline_prompt_editor.rs @@ -1615,6 +1615,8 @@ fn insert_message_creases( crease.label.clone(), crease.icon_path.clone(), None, + None, + None, start..end, cx.weak_entity(), ) diff --git a/crates/agent_ui/src/mention_set.rs b/crates/agent_ui/src/mention_set.rs index d04f222e18..97d2dfbca6 100644 --- a/crates/agent_ui/src/mention_set.rs +++ b/crates/agent_ui/src/mention_set.rs @@ -520,6 +520,7 @@ impl MentionSet { source_range: Range, selections: Vec<(Entity, Range, Range)>, editor: Entity, + workspace: WeakEntity, window: &mut Window, cx: &mut Context, ) { @@ -559,6 +560,8 @@ impl MentionSet { selection_name(abs_path.as_deref(), &line_range).into(), uri.icon_path(cx), uri.tooltip_text(), + Some(uri.clone()), + Some(workspace.clone()), range, editor.downgrade(), ); @@ -1143,11 +1146,20 @@ pub(crate) fn crease_for_mention( label: SharedString, icon_path: SharedString, tooltip: Option, + mention_uri: Option, + workspace: Option>, range: Range, editor_entity: WeakEntity, ) -> Crease { let placeholder = FoldPlaceholder { - render: render_fold_icon_button(icon_path.clone(), label.clone(), tooltip, editor_entity), + render: render_fold_icon_button( + icon_path.clone(), + label.clone(), + tooltip, + mention_uri, + workspace, + editor_entity, + ), merge_adjacent: false, ..Default::default() }; @@ -1162,6 +1174,8 @@ fn render_fold_icon_button( icon_path: SharedString, label: SharedString, tooltip: Option, + mention_uri: Option, + workspace: Option>, editor: WeakEntity, ) -> Arc, &mut App) -> AnyElement> { Arc::new({ @@ -1171,6 +1185,8 @@ fn render_fold_icon_button( .unwrap_or_default(); MentionCrease::new(fold_id, icon_path.clone(), label.clone()) + .mention_uri(mention_uri.clone()) + .workspace(workspace.clone()) .is_toggled(is_in_text_selection) .when_some(tooltip.clone(), |this, tooltip_text| { this.tooltip(tooltip_text) diff --git a/crates/agent_ui/src/message_editor.rs b/crates/agent_ui/src/message_editor.rs index f98625df4b..61ccdc07f5 100644 --- a/crates/agent_ui/src/message_editor.rs +++ b/crates/agent_ui/src/message_editor.rs @@ -1599,6 +1599,7 @@ impl MessageEditor { anchor..anchor, self.editor.downgrade(), self.mention_set.downgrade(), + self.workspace.clone(), Some(selection), ) else {