Handle fetch completions
Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
parent
2f6c9e3a2b
commit
46ed71fb9a
2 changed files with 91 additions and 26 deletions
|
@ -1229,15 +1229,7 @@ impl AgentMessage {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
MentionUri::Fetch { url } => {
|
MentionUri::Fetch { url } => {
|
||||||
write!(
|
write!(&mut fetch_context, "\nFetch: {}\n\n{}", url, content).ok();
|
||||||
&mut fetch_context,
|
|
||||||
"\n{}",
|
|
||||||
MarkdownCodeBlock {
|
|
||||||
tag: &format!("md {url}"),
|
|
||||||
text: &content
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,14 @@ use text::{Anchor, OffsetRangeExt as _, ToPoint as _};
|
||||||
use ui::prelude::*;
|
use ui::prelude::*;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
use workspace::notifications::NotifyResultExt;
|
||||||
|
|
||||||
use agent::{
|
use agent::{
|
||||||
context::RULES_ICON,
|
context::RULES_ICON,
|
||||||
thread_store::{TextThreadStore, ThreadStore},
|
thread_store::{TextThreadStore, ThreadStore},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::context_picker::fetch_context_picker::fetch_url_content;
|
||||||
use crate::context_picker::file_context_picker::{FileMatch, search_files};
|
use crate::context_picker::file_context_picker::{FileMatch, search_files};
|
||||||
use crate::context_picker::rules_context_picker::{RulesContextEntry, search_rules};
|
use crate::context_picker::rules_context_picker::{RulesContextEntry, search_rules};
|
||||||
use crate::context_picker::symbol_context_picker::SymbolMatch;
|
use crate::context_picker::symbol_context_picker::SymbolMatch;
|
||||||
|
@ -55,6 +57,10 @@ impl MentionSet {
|
||||||
self.uri_by_crease_id.insert(crease_id, uri);
|
self.uri_by_crease_id.insert(crease_id, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_fetch_result(&mut self, url: Url, content: String) {
|
||||||
|
self.fetch_results.insert(url, content);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn drain(&mut self) -> impl Iterator<Item = CreaseId> {
|
pub fn drain(&mut self) -> impl Iterator<Item = CreaseId> {
|
||||||
self.uri_by_crease_id.drain().map(|(id, _)| id)
|
self.uri_by_crease_id.drain().map(|(id, _)| id)
|
||||||
}
|
}
|
||||||
|
@ -279,8 +285,11 @@ fn search(
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(ContextPickerMode::Fetch) => {
|
Some(ContextPickerMode::Fetch) => {
|
||||||
// todo! make a new mode type for acp?
|
if !query.is_empty() {
|
||||||
unreachable!()
|
Task::ready(vec![Match::Fetch(query.into())])
|
||||||
|
} else {
|
||||||
|
Task::ready(Vec::new())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(ContextPickerMode::Rules) => {
|
Some(ContextPickerMode::Rules) => {
|
||||||
|
@ -750,9 +759,7 @@ impl ContextPickerCompletionProvider {
|
||||||
mention_set: Arc<Mutex<MentionSet>>,
|
mention_set: Arc<Mutex<MentionSet>>,
|
||||||
http_client: Arc<HttpClientWithUrl>,
|
http_client: Arc<HttpClientWithUrl>,
|
||||||
) -> Option<Completion> {
|
) -> Option<Completion> {
|
||||||
let url = url::Url::parse(url_to_fetch.as_ref()).ok()?;
|
let new_text = format!("@fetch {} ", url_to_fetch.clone());
|
||||||
let mention_uri = MentionUri::Fetch { url };
|
|
||||||
let new_text = format!("{} ", mention_uri.as_link());
|
|
||||||
let new_text_len = new_text.len();
|
let new_text_len = new_text.len();
|
||||||
Some(Completion {
|
Some(Completion {
|
||||||
replace_range: source_range.clone(),
|
replace_range: source_range.clone(),
|
||||||
|
@ -762,17 +769,82 @@ impl ContextPickerCompletionProvider {
|
||||||
source: project::CompletionSource::Custom,
|
source: project::CompletionSource::Custom,
|
||||||
icon_path: Some(IconName::ToolWeb.path().into()),
|
icon_path: Some(IconName::ToolWeb.path().into()),
|
||||||
insert_text_mode: None,
|
insert_text_mode: None,
|
||||||
// todo! custom callback to fetch
|
confirm: Some({
|
||||||
confirm: Some(confirm_completion_callback(
|
let start = source_range.start;
|
||||||
IconName::ToolWeb.path().into(),
|
let content_len = new_text_len - 1;
|
||||||
url_to_fetch.clone(),
|
let editor = editor.clone();
|
||||||
excerpt_id,
|
let url_to_fetch = url_to_fetch.clone();
|
||||||
source_range.start,
|
let source_range = source_range.clone();
|
||||||
new_text_len - 1,
|
Arc::new(move |_, window, cx| {
|
||||||
editor.clone(),
|
let Some(url) = url::Url::parse(url_to_fetch.as_ref())
|
||||||
mention_set,
|
.or_else(|_| url::Url::parse(&format!("https://{url_to_fetch}")))
|
||||||
mention_uri,
|
.notify_app_err(cx)
|
||||||
)),
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let mention_uri = MentionUri::Fetch { url: url.clone() };
|
||||||
|
|
||||||
|
let editor = editor.clone();
|
||||||
|
let mention_set = mention_set.clone();
|
||||||
|
let http_client = http_client.clone();
|
||||||
|
let source_range = source_range.clone();
|
||||||
|
window.defer(cx, move |window, cx| {
|
||||||
|
let url = url.clone();
|
||||||
|
|
||||||
|
let Some(crease_id) = crate::context_picker::insert_crease_for_mention(
|
||||||
|
excerpt_id,
|
||||||
|
start,
|
||||||
|
content_len,
|
||||||
|
url.to_string().into(),
|
||||||
|
IconName::ToolWeb.path().into(),
|
||||||
|
editor.clone(),
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let editor = editor.clone();
|
||||||
|
let mention_set = mention_set.clone();
|
||||||
|
let http_client = http_client.clone();
|
||||||
|
let source_range = source_range.clone();
|
||||||
|
window
|
||||||
|
.spawn(cx, async move |cx| {
|
||||||
|
if let Some(content) =
|
||||||
|
fetch_url_content(http_client, url.to_string())
|
||||||
|
.await
|
||||||
|
.notify_async_err(cx)
|
||||||
|
{
|
||||||
|
mention_set.lock().add_fetch_result(url, content);
|
||||||
|
mention_set.lock().insert(crease_id, mention_uri.clone());
|
||||||
|
} else {
|
||||||
|
// Remove crease if we failed to fetch
|
||||||
|
editor
|
||||||
|
.update(cx, |editor, cx| {
|
||||||
|
let snapshot = editor.buffer().read(cx).snapshot(cx);
|
||||||
|
let Some(anchor) = snapshot
|
||||||
|
.anchor_in_excerpt(excerpt_id, source_range.start)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
editor.display_map.update(cx, |display_map, cx| {
|
||||||
|
display_map.unfold_intersecting(
|
||||||
|
vec![anchor..anchor],
|
||||||
|
true,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
editor.remove_creases([crease_id], cx);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
Some(())
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
});
|
||||||
|
false
|
||||||
|
})
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -820,6 +892,7 @@ impl CompletionProvider for ContextPickerCompletionProvider {
|
||||||
};
|
};
|
||||||
|
|
||||||
let project = workspace.read(cx).project().clone();
|
let project = workspace.read(cx).project().clone();
|
||||||
|
let http_client = workspace.read(cx).client().http_client();
|
||||||
let snapshot = buffer.read(cx).snapshot();
|
let snapshot = buffer.read(cx).snapshot();
|
||||||
let source_range = snapshot.anchor_before(state.source_range.start)
|
let source_range = snapshot.anchor_before(state.source_range.start)
|
||||||
..snapshot.anchor_after(state.source_range.end);
|
..snapshot.anchor_after(state.source_range.end);
|
||||||
|
@ -945,7 +1018,7 @@ impl CompletionProvider for ContextPickerCompletionProvider {
|
||||||
excerpt_id,
|
excerpt_id,
|
||||||
editor.clone(),
|
editor.clone(),
|
||||||
mention_set.clone(),
|
mention_set.clone(),
|
||||||
todo!(),
|
http_client.clone(),
|
||||||
),
|
),
|
||||||
|
|
||||||
Match::Entry(EntryMatch { entry, .. }) => Self::completion_for_entry(
|
Match::Entry(EntryMatch { entry, .. }) => Self::completion_for_entry(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue