acp: Start sending Client Info to the Agent (#41265)

Updates to acp crate 0.7, which allows us to send information about the
client to the Agent.
In the future, we can also use the AgentInfo on the response for
internal metrics.

Release Notes:

- N/A
This commit is contained in:
Ben Brandt
2025-10-27 10:05:50 +00:00
committed by GitHub
parent ae3abf50d8
commit 7cb2d83608
6 changed files with 111 additions and 64 deletions
Generated
+5 -4
View File
@@ -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",
+1 -1
View File
@@ -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"
+23 -17
View File
@@ -1105,13 +1105,13 @@ impl AcpThread {
cx: &mut Context<Self>,
) -> 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();
+1
View File
@@ -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
+18 -1
View File
@@ -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(&notification.session_id)
.context("Failed to get session")?;
if let acp::SessionUpdate::CurrentModeUpdate { current_mode_id } = &notification.update {
if let acp::SessionUpdate::CurrentModeUpdate(acp::CurrentModeUpdate {
current_mode_id,
..
}) = &notification.update
{
if let Some(session_modes) = &session.session_modes {
session_modes.borrow_mut().current_mode_id = current_mode_id.clone();
} else {
+63 -41
View File
@@ -5981,9 +5981,12 @@ pub(crate) mod tests {
impl StubAgentServer<StubAgentConnection> {
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);