From bdd270cb2ae36e9502f2a1e0577d6270defd6e30 Mon Sep 17 00:00:00 2001 From: Black Circle Sentinel Date: Mon, 5 Jan 2026 15:32:52 -0500 Subject: [PATCH] fix(github): pass OAuth token to Python runner subprocesses (fixes #563) The getRunnerEnv utility was missing the OAuth token from the Claude Profile Manager. It only included API profile env vars (ANTHROPIC_*) for custom endpoints, but not the CLAUDE_CODE_OAUTH_TOKEN needed for default Claude authentication. Root cause: The OAuth token is stored encrypted in Electron's profile storage (macOS Keychain via safeStorage), not as a system env var. The getProfileEnv() function retrieves and decrypts it. This fixes the 401 authentication errors in PR review, autofix, and triage handlers that all use getRunnerEnv(). --- .../main/ipc-handlers/github/utils/runner-env.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/frontend/src/main/ipc-handlers/github/utils/runner-env.ts b/apps/frontend/src/main/ipc-handlers/github/utils/runner-env.ts index 0b20945b3b..0156a77a9c 100644 --- a/apps/frontend/src/main/ipc-handlers/github/utils/runner-env.ts +++ b/apps/frontend/src/main/ipc-handlers/github/utils/runner-env.ts @@ -1,15 +1,31 @@ import { getOAuthModeClearVars } from '../../../agent/env-utils'; import { getAPIProfileEnv } from '../../../services/profile'; +import { getProfileEnv } from '../../../rate-limit-detector'; +/** + * Get environment variables for Python runner subprocesses. + * + * Environment variable precedence (lowest to highest): + * 1. apiProfileEnv - Custom Anthropic-compatible API profile (ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN) + * 2. oauthModeClearVars - Clears stale ANTHROPIC_* vars when in OAuth mode + * 3. profileEnv - Claude OAuth token from profile manager (CLAUDE_CODE_OAUTH_TOKEN) + * 4. extraEnv - Caller-specific vars (e.g., USE_CLAUDE_MD) + * + * The profileEnv is critical for OAuth authentication (#563) - it retrieves the + * decrypted OAuth token from the profile manager's encrypted storage (macOS Keychain + * via Electron's safeStorage API). + */ export async function getRunnerEnv( extraEnv?: Record ): Promise> { const apiProfileEnv = await getAPIProfileEnv(); const oauthModeClearVars = getOAuthModeClearVars(apiProfileEnv); + const profileEnv = getProfileEnv(); return { ...apiProfileEnv, ...oauthModeClearVars, + ...profileEnv, // OAuth token from profile manager (fixes #563) ...extraEnv, }; }