Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assistant2: Suggest current file as context #22526

Merged
merged 7 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions crates/assistant2/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use gpui::SharedString;
use language_model::{LanguageModelRequestMessage, MessageContent};
use project::ProjectEntryId;
use serde::{Deserialize, Serialize};
use util::post_inc;

Expand All @@ -23,7 +24,7 @@ pub struct Context {

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ContextKind {
File,
File(ProjectEntryId),
Directory,
FetchedUrl,
Thread,
Expand All @@ -40,7 +41,7 @@ pub fn attach_context_to_message(

for context in context.into_iter() {
match context.kind {
ContextKind::File => {
ContextKind::File(_) => {
file_context.push_str(&context.text);
file_context.push('\n');
}
Expand Down
27 changes: 17 additions & 10 deletions crates/assistant2/src/context_picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use ui::{prelude::*, ListItem, ListItemSpacing};
use util::ResultExt;
use workspace::Workspace;

use crate::context::ContextKind;
use crate::context_picker::directory_context_picker::DirectoryContextPicker;
use crate::context_picker::fetch_context_picker::FetchContextPicker;
use crate::context_picker::file_context_picker::FileContextPicker;
Expand Down Expand Up @@ -54,7 +53,7 @@ impl ContextPicker {
let mut entries = Vec::new();
entries.push(ContextPickerEntry {
name: "File".into(),
kind: ContextKind::File,
kind: ContextPickerEntryKind::File,
icon: IconName::File,
});
let release_channel = ReleaseChannel::global(cx);
Expand All @@ -63,20 +62,20 @@ impl ContextPicker {
if release_channel == ReleaseChannel::Dev {
entries.push(ContextPickerEntry {
name: "Folder".into(),
kind: ContextKind::Directory,
kind: ContextPickerEntryKind::Directory,
icon: IconName::Folder,
});
}
entries.push(ContextPickerEntry {
name: "Fetch".into(),
kind: ContextKind::FetchedUrl,
kind: ContextPickerEntryKind::FetchedUrl,
icon: IconName::Globe,
});

if thread_store.is_some() {
entries.push(ContextPickerEntry {
name: "Thread".into(),
kind: ContextKind::Thread,
kind: ContextPickerEntryKind::Thread,
icon: IconName::MessageCircle,
});
}
Expand Down Expand Up @@ -140,10 +139,18 @@ impl Render for ContextPicker {
#[derive(Clone)]
struct ContextPickerEntry {
name: SharedString,
kind: ContextKind,
kind: ContextPickerEntryKind,
icon: IconName,
}

#[derive(Debug, Clone)]
enum ContextPickerEntryKind {
File,
Directory,
FetchedUrl,
Thread,
}

pub(crate) struct ContextPickerDelegate {
context_picker: WeakView<ContextPicker>,
workspace: WeakView<Workspace>,
Expand Down Expand Up @@ -183,7 +190,7 @@ impl PickerDelegate for ContextPickerDelegate {
self.context_picker
.update(cx, |this, cx| {
match entry.kind {
ContextKind::File => {
ContextPickerEntryKind::File => {
this.mode = ContextPickerMode::File(cx.new_view(|cx| {
FileContextPicker::new(
self.context_picker.clone(),
Expand All @@ -194,7 +201,7 @@ impl PickerDelegate for ContextPickerDelegate {
)
}));
}
ContextKind::Directory => {
ContextPickerEntryKind::Directory => {
this.mode = ContextPickerMode::Directory(cx.new_view(|cx| {
DirectoryContextPicker::new(
self.context_picker.clone(),
Expand All @@ -205,7 +212,7 @@ impl PickerDelegate for ContextPickerDelegate {
)
}));
}
ContextKind::FetchedUrl => {
ContextPickerEntryKind::FetchedUrl => {
this.mode = ContextPickerMode::Fetch(cx.new_view(|cx| {
FetchContextPicker::new(
self.context_picker.clone(),
Expand All @@ -216,7 +223,7 @@ impl PickerDelegate for ContextPickerDelegate {
)
}));
}
ContextKind::Thread => {
ContextPickerEntryKind::Thread => {
if let Some(thread_store) = self.thread_store.as_ref() {
this.mode = ContextPickerMode::Thread(cx.new_view(|cx| {
ThreadContextPicker::new(
Expand Down
17 changes: 13 additions & 4 deletions crates/assistant2/src/context_picker/file_context_picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::sync::Arc;
use fuzzy::PathMatch;
use gpui::{AppContext, DismissEvent, FocusHandle, FocusableView, Task, View, WeakModel, WeakView};
use picker::{Picker, PickerDelegate};
use project::{PathMatchCandidateSet, WorktreeId};
use project::{PathMatchCandidateSet, ProjectPath, WorktreeId};
use ui::{prelude::*, ListItem};
use util::ResultExt as _;
use workspace::Workspace;
Expand Down Expand Up @@ -207,11 +207,20 @@ impl PickerDelegate for FileContextPickerDelegate {
let worktree_id = WorktreeId::from_usize(mat.worktree_id);
let confirm_behavior = self.confirm_behavior;
cx.spawn(|this, mut cx| async move {
let Some(open_buffer_task) = project
let Some((entry_id, open_buffer_task)) = project
.update(&mut cx, |project, cx| {
project.open_buffer((worktree_id, path.clone()), cx)
let project_path = ProjectPath {
worktree_id,
path: path.clone(),
};

let entry_id = project.entry_for_path(&project_path, cx)?.id;
let task = project.open_buffer(project_path, cx);

Some((entry_id, task))
})
.ok()
.flatten()
else {
return anyhow::Ok(());
};
Expand All @@ -232,7 +241,7 @@ impl PickerDelegate for FileContextPickerDelegate {
text.push_str("```\n");

context_store.insert_context(
ContextKind::File,
ContextKind::File(entry_id),
path.to_string_lossy().to_string(),
text,
);
Expand Down
10 changes: 10 additions & 0 deletions crates/assistant2/src/context_store.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use gpui::SharedString;
use project::ProjectEntryId;

use crate::context::{Context, ContextId, ContextKind};

Expand Down Expand Up @@ -44,4 +45,13 @@ impl ContextStore {
pub fn remove_context(&mut self, id: &ContextId) {
self.context.retain(|context| context.id != *id);
}

pub fn contains_project_entry(&self, entry_id: ProjectEntryId) -> bool {
self.context.iter().any(|probe| match probe.kind {
ContextKind::File(probe_entry_id) => probe_entry_id == entry_id,
ContextKind::Directory => false,
ContextKind::FetchedUrl => false,
ContextKind::Thread => false,
})
}
Comment on lines +49 to +56
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the linear search should be ok for the current usage, but we may want to consider an alternative approach if we use this to filter file_context_picker entries later.

}
Loading
Loading