diff --git a/Cargo.lock b/Cargo.lock index a4371765847..f3f558c32ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,9 +210,9 @@ dependencies = [ [[package]] name = "agent-client-protocol" -version = "0.5.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f655394a107cd601bd2e5375c2d909ea83adc65678a0e0e8d77613d3c848a7d" +checksum = "525705e39c11cd73f7bc784e3681a9386aa30c8d0630808d3dc2237eb4f9cb1b" dependencies = [ "agent-client-protocol-schema", "anyhow", @@ -228,9 +228,9 @@ dependencies = [ [[package]] name = "agent-client-protocol-schema" -version = "0.4.11" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61be4454304d7df1a5b44c4ae55e707ffe72eac4dfb1ef8762510ce8d8f6d924" +checksum = "ecf16c18fea41282d6bbadd1549a06be6836bddb1893f44a6235f340fa24e2af" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -266,6 +266,7 @@ dependencies = [ "log", "nix 0.29.0", "project", + "release_channel", "reqwest_client", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 8e9ab428c31..d69d768f33e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -438,7 +438,7 @@ zlog_settings = { path = "crates/zlog_settings" } # External crates # -agent-client-protocol = { version = "0.5.0", features = ["unstable"] } +agent-client-protocol = { version = "0.7.0", features = ["unstable"] } aho-corasick = "1.1" alacritty_terminal = "0.25.1-rc1" any_vec = "0.14" diff --git a/crates/acp_thread/src/acp_thread.rs b/crates/acp_thread/src/acp_thread.rs index 4d8c57dd8f5..99c62201fa0 100644 --- a/crates/acp_thread/src/acp_thread.rs +++ b/crates/acp_thread/src/acp_thread.rs @@ -1105,13 +1105,13 @@ impl AcpThread { cx: &mut Context, ) -> Result<(), acp::Error> { match update { - acp::SessionUpdate::UserMessageChunk { content } => { + acp::SessionUpdate::UserMessageChunk(acp::ContentChunk { content, .. }) => { self.push_user_content_block(None, content, cx); } - acp::SessionUpdate::AgentMessageChunk { content } => { + acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk { content, .. }) => { self.push_assistant_content_block(content, false, cx); } - acp::SessionUpdate::AgentThoughtChunk { content } => { + acp::SessionUpdate::AgentThoughtChunk(acp::ContentChunk { content, .. }) => { self.push_assistant_content_block(content, true, cx); } acp::SessionUpdate::ToolCall(tool_call) => { @@ -1123,12 +1123,14 @@ impl AcpThread { acp::SessionUpdate::Plan(plan) => { self.update_plan(plan, cx); } - acp::SessionUpdate::AvailableCommandsUpdate { available_commands } => { - cx.emit(AcpThreadEvent::AvailableCommandsUpdated(available_commands)) - } - acp::SessionUpdate::CurrentModeUpdate { current_mode_id } => { - cx.emit(AcpThreadEvent::ModeUpdated(current_mode_id)) - } + acp::SessionUpdate::AvailableCommandsUpdate(acp::AvailableCommandsUpdate { + available_commands, + .. + }) => cx.emit(AcpThreadEvent::AvailableCommandsUpdated(available_commands)), + acp::SessionUpdate::CurrentModeUpdate(acp::CurrentModeUpdate { + current_mode_id, + .. + }) => cx.emit(AcpThreadEvent::ModeUpdated(current_mode_id)), } Ok(()) } @@ -2586,17 +2588,19 @@ mod tests { thread.update(&mut cx, |thread, cx| { thread .handle_session_update( - acp::SessionUpdate::AgentThoughtChunk { + acp::SessionUpdate::AgentThoughtChunk(acp::ContentChunk { content: "Thinking ".into(), - }, + meta: None, + }), cx, ) .unwrap(); thread .handle_session_update( - acp::SessionUpdate::AgentThoughtChunk { + acp::SessionUpdate::AgentThoughtChunk(acp::ContentChunk { content: "hard!".into(), - }, + meta: None, + }), cx, ) .unwrap(); @@ -3095,9 +3099,10 @@ mod tests { thread.update(&mut cx, |thread, cx| { thread .handle_session_update( - acp::SessionUpdate::AgentMessageChunk { + acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk { content: content.text.to_uppercase().into(), - }, + meta: None, + }), cx, ) .unwrap(); @@ -3454,9 +3459,10 @@ mod tests { thread.update(&mut cx, |thread, cx| { thread .handle_session_update( - acp::SessionUpdate::AgentMessageChunk { + acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk { content: content.text.to_uppercase().into(), - }, + meta: None, + }), cx, ) .unwrap(); diff --git a/crates/agent_servers/Cargo.toml b/crates/agent_servers/Cargo.toml index fcdba2301ee..d427290736f 100644 --- a/crates/agent_servers/Cargo.toml +++ b/crates/agent_servers/Cargo.toml @@ -38,6 +38,7 @@ language_model.workspace = true language_models.workspace = true log.workspace = true project.workspace = true +release_channel.workspace = true reqwest_client = { workspace = true, optional = true } serde.workspace = true serde_json.workspace = true diff --git a/crates/agent_servers/src/acp.rs b/crates/agent_servers/src/acp.rs index 6f92b958b2d..3a1d5c9fa84 100644 --- a/crates/agent_servers/src/acp.rs +++ b/crates/agent_servers/src/acp.rs @@ -105,6 +105,14 @@ impl AcpConnection { let sessions = Rc::new(RefCell::new(HashMap::default())); + let (release_channel, version) = cx.update(|cx| { + ( + release_channel::ReleaseChannel::try_global(cx) + .map(|release_channel| release_channel.display_name()), + release_channel::AppVersion::global(cx).to_string(), + ) + })?; + let client = ClientDelegate { sessions: sessions.clone(), cx: cx.clone(), @@ -172,6 +180,11 @@ impl AcpConnection { "terminal_output": true, })), }, + client_info: Some(acp::Implementation { + name: "zed".to_owned(), + title: release_channel.map(|c| c.to_owned()), + version, + }), meta: None, }) .await?; @@ -700,7 +713,11 @@ impl acp::Client for ClientDelegate { .get(¬ification.session_id) .context("Failed to get session")?; - if let acp::SessionUpdate::CurrentModeUpdate { current_mode_id } = ¬ification.update { + if let acp::SessionUpdate::CurrentModeUpdate(acp::CurrentModeUpdate { + current_mode_id, + .. + }) = ¬ification.update + { if let Some(session_modes) = &session.session_modes { session_modes.borrow_mut().current_mode_id = current_mode_id.clone(); } else { diff --git a/crates/agent_ui/src/acp/thread_view.rs b/crates/agent_ui/src/acp/thread_view.rs index 8e5396590fe..7e5d5b48a13 100644 --- a/crates/agent_ui/src/acp/thread_view.rs +++ b/crates/agent_ui/src/acp/thread_view.rs @@ -5981,9 +5981,12 @@ pub(crate) mod tests { impl StubAgentServer { fn default_response() -> Self { let conn = StubAgentConnection::new(); - conn.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk { - content: "Default response".into(), - }]); + conn.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk( + acp::ContentChunk { + content: "Default response".into(), + meta: None, + }, + )]); Self::new(conn) } } @@ -6334,13 +6337,16 @@ pub(crate) mod tests { let connection = StubAgentConnection::new(); - connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk { - content: acp::ContentBlock::Text(acp::TextContent { - text: "Response".into(), - annotations: None, + connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk( + acp::ContentChunk { + content: acp::ContentBlock::Text(acp::TextContent { + text: "Response".into(), + annotations: None, + meta: None, + }), meta: None, - }), - }]); + }, + )]); let (thread_view, cx) = setup_thread_view(StubAgentServer::new(connection), cx).await; add_to_workspace(thread_view.clone(), cx); @@ -6424,13 +6430,16 @@ pub(crate) mod tests { let connection = StubAgentConnection::new(); - connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk { - content: acp::ContentBlock::Text(acp::TextContent { - text: "Response".into(), - annotations: None, + connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk( + acp::ContentChunk { + content: acp::ContentBlock::Text(acp::TextContent { + text: "Response".into(), + annotations: None, + meta: None, + }), meta: None, - }), - }]); + }, + )]); let (thread_view, cx) = setup_thread_view(StubAgentServer::new(connection.clone()), cx).await; @@ -6468,13 +6477,16 @@ pub(crate) mod tests { }); // Send - connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk { - content: acp::ContentBlock::Text(acp::TextContent { - text: "New Response".into(), - annotations: None, + connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk( + acp::ContentChunk { + content: acp::ContentBlock::Text(acp::TextContent { + text: "New Response".into(), + annotations: None, + meta: None, + }), meta: None, - }), - }]); + }, + )]); user_message_editor.update_in(cx, |_editor, window, cx| { window.dispatch_action(Box::new(Chat), cx); @@ -6561,13 +6573,14 @@ pub(crate) mod tests { cx.update(|_, cx| { connection.send_update( session_id.clone(), - acp::SessionUpdate::AgentMessageChunk { + acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk { content: acp::ContentBlock::Text(acp::TextContent { text: "Response".into(), annotations: None, meta: None, }), - }, + meta: None, + }), cx, ); connection.end_turn(session_id, acp::StopReason::EndTurn); @@ -6619,9 +6632,10 @@ pub(crate) mod tests { cx.update(|_, cx| { connection.send_update( session_id.clone(), - acp::SessionUpdate::AgentMessageChunk { + acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk { content: "Message 1 resp".into(), - }, + meta: None, + }), cx, ); }); @@ -6655,9 +6669,10 @@ pub(crate) mod tests { // Simulate a response sent after beginning to cancel connection.send_update( session_id.clone(), - acp::SessionUpdate::AgentMessageChunk { + acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk { content: "onse".into(), - }, + meta: None, + }), cx, ); }); @@ -6688,9 +6703,10 @@ pub(crate) mod tests { cx.update(|_, cx| { connection.send_update( session_id.clone(), - acp::SessionUpdate::AgentMessageChunk { + acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk { content: "Message 2 response".into(), - }, + meta: None, + }), cx, ); connection.end_turn(session_id.clone(), acp::StopReason::EndTurn); @@ -6728,13 +6744,16 @@ pub(crate) mod tests { init_test(cx); let connection = StubAgentConnection::new(); - connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk { - content: acp::ContentBlock::Text(acp::TextContent { - text: "Response".into(), - annotations: None, + connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk( + acp::ContentChunk { + content: acp::ContentBlock::Text(acp::TextContent { + text: "Response".into(), + annotations: None, + meta: None, + }), meta: None, - }), - }]); + }, + )]); let (thread_view, cx) = setup_thread_view(StubAgentServer::new(connection), cx).await; add_to_workspace(thread_view.clone(), cx); @@ -6811,13 +6830,16 @@ pub(crate) mod tests { init_test(cx); let connection = StubAgentConnection::new(); - connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk { - content: acp::ContentBlock::Text(acp::TextContent { - text: "Response".into(), - annotations: None, + connection.set_next_prompt_updates(vec![acp::SessionUpdate::AgentMessageChunk( + acp::ContentChunk { + content: acp::ContentBlock::Text(acp::TextContent { + text: "Response".into(), + annotations: None, + meta: None, + }), meta: None, - }), - }]); + }, + )]); let (thread_view, cx) = setup_thread_view(StubAgentServer::new(connection), cx).await; add_to_workspace(thread_view.clone(), cx);