mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-28 13:01:20 +00:00
fix: Better remote check for auth methods (#538)
The auth methods don't have interactive modes, which means they don't work on remote machines when you need to paste a code in. Our previous change might not have been enough, so added some heuristics similar to what the SDK does for checking for remote. It's not perfect because I think they are attempting to open the URL and then falling back when it fails, but heopfully this is at least closer.
This commit is contained in:
@@ -339,13 +339,21 @@ export class ClaudeAcpAgent implements Agent {
|
||||
|
||||
const supportsTerminalAuth = request.clientCapabilities?.auth?.terminal === true;
|
||||
const supportsMetaTerminalAuth = request.clientCapabilities?._meta?.["terminal-auth"] === true;
|
||||
const noBrowser = !!process.env.NO_BROWSER;
|
||||
|
||||
// When NO_BROWSER is set (e.g. remote environments), fall back to the single
|
||||
// terminal-only login that doesn't try to open a browser.
|
||||
// Detect remote environments where the OAuth browser redirect to localhost
|
||||
// won't work. This matches the SDK's internal isRemote check. In these cases,
|
||||
// the `auth login` subcommand would fall back to a device-code-like manual
|
||||
// flow, which doesn't work well over ACP, so we offer the TUI login instead.
|
||||
const isRemote = !!(
|
||||
process.env.NO_BROWSER ||
|
||||
process.env.SSH_CONNECTION ||
|
||||
process.env.SSH_CLIENT ||
|
||||
process.env.SSH_TTY ||
|
||||
process.env.CLAUDE_CODE_REMOTE
|
||||
);
|
||||
const terminalAuthMethods: AuthMethod[] = [];
|
||||
|
||||
if (noBrowser) {
|
||||
if (isRemote) {
|
||||
const remoteLoginMethod: AuthMethod = {
|
||||
description: "Run `claude /login` in the terminal",
|
||||
name: "Log in with Claude",
|
||||
|
||||
@@ -169,9 +169,9 @@ describe("authorization", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("NO_BROWSER falls back to single legacy login method", async () => {
|
||||
it("SSH session falls back to single legacy login method", async () => {
|
||||
const [agent] = await createAgentMock();
|
||||
vi.stubGlobal("process", { ...process, env: { ...process.env, NO_BROWSER: "1" } });
|
||||
vi.stubGlobal("process", { ...process, env: { ...process.env, SSH_TTY: "/dev/pts/0" } });
|
||||
|
||||
const initializeResponse = await agent.initialize({
|
||||
protocolVersion: 1,
|
||||
@@ -189,12 +189,32 @@ describe("authorization", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("NO_BROWSER respects hide-claude-auth", async () => {
|
||||
it("CLAUDE_CODE_REMOTE falls back to single legacy login method", async () => {
|
||||
const [agent] = await createAgentMock();
|
||||
vi.stubGlobal("process", { ...process, env: { ...process.env, CLAUDE_CODE_REMOTE: "1" } });
|
||||
|
||||
const initializeResponse = await agent.initialize({
|
||||
protocolVersion: 1,
|
||||
clientCapabilities: { auth: { terminal: true } },
|
||||
});
|
||||
|
||||
expect(initializeResponse.authMethods).toContainEqual(
|
||||
expect.objectContaining({ id: "claude-login" }),
|
||||
);
|
||||
expect(initializeResponse.authMethods).not.toContainEqual(
|
||||
expect.objectContaining({ id: "claude-ai-login" }),
|
||||
);
|
||||
expect(initializeResponse.authMethods).not.toContainEqual(
|
||||
expect.objectContaining({ id: "console-login" }),
|
||||
);
|
||||
});
|
||||
|
||||
it("remote environment respects hide-claude-auth", async () => {
|
||||
const [agent] = await createAgentMock();
|
||||
vi.stubGlobal("process", {
|
||||
...process,
|
||||
argv: ["--hide-claude-auth"],
|
||||
env: { ...process.env, NO_BROWSER: "1" },
|
||||
env: { ...process.env, SSH_CONNECTION: "192.168.1.1 12345 192.168.1.2 22" },
|
||||
});
|
||||
|
||||
const initializeResponse = await agent.initialize({
|
||||
|
||||
Reference in New Issue
Block a user