diff --git a/crates/agent_ui/src/message_editor.rs b/crates/agent_ui/src/message_editor.rs index c6e52939d6..ab084d46a6 100644 --- a/crates/agent_ui/src/message_editor.rs +++ b/crates/agent_ui/src/message_editor.rs @@ -13,6 +13,7 @@ use acp_thread::MentionUri; use agent::ThreadStore; use agent_client_protocol::schema as acp; use anyhow::{Result, anyhow}; +use base64::Engine as _; use editor::{ Addon, AnchorRangeExt, ContextMenuOptions, Editor, EditorElement, EditorEvent, EditorMode, EditorStyle, Inlay, MultiBuffer, MultiBufferOffset, MultiBufferSnapshot, ToOffset, @@ -24,8 +25,8 @@ use editor::{ use futures::{FutureExt as _, future::join_all}; use gpui::{ AppContext, ClipboardEntry, ClipboardItem, Context, Entity, EventEmitter, FocusHandle, - Focusable, ImageFormat, KeyContext, SharedString, Subscription, Task, TaskExt, TextStyle, - WeakEntity, + Focusable, Image, ImageFormat, KeyContext, SharedString, Subscription, Task, TaskExt, + TextStyle, WeakEntity, }; use language::{Buffer, language_settings::InlayHintKind}; use parking_lot::RwLock; @@ -1815,6 +1816,7 @@ impl MessageEditor { for (range, mention_uri, mention) in mentions { let adjusted_start = insertion_start + range.start; let anchor = snapshot.anchor_before(MultiBufferOffset(adjusted_start)); + let image_preview = image_preview_task_for_mention(&mention); let Some((crease_id, tx, crease_entity)) = insert_crease_for_mention( snapshot.anchor_to_buffer_anchor(anchor).unwrap().0, range.end - range.start, @@ -1823,7 +1825,7 @@ impl MessageEditor { mention_uri.tooltip_text(), Some(mention_uri.clone()), Some(self.workspace.clone()), - None, + image_preview, self.editor.clone(), window, cx, @@ -2094,6 +2096,31 @@ fn build_chunks_from_creases( (chunks, tracked_buffers) } +fn image_preview_task_for_mention( + mention: &Mention, +) -> Option, String>>>> { + let Mention::Image(mention_image) = mention else { + return None; + }; + + let bytes = + match base64::engine::general_purpose::STANDARD.decode(mention_image.data.as_bytes()) { + Ok(bytes) => bytes, + Err(error) => { + log::error!("failed to decode image mention: {error}"); + return None; + } + }; + + Some( + Task::ready(Ok::, String>(Arc::new(Image::from_bytes( + mention_image.format, + bytes, + )))) + .shared(), + ) +} + fn mention_to_content_block( uri: &MentionUri, mention: Option<&Mention>,