@@ -328,7 +328,7 @@ impl ToolCall {
location: acp::ToolCallLocation,
project: WeakEntity<Project>,
cx: &mut AsyncApp,
- ) -> Option<AgentLocation> {
+ ) -> Option<ResolvedLocation> {
let buffer = project
.update(cx, |project, cx| {
project
@@ -350,17 +350,14 @@ impl ToolCall {
})
.ok()?;
- Some(AgentLocation {
- buffer: buffer.downgrade(),
- position,
- })
+ Some(ResolvedLocation { buffer, position })
}
fn resolve_locations(
&self,
project: Entity<Project>,
cx: &mut App,
- ) -> Task<Vec<Option<AgentLocation>>> {
+ ) -> Task<Vec<Option<ResolvedLocation>>> {
let locations = self.locations.clone();
project.update(cx, |_, cx| {
cx.spawn(async move |project, cx| {
@@ -374,6 +371,23 @@ impl ToolCall {
}
}
+// Separate so we can hold a strong reference to the buffer
+// for saving on the thread
+#[derive(Clone, Debug, PartialEq, Eq)]
+struct ResolvedLocation {
+ buffer: Entity<Buffer>,
+ position: Anchor,
+}
+
+impl From<&ResolvedLocation> for AgentLocation {
+ fn from(value: &ResolvedLocation) -> Self {
+ Self {
+ buffer: value.buffer.downgrade(),
+ position: value.position,
+ }
+ }
+}
+
#[derive(Debug)]
pub enum ToolCallStatus {
/// The tool call hasn't started running yet, but we start showing it to
@@ -1393,35 +1407,43 @@ impl AcpThread {
let task = tool_call.resolve_locations(project, cx);
cx.spawn(async move |this, cx| {
let resolved_locations = task.await;
+
this.update(cx, |this, cx| {
let project = this.project.clone();
+
+ for location in resolved_locations.iter().flatten() {
+ this.shared_buffers
+ .insert(location.buffer.clone(), location.buffer.read(cx).snapshot());
+ }
let Some((ix, tool_call)) = this.tool_call_mut(&id) else {
return;
};
+
if let Some(Some(location)) = resolved_locations.last() {
project.update(cx, |project, cx| {
- if let Some(agent_location) = project.agent_location() {
- let should_ignore = agent_location.buffer == location.buffer
- && location
- .buffer
- .update(cx, |buffer, _| {
- let snapshot = buffer.snapshot();
- let old_position =
- agent_location.position.to_point(&snapshot);
- let new_position = location.position.to_point(&snapshot);
- // ignore this so that when we get updates from the edit tool
- // the position doesn't reset to the startof line
- old_position.row == new_position.row
- && old_position.column > new_position.column
- })
- .ok()
- .unwrap_or_default();
- if !should_ignore {
- project.set_agent_location(Some(location.clone()), cx);
- }
+ let should_ignore = if let Some(agent_location) = project.agent_location() {
+ let snapshot = location.buffer.read(cx).snapshot();
+ let old_position = agent_location.position.to_point(&snapshot);
+ let new_position = location.position.to_point(&snapshot);
+ agent_location.buffer == location.buffer
+ // ignore this so that when we get updates from the edit tool
+ // the position doesn't reset to the startof line
+ && (old_position.row == new_position.row
+ && old_position.column > new_position.column)
+ } else {
+ false
+ };
+ if !should_ignore {
+ project.set_agent_location(Some(location.into()), cx);
}
});
}
+
+ let resolved_locations = resolved_locations
+ .iter()
+ .map(|l| l.as_ref().map(|l| AgentLocation::from(l)))
+ .collect::<Vec<_>>();
+
if tool_call.resolved_locations != resolved_locations {
tool_call.resolved_locations = resolved_locations;
cx.emit(AcpThreadEvent::EntryUpdated(ix));