Skip to content

Commit d0a2476

Browse files
agu-zcole-miller
authored andcommitted
acp: Receive available commands over notifications (zed-industries#37499)
See: agentclientprotocol/agent-client-protocol#62 Release Notes: - Agent Panel: Fixes an issue where Claude Code would timeout waiting for slash commands to be loaded Co-authored-by: Cole Miller <cole@zed.dev>
1 parent 5bef3fb commit d0a2476

9 files changed

Lines changed: 34 additions & 37 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ zlog_settings = { path = "crates/zlog_settings" }
430430
# External crates
431431
#
432432

433-
agent-client-protocol = { version = "0.2.0-alpha.4", features = ["unstable"]}
433+
agent-client-protocol = { version = "0.2.0-alpha.6", features = ["unstable"]}
434434
aho-corasick = "1.1"
435435
alacritty_terminal = { git = "https://github.com/zed-industries/alacritty.git", branch = "add-hush-login-flag" }
436436
any_vec = "0.14"

crates/acp_thread/src/acp_thread.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,6 @@ pub struct AcpThread {
785785
session_id: acp::SessionId,
786786
token_usage: Option<TokenUsage>,
787787
prompt_capabilities: acp::PromptCapabilities,
788-
available_commands: Vec<acp::AvailableCommand>,
789788
_observe_prompt_capabilities: Task<anyhow::Result<()>>,
790789
determine_shell: Shared<Task<String>>,
791790
terminals: HashMap<acp::TerminalId, Entity<Terminal>>,
@@ -805,6 +804,7 @@ pub enum AcpThreadEvent {
805804
LoadError(LoadError),
806805
PromptCapabilitiesUpdated,
807806
Refusal,
807+
AvailableCommandsUpdated(Vec<acp::AvailableCommand>),
808808
}
809809

810810
impl EventEmitter<AcpThreadEvent> for AcpThread {}
@@ -860,7 +860,6 @@ impl AcpThread {
860860
action_log: Entity<ActionLog>,
861861
session_id: acp::SessionId,
862862
mut prompt_capabilities_rx: watch::Receiver<acp::PromptCapabilities>,
863-
available_commands: Vec<acp::AvailableCommand>,
864863
cx: &mut Context<Self>,
865864
) -> Self {
866865
let prompt_capabilities = *prompt_capabilities_rx.borrow();
@@ -900,7 +899,6 @@ impl AcpThread {
900899
session_id,
901900
token_usage: None,
902901
prompt_capabilities,
903-
available_commands,
904902
_observe_prompt_capabilities: task,
905903
terminals: HashMap::default(),
906904
determine_shell,
@@ -911,10 +909,6 @@ impl AcpThread {
911909
self.prompt_capabilities
912910
}
913911

914-
pub fn available_commands(&self) -> Vec<acp::AvailableCommand> {
915-
self.available_commands.clone()
916-
}
917-
918912
pub fn connection(&self) -> &Rc<dyn AgentConnection> {
919913
&self.connection
920914
}
@@ -1010,6 +1004,9 @@ impl AcpThread {
10101004
acp::SessionUpdate::Plan(plan) => {
10111005
self.update_plan(plan, cx);
10121006
}
1007+
acp::SessionUpdate::AvailableCommandsUpdate { available_commands } => {
1008+
cx.emit(AcpThreadEvent::AvailableCommandsUpdated(available_commands))
1009+
}
10131010
}
10141011
Ok(())
10151012
}
@@ -3080,7 +3077,6 @@ mod tests {
30803077
audio: true,
30813078
embedded_context: true,
30823079
}),
3083-
vec![],
30843080
cx,
30853081
)
30863082
});

crates/acp_thread/src/connection.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@ mod test_support {
338338
audio: true,
339339
embedded_context: true,
340340
}),
341-
vec![],
342341
cx,
343342
)
344343
});

crates/agent2/src/agent.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,6 @@ impl NativeAgent {
292292
action_log.clone(),
293293
session_id.clone(),
294294
prompt_capabilities_rx,
295-
vec![],
296295
cx,
297296
)
298297
});

