Detailed changes
@@ -34,6 +34,22 @@ impl AgentServer for NativeAgentServer {
ui::IconName::ZedAgent
}
+ fn local_login_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn remote_login_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn local_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn remote_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
fn connect(
&self,
_root_dir: Option<&Path>,
@@ -69,14 +69,24 @@ 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").
+ /// when running locally (e.g., "/login").
/// These commands will be intercepted by Zed to show the auth method selection UI.
- fn login_commands(&self) -> Vec<&'static str>;
+ fn local_login_commands(&self) -> Vec<&'static str>;
+
+ /// Returns the list of slash commands that should trigger Zed's authentication UI
+ /// when running remotely (e.g., "/login").
+ /// These commands will be intercepted by Zed to show the auth method selection UI.
+ fn remote_login_commands(&self) -> Vec<&'static str>;
+
+ /// Returns the list of logout-related slash commands that should be sent to the agent
+ /// when running locally to let it reset internal state (e.g., "/logout").
+ /// These commands will be added to available_commands and passed through to the agent.
+ fn local_logout_commands(&self) -> Vec<&'static str>;
/// Returns the list of logout-related slash commands that should be sent to the agent
- /// to let it reset internal state (e.g., "/logout").
+ /// when running remotely 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>;
+ fn remote_logout_commands(&self) -> Vec<&'static str>;
fn connect(
&self,
@@ -56,11 +56,19 @@ impl AgentServer for ClaudeCode {
});
}
- fn login_commands(&self) -> Vec<&'static str> {
+ fn local_login_commands(&self) -> Vec<&'static str> {
vec!["login"]
}
- fn logout_commands(&self) -> Vec<&'static str> {
+ fn remote_login_commands(&self) -> Vec<&'static str> {
+ vec!["login"]
+ }
+
+ fn local_logout_commands(&self) -> Vec<&'static str> {
+ vec!["logout"]
+ }
+
+ fn remote_logout_commands(&self) -> Vec<&'static str> {
vec!["logout"]
}
@@ -36,6 +36,22 @@ impl AgentServer for Codex {
ui::IconName::AiOpenAi
}
+ fn local_login_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn remote_login_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn local_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn remote_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
fn default_mode(&self, cx: &mut App) -> Option<acp::SessionModeId> {
let settings = cx.read_global(|settings: &SettingsStore, _| {
settings.get::<AllAgentServersSettings>(None).codex.clone()
@@ -34,6 +34,22 @@ impl crate::AgentServer for CustomAgentServer {
IconName::Terminal
}
+ fn local_login_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn remote_login_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn local_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn remote_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
fn default_mode(&self, cx: &mut App) -> Option<acp::SessionModeId> {
let settings = cx.read_global(|settings: &SettingsStore, _| {
settings
@@ -25,10 +25,24 @@ impl AgentServer for Gemini {
ui::IconName::AiGemini
}
- fn login_commands(&self) -> Vec<&'static str> {
+ fn local_login_commands(&self) -> Vec<&'static str> {
vec!["login"]
}
+ fn remote_login_commands(&self) -> Vec<&'static str> {
+ // When remote, OAuth doesn't work, so login is handled via the
+ // auth_commands mapping (oauth-personal -> spawn-gemini-cli)
+ vec![]
+ }
+
+ fn local_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn remote_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
fn connect(
&self,
root_dir: Option<&Path>,
@@ -57,7 +71,7 @@ impl AgentServer for Gemini {
{
extra_env.insert("GEMINI_API_KEY".into(), api_key);
}
- let (command, root_dir, mut auth_commands) = store
+ let (command, root_dir, auth_commands) = store
.update(cx, |store, cx| {
let agent = store
.get_external_agent(&GEMINI_NAME.into())
@@ -72,14 +86,6 @@ impl AgentServer for Gemini {
})??
.await?;
- // When remote, OAuth doesn't work, so we need to use the terminal-based login
- // for oauth-personal. Map it to the same terminal command as spawn-gemini-cli.
- if is_remote {
- if let Some(spawn_gemini_cli) = auth_commands.get("spawn-gemini-cli").cloned() {
- auth_commands.insert("oauth-personal".to_string(), spawn_gemini_cli);
- }
- }
-
let connection = crate::acp::connect(
name,
command,
@@ -1055,13 +1055,24 @@ impl AcpThreadView {
// Check if this is a login or logout command
let command_name = text.strip_prefix('/');
+ let is_remote = self.project.read(cx).is_via_remote_server();
+ let login_commands = if is_remote {
+ self.agent.remote_login_commands()
+ } else {
+ self.agent.local_login_commands()
+ };
+ let logout_commands = if is_remote {
+ self.agent.remote_logout_commands()
+ } else {
+ self.agent.local_logout_commands()
+ };
let is_login_command = if let Some(cmd) = command_name {
- self.agent.login_commands().contains(&cmd)
+ login_commands.contains(&cmd)
} else {
false
};
let is_logout_command = if let Some(cmd) = command_name {
- self.agent.logout_commands().contains(&cmd)
+ logout_commands.contains(&cmd)
} else {
false
};
@@ -1438,10 +1449,22 @@ impl AcpThreadView {
AcpThreadEvent::AvailableCommandsUpdated(available_commands) => {
let mut available_commands = available_commands.clone();
+ let is_remote = self.project.read(cx).is_via_remote_server();
+ let login_commands = if is_remote {
+ self.agent.remote_login_commands()
+ } else {
+ self.agent.local_login_commands()
+ };
+ let logout_commands = if is_remote {
+ self.agent.remote_logout_commands()
+ } else {
+ self.agent.local_logout_commands()
+ };
+
// Add login commands from the agent
- for command_name in self.agent.login_commands() {
+ for command_name in login_commands {
available_commands.push(acp::AvailableCommand {
- name: command_name.to_owned(),
+ name: command_name.to_string(),
description: "Authenticate".to_owned(),
input: None,
meta: None,
@@ -1449,9 +1472,9 @@ impl AcpThreadView {
}
// Add logout commands from the agent
- for command_name in self.agent.logout_commands() {
+ for command_name in logout_commands {
available_commands.push(acp::AvailableCommand {
- name: command_name.to_owned(),
+ name: command_name.to_string(),
description: "Authenticate".to_owned(),
input: None,
meta: None,
@@ -6027,6 +6050,22 @@ pub(crate) mod tests {
"Test".into()
}
+ fn local_login_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn remote_login_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn local_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
+ fn remote_logout_commands(&self) -> Vec<&'static str> {
+ vec![]
+ }
+
fn connect(
&self,
_root_dir: Option<&Path>,