Push request and insert further

Ben Brandt created

Change summary

crates/acp_thread/src/acp_thread.rs | 173 +++++++++---------------------
1 file changed, 51 insertions(+), 122 deletions(-)

Detailed changes

crates/acp_thread/src/acp_thread.rs 🔗

@@ -180,6 +180,31 @@ pub struct ToolCall {
 }
 
 impl ToolCall {
+    fn from_acp(
+        tool_call: acp::ToolCall,
+        status: ToolCallStatus,
+        language_registry: Arc<LanguageRegistry>,
+        cx: &mut App,
+    ) -> Self {
+        Self {
+            id: tool_call.id,
+            label: cx.new(|cx| {
+                Markdown::new(
+                    tool_call.label.into(),
+                    Some(language_registry.clone()),
+                    None,
+                    cx,
+                )
+            }),
+            kind: tool_call.kind,
+            // todo! Do we assume there is either a coalesced content OR diff?
+            content: ToolCallContent::from_acp_contents(tool_call.content, language_registry, cx)
+                .into_iter()
+                .next(),
+            locations: tool_call.locations,
+            status,
+        }
+    }
     fn to_markdown(&self, cx: &App) -> String {
         let mut markdown = format!(
             "**Tool Call: {}**\nStatus: {}\n\n",
@@ -780,98 +805,46 @@ impl AcpThread {
         cx: &mut Context<Self>,
     ) -> Result<()> {
         let language_registry = self.project.read(cx).languages().clone();
-
-        let new_tool_call = ToolCall {
-            id: tool_call.id,
-            label: cx.new(|cx| {
-                Markdown::new(
-                    tool_call.label.into(),
-                    Some(language_registry.clone()),
-                    None,
-                    cx,
-                )
-            }),
-            kind: tool_call.kind,
-            // todo! Do we assume there is either a coalesced content OR diff?
-            content: ToolCallContent::from_acp_contents(tool_call.content, language_registry, cx)
-                .into_iter()
-                .next(),
-            locations: tool_call.locations,
-            status: ToolCallStatus::Allowed {
-                status: tool_call.status,
-            },
+        let status = ToolCallStatus::Allowed {
+            status: tool_call.status,
         };
+        let call = ToolCall::from_acp(tool_call, status, language_registry, cx);
 
-        if let Some((ix, current_call)) = self.tool_call_mut(tool_call.id) {
-            match &mut current_call.status {
-                ToolCallStatus::Allowed { status } => {
-                    *status = tool_call.status;
-                }
+        let location = call.locations.last().cloned();
+
+        if let Some((ix, current_call)) = self.tool_call_mut(&call.id) {
+            match &current_call.status {
                 ToolCallStatus::WaitingForConfirmation { .. } => {
                     anyhow::bail!("Tool call hasn't been authorized yet")
                 }
                 ToolCallStatus::Rejected => {
                     anyhow::bail!("Tool call was rejected and therefore can't be updated")
                 }
-                ToolCallStatus::Canceled => {
-                    current_call.status = ToolCallStatus::Allowed { status: new_status };
-                }
+                ToolCallStatus::Allowed { .. } | ToolCallStatus::Canceled => {}
             }
 
-            *current_call = new_tool_call;
-
-            let location = current_call.locations.last().cloned();
-            if let Some(location) = location {
-                self.set_project_location(location, cx)
-            }
+            *current_call = call;
 
             cx.emit(AcpThreadEvent::EntryUpdated(ix));
         } else {
-            let language_registry = self.project.read(cx).languages().clone();
-            let call = ToolCall {
-                id: tool_call.id,
-                label: cx.new(|cx| {
-                    Markdown::new(
-                        tool_call.label.into(),
-                        Some(language_registry.clone()),
-                        None,
-                        cx,
-                    )
-                }),
-                kind: tool_call.kind,
-                // todo! Do we assume there is either a coalesced content OR diff?
-                content: ToolCallContent::from_acp_contents(
-                    tool_call.content,
-                    language_registry,
-                    cx,
-                )
-                .into_iter()
-                .next(),
-                locations: tool_call.locations,
-                status: ToolCallStatus::Allowed {
-                    status: tool_call.status,
-                },
-            };
-
-            let location = call.locations.last().cloned();
-            if let Some(location) = location {
-                self.set_project_location(location, cx)
-            }
-
             self.push_entry(AgentThreadEntry::ToolCall(call), cx);
         }
 
+        if let Some(location) = location {
+            self.set_project_location(location, cx)
+        }
+
         Ok(())
     }
 
-    fn tool_call_mut(&mut self, id: acp::ToolCallId) -> Option<(usize, &mut ToolCall)> {
+    fn tool_call_mut(&mut self, id: &acp::ToolCallId) -> Option<(usize, &mut ToolCall)> {
         self.entries
             .iter_mut()
             .enumerate()
             .rev()
             .find_map(|(index, tool_call)| {
                 if let AgentThreadEntry::ToolCall(tool_call) = tool_call
-                    && tool_call.id == id
+                    && &tool_call.id == id
                 {
                     Some((index, tool_call))
                 } else {
@@ -885,7 +858,7 @@ impl AcpThread {
         tool_call: acp::ToolCall,
         possible_grants: Vec<acp::Grant>,
         cx: &mut Context<Self>,
-    ) -> ToolCallRequest {
+    ) -> oneshot::Receiver<acp::GrantId> {
         let (tx, rx) = oneshot::channel();
 
         let status = ToolCallStatus::WaitingForConfirmation {
@@ -893,61 +866,18 @@ impl AcpThread {
             respond_tx: tx,
         };
 
-        let id = self.insert_tool_call(tool_call, status, cx);
-        ToolCallRequest { id, outcome: rx }
-    }
-
-    pub fn request_tool_call_confirmation(
-        &mut self,
-        tool_call_id: ToolCallId,
-        confirmation: acp_old::ToolCallConfirmation,
-        cx: &mut Context<Self>,
-    ) -> Result<ToolCallRequest> {
-        let project = self.project.read(cx).languages().clone();
-        let Some((idx, call)) = self.tool_call_mut(tool_call_id) else {
-            anyhow::bail!("Tool call not found");
-        };
-
-        let (tx, rx) = oneshot::channel();
-
-        call.status = ToolCallStatus::WaitingForConfirmation {
-            confirmation: ToolCallConfirmation::from_acp(confirmation, project, cx),
-            respond_tx: tx,
-        };
-
-        cx.emit(AcpThreadEvent::EntryUpdated(idx));
-
-        Ok(ToolCallRequest {
-            id: tool_call_id,
-            outcome: rx,
-        })
+        self.insert_tool_call(tool_call, status, cx);
+        rx
     }
 
     fn insert_tool_call(
         &mut self,
-        tool_call: acp_old::PushToolCallParams,
+        tool_call: acp::ToolCall,
         status: ToolCallStatus,
         cx: &mut Context<Self>,
-    ) -> acp_old::ToolCallId {
+    ) {
         let language_registry = self.project.read(cx).languages().clone();
-        let id = acp_old::ToolCallId(self.entries.len() as u64);
-        let call = ToolCall {
-            id,
-            label: cx.new(|cx| {
-                Markdown::new(
-                    tool_call.label.into(),
-                    Some(language_registry.clone()),
-                    None,
-                    cx,
-                )
-            }),
-            icon: acp_icon_to_ui_icon(tool_call.icon),
-            content: tool_call
-                .content
-                .map(|content| ToolCallContent::from_acp(content, language_registry, cx)),
-            locations: tool_call.locations,
-            status,
-        };
+        let call = ToolCall::from_acp(tool_call, status, language_registry, cx);
 
         let location = call.locations.last().cloned();
         if let Some(location) = location {
@@ -955,8 +885,6 @@ impl AcpThread {
         }
 
         self.push_entry(AgentThreadEntry::ToolCall(call), cx);
-
-        id
     }
 
     pub fn authorize_tool_call(
@@ -965,7 +893,7 @@ impl AcpThread {
         grant: acp::Grant,
         cx: &mut Context<Self>,
     ) {
-        let Some((ix, call)) = self.tool_call_mut(id) else {
+        let Some((ix, call)) = self.tool_call_mut(&id) else {
             return;
         };
 
@@ -1135,7 +1063,7 @@ impl AcpThread {
                                 call.status,
                                 ToolCallStatus::WaitingForConfirmation { .. }
                                     | ToolCallStatus::Allowed {
-                                        status: acp_old::ToolCallStatus::Running
+                                        status: acp::ToolCallStatus::InProgress
                                     }
                             );
 
@@ -1147,6 +1075,7 @@ impl AcpThread {
                                     respond_tx, ..
                                 } = curr_status
                                 {
+                                    // todo! do we need a way to cancel rather than reject?
                                     respond_tx
                                         .send(acp_old::ToolCallConfirmationOutcome::Cancel)
                                         .ok();
@@ -1698,7 +1627,7 @@ mod tests {
                 thread.entries[1],
                 AgentThreadEntry::ToolCall(ToolCall {
                     status: ToolCallStatus::Allowed {
-                        status: acp_old::ToolCallStatus::Running,
+                        status: acp::ToolCallStatus::InProgress,
                         ..
                     },
                     ..
@@ -1742,7 +1671,7 @@ mod tests {
                 thread.entries[1],
                 AgentThreadEntry::ToolCall(ToolCall {
                     status: ToolCallStatus::Allowed {
-                        status: acp_old::ToolCallStatus::Finished,
+                        status: acp::ToolCallStatus::Completed,
                         ..
                     },
                     ..