acp: Fix spawning login task (#38567)

Reverts #38175, which is not correct, since in fact we do need to
pre-quote the command and arguments for the shell when using
`SpawnInTerminal` (although we should probably change the API so that
this isn't necessary). Then, applies the same fix as #38565 to fix the
root cause of being unable to spawn the login task on macOS, or in any
case where the command/args contain spaces.

Release Notes:

- Fixed being unable to login with Claude Code or Gemini using the
terminal.
This commit is contained in:
Cole Miller
2025-09-20 14:14:55 -04:00
committed by GitHub
parent f5c2e4b49e
commit 18df6a81b4
3 changed files with 17 additions and 19 deletions
Generated
+1
View File
@@ -419,6 +419,7 @@ dependencies = [
"serde_json",
"serde_json_lenient",
"settings",
"shlex",
"smol",
"streaming_diff",
"task",
+1
View File
@@ -80,6 +80,7 @@ serde.workspace = true
serde_json.workspace = true
serde_json_lenient.workspace = true
settings.workspace = true
shlex.workspace = true
smol.workspace = true
streaming_diff.workspace = true
task.workspace = true
+15 -19
View File
@@ -9,7 +9,7 @@ use agent_client_protocol::{self as acp, PromptCapabilities};
use agent_servers::{AgentServer, AgentServerDelegate};
use agent_settings::{AgentProfileId, AgentSettings, CompletionMode};
use agent2::{DbThreadMetadata, HistoryEntry, HistoryEntryId, HistoryStore, NativeAgentServer};
use anyhow::{Result, anyhow, bail};
use anyhow::{Context as _, Result, anyhow, bail};
use arrayvec::ArrayVec;
use audio::{Audio, Sound};
use buffer_diff::BufferDiff;
@@ -1582,6 +1582,19 @@ impl AcpThreadView {
window.spawn(cx, async move |cx| {
let mut task = login.clone();
task.command = task
.command
.map(|command| anyhow::Ok(shlex::try_quote(&command)?.to_string()))
.transpose()?;
task.args = task
.args
.iter()
.map(|arg| {
Ok(shlex::try_quote(arg)
.context("Failed to quote argument")?
.to_string())
})
.collect::<Result<Vec<_>>>()?;
task.full_label = task.label.clone();
task.id = task::TaskId(format!("external-agent-{}-login", task.label));
task.command_label = task.label.clone();
@@ -1591,7 +1604,7 @@ impl AcpThreadView {
task.shell = shell;
let terminal = terminal_panel.update_in(cx, |terminal_panel, window, cx| {
terminal_panel.spawn_task(&login, window, cx)
terminal_panel.spawn_task(&task, window, cx)
})?;
let terminal = terminal.await?;
@@ -5669,23 +5682,6 @@ pub(crate) mod tests {
});
}
#[gpui::test]
async fn test_spawn_external_agent_login_handles_spaces(cx: &mut TestAppContext) {
init_test(cx);
// Verify paths with spaces aren't pre-quoted
let path_with_spaces = "/Users/test/Library/Application Support/Zed/cli.js";
let login_task = task::SpawnInTerminal {
command: Some("node".to_string()),
args: vec![path_with_spaces.to_string(), "/login".to_string()],
..Default::default()
};
// Args should be passed as-is, not pre-quoted
assert!(!login_task.args[0].starts_with('"'));
assert!(!login_task.args[0].starts_with('\''));
}
#[gpui::test]
async fn test_notification_for_tool_authorization(cx: &mut TestAppContext) {
init_test(cx);