agent2: Start loading mentioned threads and text threads as soon as they're added (#36374)
Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
parent
8282b9cf00
commit
2dbc951058
1 changed files with 217 additions and 83 deletions
|
@ -207,11 +207,13 @@ impl MessageEditor {
|
|||
cx,
|
||||
);
|
||||
}
|
||||
MentionUri::Symbol { .. }
|
||||
| MentionUri::Thread { .. }
|
||||
| MentionUri::TextThread { .. }
|
||||
| MentionUri::Rule { .. }
|
||||
| MentionUri::Selection { .. } => {
|
||||
MentionUri::Thread { id, name } => {
|
||||
self.confirm_mention_for_thread(crease_id, anchor, id, name, window, cx);
|
||||
}
|
||||
MentionUri::TextThread { path, name } => {
|
||||
self.confirm_mention_for_text_thread(crease_id, anchor, path, name, window, cx);
|
||||
}
|
||||
MentionUri::Symbol { .. } | MentionUri::Rule { .. } | MentionUri::Selection { .. } => {
|
||||
self.mention_set.insert_uri(crease_id, mention_uri.clone());
|
||||
}
|
||||
}
|
||||
|
@ -363,13 +365,9 @@ impl MessageEditor {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Task<Result<Vec<acp::ContentBlock>>> {
|
||||
let contents = self.mention_set.contents(
|
||||
self.project.clone(),
|
||||
self.thread_store.clone(),
|
||||
self.text_thread_store.clone(),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let contents =
|
||||
self.mention_set
|
||||
.contents(self.project.clone(), self.thread_store.clone(), window, cx);
|
||||
let editor = self.editor.clone();
|
||||
|
||||
cx.spawn(async move |_, cx| {
|
||||
|
@ -591,52 +589,154 @@ impl MessageEditor {
|
|||
) {
|
||||
let editor = self.editor.clone();
|
||||
let task = cx
|
||||
.spawn_in(window, async move |this, cx| {
|
||||
let image = image.await.map_err(|e| e.to_string())?;
|
||||
let format = image.format;
|
||||
let image = cx
|
||||
.update(|_, cx| LanguageModelImage::from_image(image, cx))
|
||||
.map_err(|e| e.to_string())?
|
||||
.await;
|
||||
if let Some(image) = image {
|
||||
if let Some(abs_path) = abs_path.clone() {
|
||||
this.update(cx, |this, _cx| {
|
||||
this.mention_set.insert_uri(
|
||||
crease_id,
|
||||
MentionUri::File {
|
||||
abs_path,
|
||||
is_directory: false,
|
||||
},
|
||||
);
|
||||
.spawn_in(window, {
|
||||
let abs_path = abs_path.clone();
|
||||
async move |_, cx| {
|
||||
let image = image.await.map_err(|e| e.to_string())?;
|
||||
let format = image.format;
|
||||
let image = cx
|
||||
.update(|_, cx| LanguageModelImage::from_image(image, cx))
|
||||
.map_err(|e| e.to_string())?
|
||||
.await;
|
||||
if let Some(image) = image {
|
||||
Ok(MentionImage {
|
||||
abs_path,
|
||||
data: image.source,
|
||||
format,
|
||||
})
|
||||
.map_err(|e| e.to_string())?;
|
||||
} else {
|
||||
Err("Failed to convert image".into())
|
||||
}
|
||||
Ok(MentionImage {
|
||||
abs_path,
|
||||
data: image.source,
|
||||
format,
|
||||
})
|
||||
} else {
|
||||
editor
|
||||
.update(cx, |editor, cx| {
|
||||
editor.display_map.update(cx, |display_map, cx| {
|
||||
display_map.unfold_intersecting(vec![anchor..anchor], true, cx);
|
||||
});
|
||||
editor.remove_creases([crease_id], cx);
|
||||
})
|
||||
.ok();
|
||||
Err("Failed to convert image".to_string())
|
||||
}
|
||||
})
|
||||
.shared();
|
||||
|
||||
cx.spawn_in(window, {
|
||||
let task = task.clone();
|
||||
async move |_, cx| task.clone().await.notify_async_err(cx)
|
||||
self.mention_set.insert_image(crease_id, task.clone());
|
||||
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if task.await.notify_async_err(cx).is_some() {
|
||||
if let Some(abs_path) = abs_path.clone() {
|
||||
this.update(cx, |this, _cx| {
|
||||
this.mention_set.insert_uri(
|
||||
crease_id,
|
||||
MentionUri::File {
|
||||
abs_path,
|
||||
is_directory: false,
|
||||
},
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
} else {
|
||||
editor
|
||||
.update(cx, |editor, cx| {
|
||||
editor.display_map.update(cx, |display_map, cx| {
|
||||
display_map.unfold_intersecting(vec![anchor..anchor], true, cx);
|
||||
});
|
||||
editor.remove_creases([crease_id], cx);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
self.mention_set.insert_image(crease_id, task);
|
||||
fn confirm_mention_for_thread(
|
||||
&mut self,
|
||||
crease_id: CreaseId,
|
||||
anchor: Anchor,
|
||||
id: ThreadId,
|
||||
name: String,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let uri = MentionUri::Thread {
|
||||
id: id.clone(),
|
||||
name,
|
||||
};
|
||||
let open_task = self.thread_store.update(cx, |thread_store, cx| {
|
||||
thread_store.open_thread(&id, window, cx)
|
||||
});
|
||||
let task = cx
|
||||
.spawn(async move |_, cx| {
|
||||
let thread = open_task.await.map_err(|e| e.to_string())?;
|
||||
let content = thread
|
||||
.read_with(cx, |thread, _cx| thread.latest_detailed_summary_or_text())
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(content)
|
||||
})
|
||||
.shared();
|
||||
|
||||
self.mention_set.insert_thread(id, task.clone());
|
||||
|
||||
let editor = self.editor.clone();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if task.await.notify_async_err(cx).is_some() {
|
||||
this.update(cx, |this, _| {
|
||||
this.mention_set.insert_uri(crease_id, uri);
|
||||
})
|
||||
.ok();
|
||||
} else {
|
||||
editor
|
||||
.update(cx, |editor, cx| {
|
||||
editor.display_map.update(cx, |display_map, cx| {
|
||||
display_map.unfold_intersecting(vec![anchor..anchor], true, cx);
|
||||
});
|
||||
editor.remove_creases([crease_id], cx);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn confirm_mention_for_text_thread(
|
||||
&mut self,
|
||||
crease_id: CreaseId,
|
||||
anchor: Anchor,
|
||||
path: PathBuf,
|
||||
name: String,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let uri = MentionUri::TextThread {
|
||||
path: path.clone(),
|
||||
name,
|
||||
};
|
||||
let context = self.text_thread_store.update(cx, |text_thread_store, cx| {
|
||||
text_thread_store.open_local_context(path.as_path().into(), cx)
|
||||
});
|
||||
let task = cx
|
||||
.spawn(async move |_, cx| {
|
||||
let context = context.await.map_err(|e| e.to_string())?;
|
||||
let xml = context
|
||||
.update(cx, |context, cx| context.to_xml(cx))
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(xml)
|
||||
})
|
||||
.shared();
|
||||
|
||||
self.mention_set.insert_text_thread(path, task.clone());
|
||||
|
||||
let editor = self.editor.clone();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if task.await.notify_async_err(cx).is_some() {
|
||||
this.update(cx, |this, _| {
|
||||
this.mention_set.insert_uri(crease_id, uri);
|
||||
})
|
||||
.ok();
|
||||
} else {
|
||||
editor
|
||||
.update(cx, |editor, cx| {
|
||||
editor.display_map.update(cx, |display_map, cx| {
|
||||
display_map.unfold_intersecting(vec![anchor..anchor], true, cx);
|
||||
});
|
||||
editor.remove_creases([crease_id], cx);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn set_mode(&mut self, mode: EditorMode, cx: &mut Context<Self>) {
|
||||
|
@ -671,7 +771,7 @@ impl MessageEditor {
|
|||
let start = text.len();
|
||||
write!(&mut text, "{}", mention_uri.as_link()).ok();
|
||||
let end = text.len();
|
||||
mentions.push((start..end, mention_uri));
|
||||
mentions.push((start..end, mention_uri, resource.text));
|
||||
}
|
||||
}
|
||||
acp::ContentBlock::Image(content) => {
|
||||
|
@ -691,7 +791,7 @@ impl MessageEditor {
|
|||
editor.buffer().read(cx).snapshot(cx)
|
||||
});
|
||||
|
||||
for (range, mention_uri) in mentions {
|
||||
for (range, mention_uri, text) in mentions {
|
||||
let anchor = snapshot.anchor_before(range.start);
|
||||
let crease_id = crate::context_picker::insert_crease_for_mention(
|
||||
anchor.excerpt_id,
|
||||
|
@ -705,7 +805,26 @@ impl MessageEditor {
|
|||
);
|
||||
|
||||
if let Some(crease_id) = crease_id {
|
||||
self.mention_set.insert_uri(crease_id, mention_uri);
|
||||
self.mention_set.insert_uri(crease_id, mention_uri.clone());
|
||||
}
|
||||
|
||||
match mention_uri {
|
||||
MentionUri::Thread { id, .. } => {
|
||||
self.mention_set
|
||||
.insert_thread(id, Task::ready(Ok(text.into())).shared());
|
||||
}
|
||||
MentionUri::TextThread { path, .. } => {
|
||||
self.mention_set
|
||||
.insert_text_thread(path, Task::ready(Ok(text)).shared());
|
||||
}
|
||||
MentionUri::Fetch { url } => {
|
||||
self.mention_set
|
||||
.add_fetch_result(url, Task::ready(Ok(text)).shared());
|
||||
}
|
||||
MentionUri::File { .. }
|
||||
| MentionUri::Symbol { .. }
|
||||
| MentionUri::Rule { .. }
|
||||
| MentionUri::Selection { .. } => {}
|
||||
}
|
||||
}
|
||||
for (range, content) in images {
|
||||
|
@ -905,9 +1024,11 @@ pub struct MentionImage {
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct MentionSet {
|
||||
pub(crate) uri_by_crease_id: HashMap<CreaseId, MentionUri>,
|
||||
uri_by_crease_id: HashMap<CreaseId, MentionUri>,
|
||||
fetch_results: HashMap<Url, Shared<Task<Result<String, String>>>>,
|
||||
images: HashMap<CreaseId, Shared<Task<Result<MentionImage, String>>>>,
|
||||
thread_summaries: HashMap<ThreadId, Shared<Task<Result<SharedString, String>>>>,
|
||||
text_thread_summaries: HashMap<PathBuf, Shared<Task<Result<String, String>>>>,
|
||||
}
|
||||
|
||||
impl MentionSet {
|
||||
|
@ -927,8 +1048,18 @@ impl MentionSet {
|
|||
self.images.insert(crease_id, task);
|
||||
}
|
||||
|
||||
fn insert_thread(&mut self, id: ThreadId, task: Shared<Task<Result<SharedString, String>>>) {
|
||||
self.thread_summaries.insert(id, task);
|
||||
}
|
||||
|
||||
fn insert_text_thread(&mut self, path: PathBuf, task: Shared<Task<Result<String, String>>>) {
|
||||
self.text_thread_summaries.insert(path, task);
|
||||
}
|
||||
|
||||
pub fn drain(&mut self) -> impl Iterator<Item = CreaseId> {
|
||||
self.fetch_results.clear();
|
||||
self.thread_summaries.clear();
|
||||
self.text_thread_summaries.clear();
|
||||
self.uri_by_crease_id
|
||||
.drain()
|
||||
.map(|(id, _)| id)
|
||||
|
@ -939,8 +1070,7 @@ impl MentionSet {
|
|||
&self,
|
||||
project: Entity<Project>,
|
||||
thread_store: Entity<ThreadStore>,
|
||||
text_thread_store: Entity<TextThreadStore>,
|
||||
window: &mut Window,
|
||||
_window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Task<Result<HashMap<CreaseId, Mention>>> {
|
||||
let mut processed_image_creases = HashSet::default();
|
||||
|
@ -1010,30 +1140,40 @@ impl MentionSet {
|
|||
anyhow::Ok((crease_id, Mention::Text { uri, content }))
|
||||
})
|
||||
}
|
||||
MentionUri::Thread { id: thread_id, .. } => {
|
||||
let open_task = thread_store.update(cx, |thread_store, cx| {
|
||||
thread_store.open_thread(&thread_id, window, cx)
|
||||
});
|
||||
|
||||
MentionUri::Thread { id, .. } => {
|
||||
let Some(content) = self.thread_summaries.get(id).cloned() else {
|
||||
return Task::ready(Err(anyhow!("missing thread summary")));
|
||||
};
|
||||
let uri = uri.clone();
|
||||
cx.spawn(async move |cx| {
|
||||
let thread = open_task.await?;
|
||||
let content = thread.read_with(cx, |thread, _cx| {
|
||||
thread.latest_detailed_summary_or_text().to_string()
|
||||
})?;
|
||||
|
||||
anyhow::Ok((crease_id, Mention::Text { uri, content }))
|
||||
cx.spawn(async move |_| {
|
||||
Ok((
|
||||
crease_id,
|
||||
Mention::Text {
|
||||
uri,
|
||||
content: content
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("{e}"))?
|
||||
.to_string(),
|
||||
},
|
||||
))
|
||||
})
|
||||
}
|
||||
MentionUri::TextThread { path, .. } => {
|
||||
let context = text_thread_store.update(cx, |text_thread_store, cx| {
|
||||
text_thread_store.open_local_context(path.as_path().into(), cx)
|
||||
});
|
||||
let Some(content) = self.text_thread_summaries.get(path).cloned() else {
|
||||
return Task::ready(Err(anyhow!("missing text thread summary")));
|
||||
};
|
||||
let uri = uri.clone();
|
||||
cx.spawn(async move |cx| {
|
||||
let context = context.await?;
|
||||
let xml = context.update(cx, |context, cx| context.to_xml(cx))?;
|
||||
anyhow::Ok((crease_id, Mention::Text { uri, content: xml }))
|
||||
cx.spawn(async move |_| {
|
||||
Ok((
|
||||
crease_id,
|
||||
Mention::Text {
|
||||
uri,
|
||||
content: content
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("{e}"))?
|
||||
.to_string(),
|
||||
},
|
||||
))
|
||||
})
|
||||
}
|
||||
MentionUri::Rule { id: prompt_id, .. } => {
|
||||
|
@ -1427,7 +1567,6 @@ mod tests {
|
|||
message_editor.mention_set().contents(
|
||||
project.clone(),
|
||||
thread_store.clone(),
|
||||
text_thread_store.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
|
@ -1495,7 +1634,6 @@ mod tests {
|
|||
message_editor.mention_set().contents(
|
||||
project.clone(),
|
||||
thread_store.clone(),
|
||||
text_thread_store.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
|
@ -1616,13 +1754,9 @@ mod tests {
|
|||
|
||||
let contents = message_editor
|
||||
.update_in(&mut cx, |message_editor, window, cx| {
|
||||
message_editor.mention_set().contents(
|
||||
project.clone(),
|
||||
thread_store,
|
||||
text_thread_store,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
message_editor
|
||||
.mention_set()
|
||||
.contents(project.clone(), thread_store, window, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue