agent: Show actual file name and icon in context pill (#31813)
Previously in the agent context pill if we added images it showed generic Image tag on the image context pill. This PR make sure if we have a path available for a image context show the filename which is in line with other context pills. Before | After --- | ---  |  Release Notes: - N/A --------- Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
This commit is contained in:
parent
ae219e9e99
commit
9c715b470e
3 changed files with 81 additions and 50 deletions
|
@ -734,6 +734,7 @@ impl Display for RulesContext {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ImageContext {
|
pub struct ImageContext {
|
||||||
pub project_path: Option<ProjectPath>,
|
pub project_path: Option<ProjectPath>,
|
||||||
|
pub full_path: Option<Arc<Path>>,
|
||||||
pub original_image: Arc<gpui::Image>,
|
pub original_image: Arc<gpui::Image>,
|
||||||
// TODO: handle this elsewhere and remove `ignore-interior-mutability` opt-out in clippy.toml
|
// TODO: handle this elsewhere and remove `ignore-interior-mutability` opt-out in clippy.toml
|
||||||
// needed due to a false positive of `clippy::mutable_key_type`.
|
// needed due to a false positive of `clippy::mutable_key_type`.
|
||||||
|
|
|
@ -7,7 +7,7 @@ use assistant_context_editor::AssistantContext;
|
||||||
use collections::{HashSet, IndexSet};
|
use collections::{HashSet, IndexSet};
|
||||||
use futures::{self, FutureExt};
|
use futures::{self, FutureExt};
|
||||||
use gpui::{App, Context, Entity, EventEmitter, Image, SharedString, Task, WeakEntity};
|
use gpui::{App, Context, Entity, EventEmitter, Image, SharedString, Task, WeakEntity};
|
||||||
use language::Buffer;
|
use language::{Buffer, File as _};
|
||||||
use language_model::LanguageModelImage;
|
use language_model::LanguageModelImage;
|
||||||
use project::image_store::is_image_file;
|
use project::image_store::is_image_file;
|
||||||
use project::{Project, ProjectItem, ProjectPath, Symbol};
|
use project::{Project, ProjectItem, ProjectPath, Symbol};
|
||||||
|
@ -304,11 +304,13 @@ impl ContextStore {
|
||||||
project.open_image(project_path.clone(), cx)
|
project.open_image(project_path.clone(), cx)
|
||||||
})?;
|
})?;
|
||||||
let image_item = open_image_task.await?;
|
let image_item = open_image_task.await?;
|
||||||
let image = image_item.read_with(cx, |image_item, _| image_item.image.clone())?;
|
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
|
let item = image_item.read(cx);
|
||||||
this.insert_image(
|
this.insert_image(
|
||||||
Some(image_item.read(cx).project_path(cx)),
|
Some(item.project_path(cx)),
|
||||||
image,
|
Some(item.file.full_path(cx).into()),
|
||||||
|
item.image.clone(),
|
||||||
remove_if_exists,
|
remove_if_exists,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
@ -317,12 +319,13 @@ impl ContextStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_image_instance(&mut self, image: Arc<Image>, cx: &mut Context<ContextStore>) {
|
pub fn add_image_instance(&mut self, image: Arc<Image>, cx: &mut Context<ContextStore>) {
|
||||||
self.insert_image(None, image, false, cx);
|
self.insert_image(None, None, image, false, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_image(
|
fn insert_image(
|
||||||
&mut self,
|
&mut self,
|
||||||
project_path: Option<ProjectPath>,
|
project_path: Option<ProjectPath>,
|
||||||
|
full_path: Option<Arc<Path>>,
|
||||||
image: Arc<Image>,
|
image: Arc<Image>,
|
||||||
remove_if_exists: bool,
|
remove_if_exists: bool,
|
||||||
cx: &mut Context<ContextStore>,
|
cx: &mut Context<ContextStore>,
|
||||||
|
@ -330,6 +333,7 @@ impl ContextStore {
|
||||||
let image_task = LanguageModelImage::from_image(image.clone(), cx).shared();
|
let image_task = LanguageModelImage::from_image(image.clone(), cx).shared();
|
||||||
let context = AgentContextHandle::Image(ImageContext {
|
let context = AgentContextHandle::Image(ImageContext {
|
||||||
project_path,
|
project_path,
|
||||||
|
full_path,
|
||||||
original_image: image,
|
original_image: image,
|
||||||
image_task,
|
image_task,
|
||||||
context_id: self.next_context_id.post_inc(),
|
context_id: self.next_context_id.post_inc(),
|
||||||
|
|
|
@ -304,7 +304,7 @@ impl AddedContext {
|
||||||
AgentContextHandle::Thread(handle) => Some(Self::pending_thread(handle, cx)),
|
AgentContextHandle::Thread(handle) => Some(Self::pending_thread(handle, cx)),
|
||||||
AgentContextHandle::TextThread(handle) => Some(Self::pending_text_thread(handle, cx)),
|
AgentContextHandle::TextThread(handle) => Some(Self::pending_text_thread(handle, cx)),
|
||||||
AgentContextHandle::Rules(handle) => Self::pending_rules(handle, prompt_store, cx),
|
AgentContextHandle::Rules(handle) => Self::pending_rules(handle, prompt_store, cx),
|
||||||
AgentContextHandle::Image(handle) => Some(Self::image(handle)),
|
AgentContextHandle::Image(handle) => Some(Self::image(handle, cx)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ impl AddedContext {
|
||||||
AgentContext::Thread(context) => Self::attached_thread(context),
|
AgentContext::Thread(context) => Self::attached_thread(context),
|
||||||
AgentContext::TextThread(context) => Self::attached_text_thread(context),
|
AgentContext::TextThread(context) => Self::attached_text_thread(context),
|
||||||
AgentContext::Rules(context) => Self::attached_rules(context),
|
AgentContext::Rules(context) => Self::attached_rules(context),
|
||||||
AgentContext::Image(context) => Self::image(context.clone()),
|
AgentContext::Image(context) => Self::image(context.clone(), cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,14 +333,8 @@ impl AddedContext {
|
||||||
|
|
||||||
fn file(handle: FileContextHandle, full_path: &Path, cx: &App) -> AddedContext {
|
fn file(handle: FileContextHandle, full_path: &Path, cx: &App) -> AddedContext {
|
||||||
let full_path_string: SharedString = full_path.to_string_lossy().into_owned().into();
|
let full_path_string: SharedString = full_path.to_string_lossy().into_owned().into();
|
||||||
let name = full_path
|
let (name, parent) =
|
||||||
.file_name()
|
extract_file_name_and_directory_from_full_path(full_path, &full_path_string);
|
||||||
.map(|n| n.to_string_lossy().into_owned().into())
|
|
||||||
.unwrap_or_else(|| full_path_string.clone());
|
|
||||||
let parent = full_path
|
|
||||||
.parent()
|
|
||||||
.and_then(|p| p.file_name())
|
|
||||||
.map(|n| n.to_string_lossy().into_owned().into());
|
|
||||||
AddedContext {
|
AddedContext {
|
||||||
kind: ContextKind::File,
|
kind: ContextKind::File,
|
||||||
name,
|
name,
|
||||||
|
@ -370,14 +364,8 @@ impl AddedContext {
|
||||||
|
|
||||||
fn directory(handle: DirectoryContextHandle, full_path: &Path) -> AddedContext {
|
fn directory(handle: DirectoryContextHandle, full_path: &Path) -> AddedContext {
|
||||||
let full_path_string: SharedString = full_path.to_string_lossy().into_owned().into();
|
let full_path_string: SharedString = full_path.to_string_lossy().into_owned().into();
|
||||||
let name = full_path
|
let (name, parent) =
|
||||||
.file_name()
|
extract_file_name_and_directory_from_full_path(full_path, &full_path_string);
|
||||||
.map(|n| n.to_string_lossy().into_owned().into())
|
|
||||||
.unwrap_or_else(|| full_path_string.clone());
|
|
||||||
let parent = full_path
|
|
||||||
.parent()
|
|
||||||
.and_then(|p| p.file_name())
|
|
||||||
.map(|n| n.to_string_lossy().into_owned().into());
|
|
||||||
AddedContext {
|
AddedContext {
|
||||||
kind: ContextKind::Directory,
|
kind: ContextKind::Directory,
|
||||||
name,
|
name,
|
||||||
|
@ -605,13 +593,23 @@ impl AddedContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn image(context: ImageContext) -> AddedContext {
|
fn image(context: ImageContext, cx: &App) -> AddedContext {
|
||||||
|
let (name, parent, icon_path) = if let Some(full_path) = context.full_path.as_ref() {
|
||||||
|
let full_path_string: SharedString = full_path.to_string_lossy().into_owned().into();
|
||||||
|
let (name, parent) =
|
||||||
|
extract_file_name_and_directory_from_full_path(full_path, &full_path_string);
|
||||||
|
let icon_path = FileIcons::get_icon(&full_path, cx);
|
||||||
|
(name, parent, icon_path)
|
||||||
|
} else {
|
||||||
|
("Image".into(), None, None)
|
||||||
|
};
|
||||||
|
|
||||||
AddedContext {
|
AddedContext {
|
||||||
kind: ContextKind::Image,
|
kind: ContextKind::Image,
|
||||||
name: "Image".into(),
|
name,
|
||||||
parent: None,
|
parent,
|
||||||
tooltip: None,
|
tooltip: None,
|
||||||
icon_path: None,
|
icon_path,
|
||||||
status: match context.status() {
|
status: match context.status() {
|
||||||
ImageStatus::Loading => ContextStatus::Loading {
|
ImageStatus::Loading => ContextStatus::Loading {
|
||||||
message: "Loading…".into(),
|
message: "Loading…".into(),
|
||||||
|
@ -639,6 +637,22 @@ impl AddedContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extract_file_name_and_directory_from_full_path(
|
||||||
|
path: &Path,
|
||||||
|
name_fallback: &SharedString,
|
||||||
|
) -> (SharedString, Option<SharedString>) {
|
||||||
|
let name = path
|
||||||
|
.file_name()
|
||||||
|
.map(|n| n.to_string_lossy().into_owned().into())
|
||||||
|
.unwrap_or_else(|| name_fallback.clone());
|
||||||
|
let parent = path
|
||||||
|
.parent()
|
||||||
|
.and_then(|p| p.file_name())
|
||||||
|
.map(|n| n.to_string_lossy().into_owned().into());
|
||||||
|
|
||||||
|
(name, parent)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct ContextFileExcerpt {
|
struct ContextFileExcerpt {
|
||||||
pub file_name_and_range: SharedString,
|
pub file_name_and_range: SharedString,
|
||||||
|
@ -765,19 +779,25 @@ impl Component for AddedContext {
|
||||||
let mut next_context_id = ContextId::zero();
|
let mut next_context_id = ContextId::zero();
|
||||||
let image_ready = (
|
let image_ready = (
|
||||||
"Ready",
|
"Ready",
|
||||||
AddedContext::image(ImageContext {
|
AddedContext::image(
|
||||||
|
ImageContext {
|
||||||
context_id: next_context_id.post_inc(),
|
context_id: next_context_id.post_inc(),
|
||||||
project_path: None,
|
project_path: None,
|
||||||
|
full_path: None,
|
||||||
original_image: Arc::new(Image::empty()),
|
original_image: Arc::new(Image::empty()),
|
||||||
image_task: Task::ready(Some(LanguageModelImage::empty())).shared(),
|
image_task: Task::ready(Some(LanguageModelImage::empty())).shared(),
|
||||||
}),
|
},
|
||||||
|
cx,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
let image_loading = (
|
let image_loading = (
|
||||||
"Loading",
|
"Loading",
|
||||||
AddedContext::image(ImageContext {
|
AddedContext::image(
|
||||||
|
ImageContext {
|
||||||
context_id: next_context_id.post_inc(),
|
context_id: next_context_id.post_inc(),
|
||||||
project_path: None,
|
project_path: None,
|
||||||
|
full_path: None,
|
||||||
original_image: Arc::new(Image::empty()),
|
original_image: Arc::new(Image::empty()),
|
||||||
image_task: cx
|
image_task: cx
|
||||||
.background_spawn(async move {
|
.background_spawn(async move {
|
||||||
|
@ -785,17 +805,23 @@ impl Component for AddedContext {
|
||||||
Some(LanguageModelImage::empty())
|
Some(LanguageModelImage::empty())
|
||||||
})
|
})
|
||||||
.shared(),
|
.shared(),
|
||||||
}),
|
},
|
||||||
|
cx,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
let image_error = (
|
let image_error = (
|
||||||
"Error",
|
"Error",
|
||||||
AddedContext::image(ImageContext {
|
AddedContext::image(
|
||||||
|
ImageContext {
|
||||||
context_id: next_context_id.post_inc(),
|
context_id: next_context_id.post_inc(),
|
||||||
project_path: None,
|
project_path: None,
|
||||||
|
full_path: None,
|
||||||
original_image: Arc::new(Image::empty()),
|
original_image: Arc::new(Image::empty()),
|
||||||
image_task: Task::ready(None).shared(),
|
image_task: Task::ready(None).shared(),
|
||||||
}),
|
},
|
||||||
|
cx,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue