acp: Eagerly load all kinds of mentions (#36741)
This PR makes it so that all kinds of @-mentions start loading their context as soon as they are confirmed. Previously, we were waiting to load the context for file, symbol, selection, and rule mentions until the user's message was sent. By kicking off loading immediately for these kinds of context, we can support adding selections from unsaved buffers, and we make the semantics of @-mentions more consistent. Loading all kinds of context eagerly also makes it possible to simplify the structure of the MentionSet and the code around it. Now MentionSet is just a single hash map, all the management of creases happens in a uniform way in `MessageEditor::confirm_completion`, and the helper methods for loading different kinds of context are much more focused and orthogonal. Release Notes: - N/A --------- Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
parent
5da31fdb72
commit
ea42013746
7 changed files with 699 additions and 837 deletions
|
@ -266,8 +266,19 @@ impl ThreadsDatabase {
|
|||
}
|
||||
|
||||
pub fn new(executor: BackgroundExecutor) -> Result<Self> {
|
||||
let connection = if *ZED_STATELESS || cfg!(any(feature = "test-support", test)) {
|
||||
let connection = if *ZED_STATELESS {
|
||||
Connection::open_memory(Some("THREAD_FALLBACK_DB"))
|
||||
} else if cfg!(any(feature = "test-support", test)) {
|
||||
// rust stores the name of the test on the current thread.
|
||||
// We use this to automatically create a database that will
|
||||
// be shared within the test (for the test_retrieve_old_thread)
|
||||
// but not with concurrent tests.
|
||||
let thread = std::thread::current();
|
||||
let test_name = thread.name();
|
||||
Connection::open_memory(Some(&format!(
|
||||
"THREAD_FALLBACK_{}",
|
||||
test_name.unwrap_or_default()
|
||||
)))
|
||||
} else {
|
||||
let threads_dir = paths::data_dir().join("threads");
|
||||
std::fs::create_dir_all(&threads_dir)?;
|
||||
|
|
|
@ -45,14 +45,15 @@ use schemars::{JsonSchema, Schema};
|
|||
use serde::{Deserialize, Serialize};
|
||||
use settings::{Settings, update_settings_file};
|
||||
use smol::stream::StreamExt;
|
||||
use std::fmt::Write;
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
ops::RangeInclusive,
|
||||
path::Path,
|
||||
sync::Arc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use std::{fmt::Write, ops::Range};
|
||||
use util::{ResultExt, markdown::MarkdownCodeBlock};
|
||||
use util::{ResultExt, debug_panic, markdown::MarkdownCodeBlock};
|
||||
use uuid::Uuid;
|
||||
|
||||
const TOOL_CANCELED_MESSAGE: &str = "Tool canceled by user";
|
||||
|
@ -187,6 +188,7 @@ impl UserMessage {
|
|||
const OPEN_FILES_TAG: &str = "<files>";
|
||||
const OPEN_DIRECTORIES_TAG: &str = "<directories>";
|
||||
const OPEN_SYMBOLS_TAG: &str = "<symbols>";
|
||||
const OPEN_SELECTIONS_TAG: &str = "<selections>";
|
||||
const OPEN_THREADS_TAG: &str = "<threads>";
|
||||
const OPEN_FETCH_TAG: &str = "<fetched_urls>";
|
||||
const OPEN_RULES_TAG: &str =
|
||||
|
@ -195,6 +197,7 @@ impl UserMessage {
|
|||
let mut file_context = OPEN_FILES_TAG.to_string();
|
||||
let mut directory_context = OPEN_DIRECTORIES_TAG.to_string();
|
||||
let mut symbol_context = OPEN_SYMBOLS_TAG.to_string();
|
||||
let mut selection_context = OPEN_SELECTIONS_TAG.to_string();
|
||||
let mut thread_context = OPEN_THREADS_TAG.to_string();
|
||||
let mut fetch_context = OPEN_FETCH_TAG.to_string();
|
||||
let mut rules_context = OPEN_RULES_TAG.to_string();
|
||||
|
@ -211,7 +214,7 @@ impl UserMessage {
|
|||
match uri {
|
||||
MentionUri::File { abs_path } => {
|
||||
write!(
|
||||
&mut symbol_context,
|
||||
&mut file_context,
|
||||
"\n{}",
|
||||
MarkdownCodeBlock {
|
||||
tag: &codeblock_tag(abs_path, None),
|
||||
|
@ -220,17 +223,19 @@ impl UserMessage {
|
|||
)
|
||||
.ok();
|
||||
}
|
||||
MentionUri::PastedImage => {
|
||||
debug_panic!("pasted image URI should not be used in mention content")
|
||||
}
|
||||
MentionUri::Directory { .. } => {
|
||||
write!(&mut directory_context, "\n{}\n", content).ok();
|
||||
}
|
||||
MentionUri::Symbol {
|
||||
path, line_range, ..
|
||||
}
|
||||
| MentionUri::Selection {
|
||||
path, line_range, ..
|
||||
abs_path: path,
|
||||
line_range,
|
||||
..
|
||||
} => {
|
||||
write!(
|
||||
&mut rules_context,
|
||||
&mut symbol_context,
|
||||
"\n{}",
|
||||
MarkdownCodeBlock {
|
||||
tag: &codeblock_tag(path, Some(line_range)),
|
||||
|
@ -239,6 +244,24 @@ impl UserMessage {
|
|||
)
|
||||
.ok();
|
||||
}
|
||||
MentionUri::Selection {
|
||||
abs_path: path,
|
||||
line_range,
|
||||
..
|
||||
} => {
|
||||
write!(
|
||||
&mut selection_context,
|
||||
"\n{}",
|
||||
MarkdownCodeBlock {
|
||||
tag: &codeblock_tag(
|
||||
path.as_deref().unwrap_or("Untitled".as_ref()),
|
||||
Some(line_range)
|
||||
),
|
||||
text: content
|
||||
}
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
MentionUri::Thread { .. } => {
|
||||
write!(&mut thread_context, "\n{}\n", content).ok();
|
||||
}
|
||||
|
@ -291,6 +314,13 @@ impl UserMessage {
|
|||
.push(language_model::MessageContent::Text(symbol_context));
|
||||
}
|
||||
|
||||
if selection_context.len() > OPEN_SELECTIONS_TAG.len() {
|
||||
selection_context.push_str("</selections>\n");
|
||||
message
|
||||
.content
|
||||
.push(language_model::MessageContent::Text(selection_context));
|
||||
}
|
||||
|
||||
if thread_context.len() > OPEN_THREADS_TAG.len() {
|
||||
thread_context.push_str("</threads>\n");
|
||||
message
|
||||
|
@ -326,7 +356,7 @@ impl UserMessage {
|
|||
}
|
||||
}
|
||||
|
||||
fn codeblock_tag(full_path: &Path, line_range: Option<&Range<u32>>) -> String {
|
||||
fn codeblock_tag(full_path: &Path, line_range: Option<&RangeInclusive<u32>>) -> String {
|
||||
let mut result = String::new();
|
||||
|
||||
if let Some(extension) = full_path.extension().and_then(|ext| ext.to_str()) {
|
||||
|
@ -336,10 +366,10 @@ fn codeblock_tag(full_path: &Path, line_range: Option<&Range<u32>>) -> String {
|
|||
let _ = write!(result, "{}", full_path.display());
|
||||
|
||||
if let Some(range) = line_range {
|
||||
if range.start == range.end {
|
||||
let _ = write!(result, ":{}", range.start + 1);
|
||||
if range.start() == range.end() {
|
||||
let _ = write!(result, ":{}", range.start() + 1);
|
||||
} else {
|
||||
let _ = write!(result, ":{}-{}", range.start + 1, range.end + 1);
|
||||
let _ = write!(result, ":{}-{}", range.start() + 1, range.end() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue