From be8cda223b02bd2f781e8a4aeb4726c297e0b942 Mon Sep 17 00:00:00 2001 From: Pete Date: Tue, 10 Nov 2026 10:20:36 +0000 Subject: [PATCH] fix: respond with AuthRequired if the auth account read fails Previously this responded with an InternalError. --- src/CodexAcpClient.ts | 13 +++++++++++-- src/CodexAcpServer.ts | 2 +- .../CodexACPAgent/account-read-unavailable.test.ts | 11 +++++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/CodexAcpClient.ts b/src/CodexAcpClient.ts index b7271800b..121cc7182 100644 --- a/src/CodexAcpClient.ts +++ b/src/CodexAcpClient.ts @@ -141,6 +141,8 @@ export interface AuthRequirement { required: boolean; /** The account read that gave the answer, or `null` when the adapter did not read the account. */ account: GetAccountResponse | null; + /** Why the stored login does not work, from the failed account read. Absent for a missing login. */ + reason?: string; } export interface UrlElicitationRequester { @@ -438,8 +440,15 @@ export class CodexAcpClient { return {required: false, account: null}; } - const response = await this.codexClient.accountRead({refreshToken: false}); - return {required: response.requiresOpenaiAuth && !response.account, account: response}; + try { + const response = await this.codexClient.accountRead({refreshToken: false}); + return {required: response.requiresOpenaiAuth && !response.account, account: response}; + } catch (error) { + if (isAccountReadAuthFailureError(error)) { + return {required: true, account: null, reason: (error as Error).message}; + } + throw error; + } } /** diff --git a/src/CodexAcpServer.ts b/src/CodexAcpServer.ts index e12ce5f6b..06c9aa87c 100644 --- a/src/CodexAcpServer.ts +++ b/src/CodexAcpServer.ts @@ -1105,7 +1105,7 @@ export class CodexAcpServer { logger.log("Authentication completed"); } else { logger.log("Authentication required but no default auth request provided, return to IDE"); - throw RequestError.authRequired(); + throw RequestError.authRequired(undefined, requirement.reason); } return null; } diff --git a/src/__tests__/CodexACPAgent/account-read-unavailable.test.ts b/src/__tests__/CodexACPAgent/account-read-unavailable.test.ts index eb936245b..91af43fd9 100644 --- a/src/__tests__/CodexACPAgent/account-read-unavailable.test.ts +++ b/src/__tests__/CodexACPAgent/account-read-unavailable.test.ts @@ -1,4 +1,5 @@ import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"; +import {RequestError} from "@agentclientprotocol/sdk/unstable"; import {ResponseError} from "vscode-jsonrpc/node"; import { createCodexMockTestFixture, @@ -390,7 +391,10 @@ describe("CodexACPAgent - an unavailable account read", () => { await initialize(fixture); await expect(fixture.getCodexAcpAgent().loadSession({sessionId: SESSION_ID, cwd: "/test/project", mcpServers: []})) - .rejects.toThrow("workspace routing discovery unauthorized (401)"); + .rejects.toMatchObject({ + code: RequestError.authRequired().code, + message: "Authentication required: workspace routing discovery unauthorized (401)", + }); }); it("keeps the sessions and pushes nothing when an auth refresh read is unavailable", async () => { @@ -486,7 +490,10 @@ describe("CodexACPAgent - an unavailable account read", () => { await initialize(fixture); await expect(fixture.getCodexAcpAgent().loadSession({sessionId: SESSION_ID, cwd: "/test/project", mcpServers: []})) - .rejects.toThrow("workspace routing discovery unauthorized (401)"); + .rejects.toMatchObject({ + code: RequestError.authRequired().code, + message: "Authentication required: workspace routing discovery unauthorized (401)", + }); // The read of `initialize` pushes the none status. The load pushes nothing more. expect(authStatusUpdates(fixture)).toEqual([NONE_STATUS]); expect(appServer.accountLogout).not.toHaveBeenCalled();