From f8318cdb83ed79768cc9c0e4aa78d9509fe56820 Mon Sep 17 00:00:00 2001 From: Vadym O Date: Mon, 9 Nov 2026 14:31:27 +0800 Subject: [PATCH] fix(oauth): xAI login waits 20 minutes for the pasted address (AgentRadar 20115) A hosted Grok sign-in pastes the final address back by hand. The flow kept the callback server's 300 s default, so a paste 5-6 minutes after the start failed with no reason. It now waits 20 minutes, the window AgentRadar offers. Co-Authored-By: Claude Code --- src/oauth/xai.ts | 3 +++ tests/oauth/xai-login-window.test.ts | 11 +++++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/oauth/xai-login-window.test.ts diff --git a/src/oauth/xai.ts b/src/oauth/xai.ts index f1669c75769..4f22a921124 100644 --- a/src/oauth/xai.ts +++ b/src/oauth/xai.ts @@ -12,6 +12,8 @@ const XAI_OAUTH_CALLBACK_PORT = 56121; const XAI_OAUTH_CALLBACK_PATH = "/callback"; const XAI_OAUTH_REFRESH_SKEW_MS = 2 * 60 * 1000; const TOKEN_REQUEST_TIMEOUT_MS = 30_000; +// A hosted sign-in pastes the final address back by hand, so wait as long as the paste window AgentRadar offers (20115). +export const XAI_LOGIN_TIMEOUT_MS = 20 * 60_000; const RETRY_AFTER_MAX_DELAY_MS = 60_000; const JITTER_DELAY_CAP_MS = 2_000; const XAI_TRUSTED_AUTH_HOSTS = new Set(["auth.x.ai", "accounts.x.ai"]); @@ -292,6 +294,7 @@ export class XaiOAuthFlow extends OAuthCallbackFlow { callbackHostname: "127.0.0.1", callbackBindHostname: "127.0.0.1", redirectUri: `http://127.0.0.1:${XAI_OAUTH_CALLBACK_PORT}${XAI_OAUTH_CALLBACK_PATH}`, + timeoutMs: XAI_LOGIN_TIMEOUT_MS, } satisfies OAuthCallbackFlowOptions); } diff --git a/tests/oauth/xai-login-window.test.ts b/tests/oauth/xai-login-window.test.ts new file mode 100644 index 00000000000..f0d0cb4597e --- /dev/null +++ b/tests/oauth/xai-login-window.test.ts @@ -0,0 +1,11 @@ +import { describe, expect, test } from "bun:test"; +import { XAI_LOGIN_TIMEOUT_MS, XaiOAuthFlow } from "../../src/oauth/xai"; + +// AgentRadar 20115: a Grok paste 5-6 minutes after the start failed because the flow kept the 300 s default. +describe("xAI login window", () => { + test("waits 20 minutes for the callback or a pasted address", () => { + const flow = new XaiOAuthFlow({ onAuth: () => {} } as never); + expect(XAI_LOGIN_TIMEOUT_MS).toBe(20 * 60_000); + expect(flow.timeoutMs).toBe(XAI_LOGIN_TIMEOUT_MS); + }); +});