Split out login_commands and logout_commands

This commit is contained in:
Richard Feldman
2025-10-22 11:03:47 -04:00
parent b00901c126
commit 4232b59a59
4 changed files with 53 additions and 12 deletions

View File

@@ -68,6 +68,20 @@ pub trait AgentServer: Send {
) {
}
/// Returns the list of slash commands that should trigger Zed's authentication UI
/// when the user types them (e.g., "/login").
/// These commands will be intercepted by Zed to show the auth method selection UI.
fn login_commands(&self) -> Vec<&'static str> {
Vec::new()
}
/// Returns the list of logout-related slash commands that should be sent to the agent
/// to let it reset internal state (e.g., "/logout").
/// These commands will be added to available_commands and passed through to the agent.
fn logout_commands(&self) -> Vec<&'static str> {
Vec::new()
}
fn connect(
&self,
root_dir: Option<&Path>,

View File

@@ -56,6 +56,14 @@ impl AgentServer for ClaudeCode {
});
}
fn login_commands(&self) -> Vec<&'static str> {
vec!["login"]
}
fn logout_commands(&self) -> Vec<&'static str> {
vec!["logout"]
}
fn connect(
&self,
root_dir: Option<&Path>,

View File

@@ -25,6 +25,10 @@ impl AgentServer for Gemini {
ui::IconName::AiGemini
}
fn login_commands(&self) -> Vec<&'static str> {
vec!["login"]
}
fn connect(
&self,
root_dir: Option<&Path>,

View File

@@ -1052,20 +1052,36 @@ impl AcpThreadView {
let text = self.message_editor.read(cx).text(cx);
let text = text.trim();
if text == "/login" || text == "/logout" {
// Check if this is a login or logout command
let command_name = text.strip_prefix('/');
let is_login_command = if let Some(cmd) = command_name {
self.agent.login_commands().contains(&cmd)
} else {
false
};
let is_logout_command = if let Some(cmd) = command_name {
self.agent.logout_commands().contains(&cmd)
} else {
false
};
if is_login_command || is_logout_command {
let ThreadState::Ready { thread, .. } = &self.thread_state else {
return;
};
let connection = thread.read(cx).connection().clone();
let can_login = !connection.auth_methods().is_empty() || !self.auth_commands.is_empty();
// Does the agent have a specific logout command? Prefer that in case they need to reset internal state.
let logout_supported = text == "/logout"
let logout_supported = is_logout_command
&& self
.available_commands
.borrow()
.iter()
.any(|command| command.name == "logout");
.any(|command| command_name == Some(command.name.as_str()));
if can_login && !logout_supported {
self.message_editor
.update(cx, |editor, cx| editor.clear(window, cx));
@@ -1422,21 +1438,20 @@ impl AcpThreadView {
AcpThreadEvent::AvailableCommandsUpdated(available_commands) => {
let mut available_commands = available_commands.clone();
if thread
.read(cx)
.connection()
.auth_methods()
.iter()
.any(|method| method.id.0.as_ref() == "claude-login")
{
// Add login commands from the agent
for command_name in self.agent.login_commands() {
available_commands.push(acp::AvailableCommand {
name: "login".to_owned(),
name: command_name.to_owned(),
description: "Authenticate".to_owned(),
input: None,
meta: None,
});
}
// Add logout commands from the agent
for command_name in self.agent.logout_commands() {
available_commands.push(acp::AvailableCommand {
name: "logout".to_owned(),
name: command_name.to_owned(),
description: "Authenticate".to_owned(),
input: None,
meta: None,