acp: Reliably suppress gemini abort error (#36640)

Agus Zubiaga created

https://github.com/zed-industries/zed/pull/36633 relied on the prompt
request responding before cancel, but that's not guaranteed


Release Notes:

- N/A

Change summary

crates/agent_servers/src/acp/v1.rs | 33 ++++++++++++++-----------------
1 file changed, 15 insertions(+), 18 deletions(-)

Detailed changes

crates/agent_servers/src/acp/v1.rs 🔗

@@ -28,7 +28,7 @@ pub struct AcpConnection {
 
 pub struct AcpSession {
     thread: WeakEntity<AcpThread>,
-    pending_cancel: bool,
+    suppress_abort_err: bool,
 }
 
 const MINIMUM_SUPPORTED_VERSION: acp::ProtocolVersion = acp::V1;
@@ -173,7 +173,7 @@ impl AgentConnection for AcpConnection {
 
             let session = AcpSession {
                 thread: thread.downgrade(),
-                pending_cancel: false,
+                suppress_abort_err: false,
             };
             sessions.borrow_mut().insert(session_id, session);
 
@@ -208,7 +208,16 @@ impl AgentConnection for AcpConnection {
         let sessions = self.sessions.clone();
         let session_id = params.session_id.clone();
         cx.foreground_executor().spawn(async move {
-            match conn.prompt(params).await {
+            let result = conn.prompt(params).await;
+
+            let mut suppress_abort_err = false;
+
+            if let Some(session) = sessions.borrow_mut().get_mut(&session_id) {
+                suppress_abort_err = session.suppress_abort_err;
+                session.suppress_abort_err = false;
+            }
+
+            match result {
                 Ok(response) => Ok(response),
                 Err(err) => {
                     if err.code != ErrorCode::INTERNAL_ERROR.code {
@@ -230,11 +239,7 @@ impl AgentConnection for AcpConnection {
 
                     match serde_json::from_value(data.clone()) {
                         Ok(ErrorDetails { details }) => {
-                            if sessions
-                                .borrow()
-                                .get(&session_id)
-                                .is_some_and(|session| session.pending_cancel)
-                                && details.contains("This operation was aborted")
+                            if suppress_abort_err && details.contains("This operation was aborted")
                             {
                                 Ok(acp::PromptResponse {
                                     stop_reason: acp::StopReason::Canceled,
@@ -256,22 +261,14 @@ impl AgentConnection for AcpConnection {
 
     fn cancel(&self, session_id: &acp::SessionId, cx: &mut App) {
         if let Some(session) = self.sessions.borrow_mut().get_mut(session_id) {
-            session.pending_cancel = true;
+            session.suppress_abort_err = true;
         }
         let conn = self.connection.clone();
         let params = acp::CancelNotification {
             session_id: session_id.clone(),
         };
-        let sessions = self.sessions.clone();
-        let session_id = session_id.clone();
         cx.foreground_executor()
-            .spawn(async move {
-                let resp = conn.cancel(params).await;
-                if let Some(session) = sessions.borrow_mut().get_mut(&session_id) {
-                    session.pending_cancel = false;
-                }
-                resp
-            })
+            .spawn(async move { conn.cancel(params).await })
             .detach();
     }