Add back DeletePathTool
to agent2 (#36168)
This was probably removed accidentally as a result of a merge conflict. Release Notes: - N/A
This commit is contained in:
parent
8e4f30abcb
commit
b3d048d6dc
2 changed files with 57 additions and 80 deletions
|
@ -1,8 +1,8 @@
|
|||
use crate::{AgentResponseEvent, Thread, templates::Templates};
|
||||
use crate::{
|
||||
ContextServerRegistry, CopyPathTool, CreateDirectoryTool, DiagnosticsTool, EditFileTool,
|
||||
FetchTool, FindPathTool, GrepTool, ListDirectoryTool, MovePathTool, NowTool, OpenTool,
|
||||
ReadFileTool, TerminalTool, ThinkingTool, ToolCallAuthorization, UserMessageContent,
|
||||
ContextServerRegistry, CopyPathTool, CreateDirectoryTool, DeletePathTool, DiagnosticsTool,
|
||||
EditFileTool, FetchTool, FindPathTool, GrepTool, ListDirectoryTool, MovePathTool, NowTool,
|
||||
OpenTool, ReadFileTool, TerminalTool, ThinkingTool, ToolCallAuthorization, UserMessageContent,
|
||||
WebSearchTool,
|
||||
};
|
||||
use acp_thread::AgentModelSelector;
|
||||
|
@ -583,22 +583,22 @@ impl acp_thread::AgentConnection for NativeAgentConnection {
|
|||
default_model,
|
||||
cx,
|
||||
);
|
||||
thread.add_tool(CreateDirectoryTool::new(project.clone()));
|
||||
thread.add_tool(CopyPathTool::new(project.clone()));
|
||||
thread.add_tool(CreateDirectoryTool::new(project.clone()));
|
||||
thread.add_tool(DeletePathTool::new(project.clone(), action_log.clone()));
|
||||
thread.add_tool(DiagnosticsTool::new(project.clone()));
|
||||
thread.add_tool(MovePathTool::new(project.clone()));
|
||||
thread.add_tool(ListDirectoryTool::new(project.clone()));
|
||||
thread.add_tool(OpenTool::new(project.clone()));
|
||||
thread.add_tool(ThinkingTool);
|
||||
thread.add_tool(FindPathTool::new(project.clone()));
|
||||
thread.add_tool(FetchTool::new(project.read(cx).client().http_client()));
|
||||
thread.add_tool(GrepTool::new(project.clone()));
|
||||
thread.add_tool(ReadFileTool::new(project.clone(), action_log));
|
||||
thread.add_tool(EditFileTool::new(cx.entity()));
|
||||
thread.add_tool(FetchTool::new(project.read(cx).client().http_client()));
|
||||
thread.add_tool(FindPathTool::new(project.clone()));
|
||||
thread.add_tool(GrepTool::new(project.clone()));
|
||||
thread.add_tool(ListDirectoryTool::new(project.clone()));
|
||||
thread.add_tool(MovePathTool::new(project.clone()));
|
||||
thread.add_tool(NowTool);
|
||||
thread.add_tool(OpenTool::new(project.clone()));
|
||||
thread.add_tool(ReadFileTool::new(project.clone(), action_log));
|
||||
thread.add_tool(TerminalTool::new(project.clone(), cx));
|
||||
// TODO: Needs to be conditional based on zed model or not
|
||||
thread.add_tool(WebSearchTool);
|
||||
thread.add_tool(ThinkingTool);
|
||||
thread.add_tool(WebSearchTool); // TODO: Enable this only if it's a zed model.
|
||||
thread
|
||||
});
|
||||
|
||||
|
|
|
@ -411,7 +411,7 @@ pub struct Thread {
|
|||
/// Survives across multiple requests as the model performs tool calls and
|
||||
/// we run tools, report their results.
|
||||
running_turn: Option<Task<()>>,
|
||||
pending_agent_message: Option<AgentMessage>,
|
||||
pending_message: Option<AgentMessage>,
|
||||
tools: BTreeMap<SharedString, Arc<dyn AnyAgentTool>>,
|
||||
context_server_registry: Entity<ContextServerRegistry>,
|
||||
profile_id: AgentProfileId,
|
||||
|
@ -437,7 +437,7 @@ impl Thread {
|
|||
messages: Vec::new(),
|
||||
completion_mode: CompletionMode::Normal,
|
||||
running_turn: None,
|
||||
pending_agent_message: None,
|
||||
pending_message: None,
|
||||
tools: BTreeMap::default(),
|
||||
context_server_registry,
|
||||
profile_id,
|
||||
|
@ -463,7 +463,7 @@ impl Thread {
|
|||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn last_message(&self) -> Option<Message> {
|
||||
if let Some(message) = self.pending_agent_message.clone() {
|
||||
if let Some(message) = self.pending_message.clone() {
|
||||
Some(Message::Agent(message))
|
||||
} else {
|
||||
self.messages.last().cloned()
|
||||
|
@ -485,7 +485,7 @@ impl Thread {
|
|||
pub fn cancel(&mut self) {
|
||||
// TODO: do we need to emit a stop::cancel for ACP?
|
||||
self.running_turn.take();
|
||||
self.flush_pending_agent_message();
|
||||
self.flush_pending_message();
|
||||
}
|
||||
|
||||
pub fn truncate(&mut self, message_id: UserMessageId) -> Result<()> {
|
||||
|
@ -521,74 +521,58 @@ impl Thread {
|
|||
mpsc::unbounded::<Result<AgentResponseEvent, LanguageModelCompletionError>>();
|
||||
let event_stream = AgentResponseEventStream(events_tx);
|
||||
|
||||
let user_message_ix = self.messages.len();
|
||||
self.messages.push(Message::User(UserMessage {
|
||||
id: message_id,
|
||||
id: message_id.clone(),
|
||||
content,
|
||||
}));
|
||||
log::info!("Total messages in thread: {}", self.messages.len());
|
||||
self.running_turn = Some(cx.spawn(async move |thread, cx| {
|
||||
self.running_turn = Some(cx.spawn(async move |this, cx| {
|
||||
log::info!("Starting agent turn execution");
|
||||
let turn_result = async {
|
||||
// Perform one request, then keep looping if the model makes tool calls.
|
||||
let mut completion_intent = CompletionIntent::UserPrompt;
|
||||
'outer: loop {
|
||||
loop {
|
||||
log::debug!(
|
||||
"Building completion request with intent: {:?}",
|
||||
completion_intent
|
||||
);
|
||||
let request = thread.update(cx, |thread, cx| {
|
||||
thread.build_completion_request(completion_intent, cx)
|
||||
let request = this.update(cx, |this, cx| {
|
||||
this.build_completion_request(completion_intent, cx)
|
||||
})?;
|
||||
|
||||
// Stream events, appending to messages and collecting up tool uses.
|
||||
log::info!("Calling model.stream_completion");
|
||||
let mut events = model.stream_completion(request, cx).await?;
|
||||
log::debug!("Stream completion started successfully");
|
||||
|
||||
let mut tool_uses = FuturesUnordered::new();
|
||||
while let Some(event) = events.next().await {
|
||||
match event {
|
||||
Ok(LanguageModelCompletionEvent::Stop(reason)) => {
|
||||
match event? {
|
||||
LanguageModelCompletionEvent::Stop(reason) => {
|
||||
event_stream.send_stop(reason);
|
||||
if reason == StopReason::Refusal {
|
||||
thread.update(cx, |thread, _cx| {
|
||||
thread.pending_agent_message = None;
|
||||
thread.messages.truncate(user_message_ix);
|
||||
})?;
|
||||
break 'outer;
|
||||
this.update(cx, |this, _cx| this.truncate(message_id))??;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Ok(event) => {
|
||||
event => {
|
||||
log::trace!("Received completion event: {:?}", event);
|
||||
thread
|
||||
.update(cx, |thread, cx| {
|
||||
tool_uses.extend(thread.handle_streamed_completion_event(
|
||||
event,
|
||||
&event_stream,
|
||||
cx,
|
||||
));
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!("Error in completion stream: {:?}", error);
|
||||
event_stream.send_error(error);
|
||||
break;
|
||||
this.update(cx, |this, cx| {
|
||||
tool_uses.extend(this.handle_streamed_completion_event(
|
||||
event,
|
||||
&event_stream,
|
||||
cx,
|
||||
));
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no tool uses, the turn is done.
|
||||
if tool_uses.is_empty() {
|
||||
log::info!("No tool uses found, completing turn");
|
||||
break;
|
||||
return Ok(());
|
||||
}
|
||||
log::info!("Found {} tool uses to execute", tool_uses.len());
|
||||
|
||||
// As tool results trickle in, insert them in the last user
|
||||
// message so that they can be sent on the next tick of the
|
||||
// agentic loop.
|
||||
while let Some(tool_result) = tool_uses.next().await {
|
||||
log::info!("Tool finished {:?}", tool_result);
|
||||
|
||||
|
@ -604,29 +588,21 @@ impl Thread {
|
|||
..Default::default()
|
||||
},
|
||||
);
|
||||
thread
|
||||
.update(cx, |thread, _cx| {
|
||||
thread
|
||||
.pending_agent_message()
|
||||
.tool_results
|
||||
.insert(tool_result.tool_use_id.clone(), tool_result);
|
||||
})
|
||||
.ok();
|
||||
this.update(cx, |this, _cx| {
|
||||
this.pending_message()
|
||||
.tool_results
|
||||
.insert(tool_result.tool_use_id.clone(), tool_result);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
thread.update(cx, |thread, _cx| thread.flush_pending_agent_message())?;
|
||||
|
||||
this.update(cx, |this, _| this.flush_pending_message())?;
|
||||
completion_intent = CompletionIntent::ToolResults;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
.await;
|
||||
|
||||
thread
|
||||
.update(cx, |thread, _cx| thread.flush_pending_agent_message())
|
||||
.ok();
|
||||
|
||||
this.update(cx, |this, _| this.flush_pending_message()).ok();
|
||||
if let Err(error) = turn_result {
|
||||
log::error!("Turn execution failed: {:?}", error);
|
||||
event_stream.send_error(error);
|
||||
|
@ -668,7 +644,8 @@ impl Thread {
|
|||
|
||||
match event {
|
||||
StartMessage { .. } => {
|
||||
self.messages.push(Message::Agent(AgentMessage::default()));
|
||||
self.flush_pending_message();
|
||||
self.pending_message = Some(AgentMessage::default());
|
||||
}
|
||||
Text(new_text) => self.handle_text_event(new_text, event_stream, cx),
|
||||
Thinking { text, signature } => {
|
||||
|
@ -706,7 +683,7 @@ impl Thread {
|
|||
) {
|
||||
events_stream.send_text(&new_text);
|
||||
|
||||
let last_message = self.pending_agent_message();
|
||||
let last_message = self.pending_message();
|
||||
if let Some(AgentMessageContent::Text(text)) = last_message.content.last_mut() {
|
||||
text.push_str(&new_text);
|
||||
} else {
|
||||
|
@ -727,7 +704,7 @@ impl Thread {
|
|||
) {
|
||||
event_stream.send_thinking(&new_text);
|
||||
|
||||
let last_message = self.pending_agent_message();
|
||||
let last_message = self.pending_message();
|
||||
if let Some(AgentMessageContent::Thinking { text, signature }) =
|
||||
last_message.content.last_mut()
|
||||
{
|
||||
|
@ -744,7 +721,7 @@ impl Thread {
|
|||
}
|
||||
|
||||
fn handle_redacted_thinking_event(&mut self, data: String, cx: &mut Context<Self>) {
|
||||
let last_message = self.pending_agent_message();
|
||||
let last_message = self.pending_message();
|
||||
last_message
|
||||
.content
|
||||
.push(AgentMessageContent::RedactedThinking(data));
|
||||
|
@ -768,7 +745,7 @@ impl Thread {
|
|||
}
|
||||
|
||||
// Ensure the last message ends in the current tool use
|
||||
let last_message = self.pending_agent_message();
|
||||
let last_message = self.pending_message();
|
||||
let push_new_tool_use = last_message.content.last_mut().map_or(true, |content| {
|
||||
if let AgentMessageContent::ToolUse(last_tool_use) = content {
|
||||
if last_tool_use.id == tool_use.id {
|
||||
|
@ -871,12 +848,12 @@ impl Thread {
|
|||
}
|
||||
}
|
||||
|
||||
fn pending_agent_message(&mut self) -> &mut AgentMessage {
|
||||
self.pending_agent_message.get_or_insert_default()
|
||||
fn pending_message(&mut self) -> &mut AgentMessage {
|
||||
self.pending_message.get_or_insert_default()
|
||||
}
|
||||
|
||||
fn flush_pending_agent_message(&mut self) {
|
||||
let Some(mut message) = self.pending_agent_message.take() else {
|
||||
fn flush_pending_message(&mut self) {
|
||||
let Some(mut message) = self.pending_message.take() else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -997,7 +974,7 @@ impl Thread {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(message) = self.pending_agent_message.as_ref() {
|
||||
if let Some(message) = self.pending_message.as_ref() {
|
||||
messages.extend(message.to_request());
|
||||
}
|
||||
|
||||
|
@ -1013,7 +990,7 @@ impl Thread {
|
|||
markdown.push_str(&message.to_markdown());
|
||||
}
|
||||
|
||||
if let Some(message) = self.pending_agent_message.as_ref() {
|
||||
if let Some(message) = self.pending_message.as_ref() {
|
||||
markdown.push('\n');
|
||||
markdown.push_str(&message.to_markdown());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue