Support @-mentions in inline assists and when editing old agent panel messages (#29734)
Closes #ISSUE Co-authored-by: Bennet <bennet@zed.dev> Release Notes: - Added support for context `@mentions` in the inline prompt editor and when editing past messages in the agent panel. --------- Co-authored-by: Bennet Bo Fenner <bennet@zed.dev> Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
This commit is contained in:
parent
c918f6cde1
commit
9547d42b15
18 changed files with 499 additions and 156 deletions
|
@ -9,6 +9,7 @@ use assistant_settings::AssistantSettings;
|
|||
use assistant_tool::{ActionLog, AnyToolCard, Tool, ToolWorkingSet};
|
||||
use chrono::{DateTime, Utc};
|
||||
use collections::HashMap;
|
||||
use editor::display_map::CreaseMetadata;
|
||||
use feature_flags::{self, FeatureFlagAppExt};
|
||||
use futures::future::Shared;
|
||||
use futures::{FutureExt, StreamExt as _};
|
||||
|
@ -39,10 +40,10 @@ use uuid::Uuid;
|
|||
use zed_llm_client::CompletionMode;
|
||||
|
||||
use crate::ThreadStore;
|
||||
use crate::context::{AgentContext, ContextLoadResult, LoadedContext};
|
||||
use crate::context::{AgentContext, AgentContextHandle, ContextLoadResult, LoadedContext};
|
||||
use crate::thread_store::{
|
||||
SerializedLanguageModel, SerializedMessage, SerializedMessageSegment, SerializedThread,
|
||||
SerializedToolResult, SerializedToolUse, SharedProjectContext,
|
||||
SerializedCrease, SerializedLanguageModel, SerializedMessage, SerializedMessageSegment,
|
||||
SerializedThread, SerializedToolResult, SerializedToolUse, SharedProjectContext,
|
||||
};
|
||||
use crate::tool_use::{PendingToolUse, ToolUse, ToolUseMetadata, ToolUseState};
|
||||
|
||||
|
@ -96,6 +97,15 @@ impl MessageId {
|
|||
}
|
||||
}
|
||||
|
||||
/// Stored information that can be used to resurrect a context crease when creating an editor for a past message.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MessageCrease {
|
||||
pub range: Range<usize>,
|
||||
pub metadata: CreaseMetadata,
|
||||
/// None for a deserialized message, Some otherwise.
|
||||
pub context: Option<AgentContextHandle>,
|
||||
}
|
||||
|
||||
/// A message in a [`Thread`].
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Message {
|
||||
|
@ -103,6 +113,7 @@ pub struct Message {
|
|||
pub role: Role,
|
||||
pub segments: Vec<MessageSegment>,
|
||||
pub loaded_context: LoadedContext,
|
||||
pub creases: Vec<MessageCrease>,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
|
@ -473,6 +484,18 @@ impl Thread {
|
|||
text: message.context,
|
||||
images: Vec::new(),
|
||||
},
|
||||
creases: message
|
||||
.creases
|
||||
.into_iter()
|
||||
.map(|crease| MessageCrease {
|
||||
range: crease.start..crease.end,
|
||||
metadata: CreaseMetadata {
|
||||
icon_path: crease.icon_path,
|
||||
label: crease.label,
|
||||
},
|
||||
context: None,
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
.collect(),
|
||||
next_message_id,
|
||||
|
@ -826,6 +849,7 @@ impl Thread {
|
|||
text: impl Into<String>,
|
||||
loaded_context: ContextLoadResult,
|
||||
git_checkpoint: Option<GitStoreCheckpoint>,
|
||||
creases: Vec<MessageCrease>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> MessageId {
|
||||
if !loaded_context.referenced_buffers.is_empty() {
|
||||
|
@ -840,6 +864,7 @@ impl Thread {
|
|||
Role::User,
|
||||
vec![MessageSegment::Text(text.into())],
|
||||
loaded_context.loaded_context,
|
||||
creases,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
@ -860,7 +885,13 @@ impl Thread {
|
|||
segments: Vec<MessageSegment>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> MessageId {
|
||||
self.insert_message(Role::Assistant, segments, LoadedContext::default(), cx)
|
||||
self.insert_message(
|
||||
Role::Assistant,
|
||||
segments,
|
||||
LoadedContext::default(),
|
||||
Vec::new(),
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn insert_message(
|
||||
|
@ -868,6 +899,7 @@ impl Thread {
|
|||
role: Role,
|
||||
segments: Vec<MessageSegment>,
|
||||
loaded_context: LoadedContext,
|
||||
creases: Vec<MessageCrease>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> MessageId {
|
||||
let id = self.next_message_id.post_inc();
|
||||
|
@ -876,6 +908,7 @@ impl Thread {
|
|||
role,
|
||||
segments,
|
||||
loaded_context,
|
||||
creases,
|
||||
});
|
||||
self.touch_updated_at();
|
||||
cx.emit(ThreadEvent::MessageAdded(id));
|
||||
|
@ -995,6 +1028,16 @@ impl Thread {
|
|||
})
|
||||
.collect(),
|
||||
context: message.loaded_context.text.clone(),
|
||||
creases: message
|
||||
.creases
|
||||
.iter()
|
||||
.map(|crease| SerializedCrease {
|
||||
start: crease.range.start,
|
||||
end: crease.range.end,
|
||||
icon_path: crease.metadata.icon_path.clone(),
|
||||
label: crease.metadata.label.clone(),
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
.collect(),
|
||||
initial_project_snapshot,
|
||||
|
@ -2502,7 +2545,13 @@ mod tests {
|
|||
|
||||
// Insert user message with context
|
||||
let message_id = thread.update(cx, |thread, cx| {
|
||||
thread.insert_user_message("Please explain this code", loaded_context, None, cx)
|
||||
thread.insert_user_message(
|
||||
"Please explain this code",
|
||||
loaded_context,
|
||||
None,
|
||||
Vec::new(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
// Check content and context in message object
|
||||
|
@ -2578,7 +2627,7 @@ fn main() {{
|
|||
.update(|cx| load_context(new_contexts, &project, &None, cx))
|
||||
.await;
|
||||
let message1_id = thread.update(cx, |thread, cx| {
|
||||
thread.insert_user_message("Message 1", loaded_context, None, cx)
|
||||
thread.insert_user_message("Message 1", loaded_context, None, Vec::new(), cx)
|
||||
});
|
||||
|
||||
// Second message with contexts 1 and 2 (context 1 should be skipped as it's already included)
|
||||
|
@ -2593,7 +2642,7 @@ fn main() {{
|
|||
.update(|cx| load_context(new_contexts, &project, &None, cx))
|
||||
.await;
|
||||
let message2_id = thread.update(cx, |thread, cx| {
|
||||
thread.insert_user_message("Message 2", loaded_context, None, cx)
|
||||
thread.insert_user_message("Message 2", loaded_context, None, Vec::new(), cx)
|
||||
});
|
||||
|
||||
// Third message with all three contexts (contexts 1 and 2 should be skipped)
|
||||
|
@ -2609,7 +2658,7 @@ fn main() {{
|
|||
.update(|cx| load_context(new_contexts, &project, &None, cx))
|
||||
.await;
|
||||
let message3_id = thread.update(cx, |thread, cx| {
|
||||
thread.insert_user_message("Message 3", loaded_context, None, cx)
|
||||
thread.insert_user_message("Message 3", loaded_context, None, Vec::new(), cx)
|
||||
});
|
||||
|
||||
// Check what contexts are included in each message
|
||||
|
@ -2723,6 +2772,7 @@ fn main() {{
|
|||
"What is the best way to learn Rust?",
|
||||
ContextLoadResult::default(),
|
||||
None,
|
||||
Vec::new(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
@ -2756,6 +2806,7 @@ fn main() {{
|
|||
"Are there any good books?",
|
||||
ContextLoadResult::default(),
|
||||
None,
|
||||
Vec::new(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
@ -2805,7 +2856,7 @@ fn main() {{
|
|||
|
||||
// Insert user message with the buffer as context
|
||||
thread.update(cx, |thread, cx| {
|
||||
thread.insert_user_message("Explain this code", loaded_context, None, cx)
|
||||
thread.insert_user_message("Explain this code", loaded_context, None, Vec::new(), cx)
|
||||
});
|
||||
|
||||
// Create a request and check that it doesn't have a stale buffer warning yet
|
||||
|
@ -2839,6 +2890,7 @@ fn main() {{
|
|||
"What does the code do now?",
|
||||
ContextLoadResult::default(),
|
||||
None,
|
||||
Vec::new(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue