ACP champagne (#35609)

cherry pick changes from #35510 onto latest main

Release Notes:

- N/A

---------

Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Lukas Wirth <lukas@zed.dev>
This commit is contained in:
Ben Brandt 2025-08-06 11:01:06 +02:00 committed by GitHub
parent 69794db331
commit eb4b73b88e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 2361 additions and 67 deletions

View file

@ -464,7 +464,11 @@ impl AgentConnection for AcpConnection {
})
}
fn prompt(&self, params: acp::PromptRequest, cx: &mut App) -> Task<Result<()>> {
fn prompt(
&self,
params: acp::PromptRequest,
cx: &mut App,
) -> Task<Result<acp::PromptResponse>> {
let chunks = params
.prompt
.into_iter()
@ -484,7 +488,9 @@ impl AgentConnection for AcpConnection {
.request_any(acp_old::SendUserMessageParams { chunks }.into_any());
cx.foreground_executor().spawn(async move {
task.await?;
anyhow::Ok(())
anyhow::Ok(acp::PromptResponse {
stop_reason: acp::StopReason::EndTurn,
})
})
}

View file

@ -169,11 +169,15 @@ impl AgentConnection for AcpConnection {
})
}
fn prompt(&self, params: acp::PromptRequest, cx: &mut App) -> Task<Result<()>> {
fn prompt(
&self,
params: acp::PromptRequest,
cx: &mut App,
) -> Task<Result<acp::PromptResponse>> {
let conn = self.connection.clone();
cx.foreground_executor().spawn(async move {
conn.prompt(params).await?;
Ok(())
let response = conn.prompt(params).await?;
Ok(response)
})
}

View file

@ -200,7 +200,11 @@ impl AgentConnection for ClaudeAgentConnection {
Task::ready(Err(anyhow!("Authentication not supported")))
}
fn prompt(&self, params: acp::PromptRequest, cx: &mut App) -> Task<Result<()>> {
fn prompt(
&self,
params: acp::PromptRequest,
cx: &mut App,
) -> Task<Result<acp::PromptResponse>> {
let sessions = self.sessions.borrow();
let Some(session) = sessions.get(&params.session_id) else {
return Task::ready(Err(anyhow!(
@ -244,10 +248,7 @@ impl AgentConnection for ClaudeAgentConnection {
return Task::ready(Err(anyhow!(err)));
}
cx.foreground_executor().spawn(async move {
rx.await??;
Ok(())
})
cx.foreground_executor().spawn(async move { rx.await? })
}
fn cancel(&self, session_id: &acp::SessionId, _cx: &mut App) {
@ -261,6 +262,14 @@ impl AgentConnection for ClaudeAgentConnection {
.outgoing_tx
.unbounded_send(SdkMessage::new_interrupt_message())
.log_err();
if let Some(end_turn_tx) = session.end_turn_tx.borrow_mut().take() {
end_turn_tx
.send(Ok(acp::PromptResponse {
stop_reason: acp::StopReason::Cancelled,
}))
.ok();
}
}
}
@ -322,7 +331,7 @@ fn spawn_claude(
struct ClaudeAgentSession {
outgoing_tx: UnboundedSender<SdkMessage>,
end_turn_tx: Rc<RefCell<Option<oneshot::Sender<Result<()>>>>>,
end_turn_tx: Rc<RefCell<Option<oneshot::Sender<Result<acp::PromptResponse>>>>>,
_mcp_server: Option<ClaudeZedMcpServer>,
_handler_task: Task<()>,
}
@ -331,7 +340,7 @@ impl ClaudeAgentSession {
async fn handle_message(
mut thread_rx: watch::Receiver<WeakEntity<AcpThread>>,
message: SdkMessage,
end_turn_tx: Rc<RefCell<Option<oneshot::Sender<Result<()>>>>>,
end_turn_tx: Rc<RefCell<Option<oneshot::Sender<Result<acp::PromptResponse>>>>>,
cx: &mut AsyncApp,
) {
match message {
@ -436,7 +445,7 @@ impl ClaudeAgentSession {
..
} => {
if let Some(end_turn_tx) = end_turn_tx.borrow_mut().take() {
if is_error {
if is_error || subtype == ResultErrorType::ErrorDuringExecution {
end_turn_tx
.send(Err(anyhow!(
"Error: {}",
@ -444,7 +453,14 @@ impl ClaudeAgentSession {
)))
.ok();
} else {
end_turn_tx.send(Ok(())).ok();
let stop_reason = match subtype {
ResultErrorType::Success => acp::StopReason::EndTurn,
ResultErrorType::ErrorMaxTurns => acp::StopReason::MaxTurnRequests,
ResultErrorType::ErrorDuringExecution => unreachable!(),
};
end_turn_tx
.send(Ok(acp::PromptResponse { stop_reason }))
.ok();
}
}
}
@ -669,7 +685,7 @@ struct ControlResponse {
subtype: ResultErrorType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
enum ResultErrorType {
Success,