From 4466d10df3a6a2546c9502e211c9612d58346970 Mon Sep 17 00:00:00 2001 From: Suphachai Phetthamrong <54477794+monkey-mode@users.noreply.github.com> Date: Mon, 23 Mar 2026 16:58:32 +0700 Subject: [PATCH] agent_ui: Fix pasted image context showing Image instead of actual filename (#52082) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What Fix image context mentions always showing the generic label `Image` instead of the actual filename when pasting from Finder or picking via the `+` → Image button in the Agent Panel. ## Why `insert_images_as_context` hardcoded the crease label to `MentionUri::PastedImage.name()` (`"Image"`) for every image, regardless of whether it originated from a named file. Both code paths that load images from file paths — `paste_images_as_context` and `add_images_from_picker` — discarded the filename before passing images to the shared insert function. ## Fix - `agent_ui/src/mention_set.rs`: Changed `insert_images_as_context` to accept `Vec<(gpui::Image, SharedString)>` instead of `Vec`, using the provided name as the crease label. In `paste_images_as_context`, extract `file_name()` from each path and pair it with the loaded image. Raw clipboard images (screenshots, copy from image editors) continue to use `"Image"` as there is no filename. - `agent_ui/src/message_editor.rs`: Same fix for `add_images_from_picker` — extract `file_name()` from each selected path and pass it alongside the image. Closes #52079 ## Test Plan - [x] `cargo build -p agent_ui` compiles clean - [x] `cargo fmt --all -- --check` format check - [x] Manual verification of: - [x] Copy an image file in Finder (`Cmd+C`), paste into Agent Panel — mention shows actual filename - [x] `+` → Image → pick a file — mention shows actual filename - [x] Screenshot paste (`Cmd+Shift+4`) still shows `Image` - [x] Regular text paste still works ## Screenshots image --- Release Notes: - Fixed image context mentions always showing `Image` instead of the actual filename when pasting from Finder or using the image picker in the Agent Panel --- crates/agent_ui/src/mention_set.rs | 45 ++++++++++++++++----------- crates/agent_ui/src/message_editor.rs | 7 ++++- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/crates/agent_ui/src/mention_set.rs b/crates/agent_ui/src/mention_set.rs index 877fb1eb6d9b5dea47393af63776e3eeca0668e5..c0aee0fc323977d9aa2822b592db0621c7061bba 100644 --- a/crates/agent_ui/src/mention_set.rs +++ b/crates/agent_ui/src/mention_set.rs @@ -739,7 +739,7 @@ mod tests { /// Inserts a list of images into the editor as context mentions. /// This is the shared implementation used by both paste and file picker operations. pub(crate) async fn insert_images_as_context( - images: Vec, + images: Vec<(gpui::Image, SharedString)>, editor: Entity, mention_set: Entity, workspace: WeakEntity, @@ -751,7 +751,7 @@ pub(crate) async fn insert_images_as_context( let replacement_text = MentionUri::PastedImage.as_link().to_string(); - for image in images { + for (image, name) in images { let Some((excerpt_id, text_anchor, multibuffer_anchor)) = editor .update_in(cx, |editor, window, cx| { let snapshot = editor.snapshot(window, cx); @@ -785,7 +785,7 @@ pub(crate) async fn insert_images_as_context( excerpt_id, text_anchor, content_len, - MentionUri::PastedImage.name().into(), + name.clone(), IconName::Image.path().into(), None, None, @@ -856,10 +856,11 @@ pub(crate) fn paste_images_as_context( Some(window.spawn(cx, async move |mut cx| { use itertools::Itertools; - let (mut images, paths) = clipboard + let default_name: SharedString = MentionUri::PastedImage.name().into(); + let (mut images, paths): (Vec<(gpui::Image, SharedString)>, Vec<_>) = clipboard .into_entries() .filter_map(|entry| match entry { - ClipboardEntry::Image(image) => Some(Either::Left(image)), + ClipboardEntry::Image(image) => Some(Either::Left((image, default_name.clone()))), ClipboardEntry::ExternalPaths(paths) => Some(Either::Right(paths)), _ => None, }) @@ -870,24 +871,32 @@ pub(crate) fn paste_images_as_context( cx.background_spawn(async move { let mut images = vec![]; for path in paths.into_iter().flat_map(|paths| paths.paths().to_owned()) { - let Ok(content) = async_fs::read(path).await else { + let Ok(content) = async_fs::read(&path).await else { continue; }; let Ok(format) = image::guess_format(&content) else { continue; }; - images.push(gpui::Image::from_bytes( - match format { - image::ImageFormat::Png => gpui::ImageFormat::Png, - image::ImageFormat::Jpeg => gpui::ImageFormat::Jpeg, - image::ImageFormat::WebP => gpui::ImageFormat::Webp, - image::ImageFormat::Gif => gpui::ImageFormat::Gif, - image::ImageFormat::Bmp => gpui::ImageFormat::Bmp, - image::ImageFormat::Tiff => gpui::ImageFormat::Tiff, - image::ImageFormat::Ico => gpui::ImageFormat::Ico, - _ => continue, - }, - content, + let name: SharedString = path + .file_name() + .and_then(|n| n.to_str()) + .map(|s| SharedString::from(s.to_owned())) + .unwrap_or_else(|| default_name.clone()); + images.push(( + gpui::Image::from_bytes( + match format { + image::ImageFormat::Png => gpui::ImageFormat::Png, + image::ImageFormat::Jpeg => gpui::ImageFormat::Jpeg, + image::ImageFormat::WebP => gpui::ImageFormat::Webp, + image::ImageFormat::Gif => gpui::ImageFormat::Gif, + image::ImageFormat::Bmp => gpui::ImageFormat::Bmp, + image::ImageFormat::Tiff => gpui::ImageFormat::Tiff, + image::ImageFormat::Ico => gpui::ImageFormat::Ico, + _ => continue, + }, + content, + ), + name, )); } images diff --git a/crates/agent_ui/src/message_editor.rs b/crates/agent_ui/src/message_editor.rs index 646058fe488dbdd14b78e466cf53734e81a7712c..993d52640d1449b623dc47f2af4b3155d202448e 100644 --- a/crates/agent_ui/src/message_editor.rs +++ b/crates/agent_ui/src/message_editor.rs @@ -1366,7 +1366,12 @@ impl MessageEditor { continue; }; - images.push(gpui::Image::from_bytes(format, content)); + let name: gpui::SharedString = path + .file_name() + .and_then(|n| n.to_str()) + .map(|s| gpui::SharedString::from(s.to_owned())) + .unwrap_or_else(|| "Image".into()); + images.push((gpui::Image::from_bytes(format, content), name)); } crate::mention_set::insert_images_as_context(