@@ -171,9 +171,9 @@ dependencies = [
[[package]]
name = "agent-client-protocol"
-version = "0.0.28"
+version = "0.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c887e795097665ab95119580534e7cc1335b59e1a7fec296943e534b970f4ed"
+checksum = "89a2cd7e0bd2bb7ed27687cfcf6561b91542c1ce23e52fd54ee59b7568c9bd84"
dependencies = [
"anyhow",
"futures 0.3.31",
@@ -423,7 +423,7 @@ zlog_settings = { path = "crates/zlog_settings" }
#
agentic-coding-protocol = "0.0.10"
-agent-client-protocol = "0.0.28"
+agent-client-protocol = "0.0.29"
aho-corasick = "1.1"
alacritty_terminal = { git = "https://github.com/zed-industries/alacritty.git", branch = "add-hush-login-flag" }
any_vec = "0.14"
@@ -1,11 +1,12 @@
use action_log::ActionLog;
-use agent_client_protocol::{self as acp, Agent as _};
+use agent_client_protocol::{self as acp, Agent as _, ErrorCode};
use anyhow::anyhow;
use collections::HashMap;
use futures::AsyncBufReadExt as _;
use futures::channel::oneshot;
use futures::io::BufReader;
use project::Project;
+use serde::Deserialize;
use std::path::Path;
use std::rc::Rc;
use std::{any::Any, cell::RefCell};
@@ -27,6 +28,7 @@ pub struct AcpConnection {
pub struct AcpSession {
thread: WeakEntity<AcpThread>,
+ pending_cancel: bool,
}
const MINIMUM_SUPPORTED_VERSION: acp::ProtocolVersion = acp::V1;
@@ -171,6 +173,7 @@ impl AgentConnection for AcpConnection {
let session = AcpSession {
thread: thread.downgrade(),
+ pending_cancel: false,
};
sessions.borrow_mut().insert(session_id, session);
@@ -202,9 +205,48 @@ impl AgentConnection for AcpConnection {
cx: &mut App,
) -> Task<Result<acp::PromptResponse>> {
let conn = self.connection.clone();
+ let sessions = self.sessions.clone();
+ let session_id = params.session_id.clone();
cx.foreground_executor().spawn(async move {
- let response = conn.prompt(params).await?;
- Ok(response)
+ match conn.prompt(params).await {
+ Ok(response) => Ok(response),
+ Err(err) => {
+ if err.code != ErrorCode::INTERNAL_ERROR.code {
+ anyhow::bail!(err)
+ }
+
+ let Some(data) = &err.data else {
+ anyhow::bail!(err)
+ };
+
+ // Temporary workaround until the following PR is generally available:
+ // https://github.com/google-gemini/gemini-cli/pull/6656
+
+ #[derive(Deserialize)]
+ #[serde(deny_unknown_fields)]
+ struct ErrorDetails {
+ details: Box<str>,
+ }
+
+ 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")
+ {
+ Ok(acp::PromptResponse {
+ stop_reason: acp::StopReason::Canceled,
+ })
+ } else {
+ Err(anyhow!(details))
+ }
+ }
+ Err(_) => Err(anyhow!(err)),
+ }
+ }
+ }
})
}
@@ -213,12 +255,23 @@ 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;
+ }
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 { conn.cancel(params).await })
+ .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
+ })
.detach();
}