crates/agent_servers/src/acp.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ impl AgentConnection for AcpConnection {
224224
session_id.clone(),
225225
// ACP doesn't currently support per-session prompt capabilities or changing capabilities dynamically.
226226
watch::Receiver::constant(self.agent_capabilities.prompt_capabilities),
227-
response.available_commands,
228227
cx,
229228
)
230229
})?;

crates/agent_servers/src/claude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl ClaudeCode {
4040
Self::PACKAGE_NAME.into(),
4141
"node_modules/@anthropic-ai/claude-code/cli.js".into(),
4242
true,
43-
None,
43+
Some("0.2.5".parse().unwrap()),
4444
cx,
4545
)
4646
})?

crates/agent_ui/src/acp/thread_view.rs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ impl AcpThreadView {
430430
window,
431431
cx,
432432
);
433+
self.available_commands.replace(vec![]);
433434
self.new_server_version_available.take();
434435
cx.notify();
435436
}
@@ -535,26 +536,6 @@ impl AcpThreadView {
535536
Ok(thread) => {
536537
let action_log = thread.read(cx).action_log().clone();
537538

538-
let mut available_commands = thread.read(cx).available_commands();
539-
540-
if connection
541-
.auth_methods()
542-
.iter()
543-
.any(|method| method.id.0.as_ref() == "claude-login")
544-
{
545-
available_commands.push(acp::AvailableCommand {
546-
name: "login".to_owned(),
547-
description: "Authenticate".to_owned(),
548-
input: None,
549-
});
550-
available_commands.push(acp::AvailableCommand {
551-
name: "logout".to_owned(),
552-
description: "Authenticate".to_owned(),
553-
input: None,
554-
});
555-
}
556-
this.available_commands.replace(available_commands);
557-
558539
this.prompt_capabilities
559540
.set(thread.read(cx).prompt_capabilities());
560541

@@ -1343,6 +1324,30 @@ impl AcpThreadView {
13431324
.set(thread.read(cx).prompt_capabilities());
13441325
}
13451326
AcpThreadEvent::TokenUsageUpdated => {}
1327+
AcpThreadEvent::AvailableCommandsUpdated(available_commands) => {
1328+
let mut available_commands = available_commands.clone();
1329+
1330+
if thread
1331+
.read(cx)
1332+
.connection()
1333+
.auth_methods()
1334+
.iter()
1335+
.any(|method| method.id.0.as_ref() == "claude-login")
1336+
{
1337+
available_commands.push(acp::AvailableCommand {
1338+
name: "login".to_owned(),
1339+
description: "Authenticate".to_owned(),
1340+
input: None,
1341+
});
1342+
available_commands.push(acp::AvailableCommand {
1343+
name: "logout".to_owned(),
1344+
description: "Authenticate".to_owned(),
1345+
input: None,
1346+
});
1347+
}
1348+
1349+
self.available_commands.replace(available_commands);
1350+
}
13461351
}
13471352
cx.notify();
13481353
}
@@ -5745,7 +5750,6 @@ pub(crate) mod tests {
57455750
audio: true,
57465751
embedded_context: true,
57475752
}),
5748-
vec![],
57495753
cx,
57505754
)
57515755
})))
@@ -5805,7 +5809,6 @@ pub(crate) mod tests {
58055809
audio: true,
58065810
embedded_context: true,
58075811
}),
5808-
Vec::new(),
58095812
cx,
58105813
)
58115814
})))

crates/agent_ui/src/agent_diff.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,6 +1528,7 @@ impl AgentDiff {
15281528
| AcpThreadEvent::EntriesRemoved(_)
15291529
| AcpThreadEvent::ToolAuthorizationRequired
15301530
| AcpThreadEvent::PromptCapabilitiesUpdated
1531+
| AcpThreadEvent::AvailableCommandsUpdated(_)
15311532
| AcpThreadEvent::Retry(_) => {}
15321533
}
15331534
}

0 commit comments

Comments
 (0)