feat: add Gemini ADC and access token auth (#312)

* feat: add Gemini ADC and access token auth

* feat: add Gemini token and ADC provider setup

* feat: add Gemini token and ADC provider setup

* fix: honor Gemini auth mode on restart
This commit is contained in:
Vasanth T
2026-04-04 15:07:17 +05:30
committed by GitHub
parent 280c9732f5
commit ea335aeddc
15 changed files with 1128 additions and 130 deletions

View File

@@ -1,14 +1,12 @@
import { feature } from 'bun:bundle';
import {
isLocalProviderUrl,
resolveCodexApiCredentials,
resolveProviderRequest,
} from '../services/api/providerConfig.js'
import {
applyProfileEnvToProcessEnv,
buildStartupEnvFromProfile,
redactSecretValueForDisplay,
} from '../utils/providerProfile.js'
import {
getProviderValidationError,
validateProviderEnvOrExit,
} from '../utils/providerValidation.js'
// OpenClaude: disable experimental API betas by default.
// Tool search (defer_loading), global cache scope, and context management
@@ -42,82 +40,6 @@ if (feature('ABLATION_BASELINE') && process.env.CLAUDE_CODE_ABLATION_BASELINE) {
}
}
function isEnvTruthy(value: string | undefined): boolean {
if (!value) return false
const normalized = value.trim().toLowerCase()
return normalized !== '' && normalized !== '0' && normalized !== 'false' && normalized !== 'no'
}
function getProviderValidationError(
env: NodeJS.ProcessEnv = process.env,
): string | null {
const useOpenAI = isEnvTruthy(env.CLAUDE_CODE_USE_OPENAI)
const useGithub = isEnvTruthy(env.CLAUDE_CODE_USE_GITHUB)
if (isEnvTruthy(env.CLAUDE_CODE_USE_GEMINI)) {
if (!(env.GEMINI_API_KEY ?? env.GOOGLE_API_KEY)) {
return 'GEMINI_API_KEY is required when CLAUDE_CODE_USE_GEMINI=1.'
}
return null
}
if (useGithub && !useOpenAI) {
const token = (env.GITHUB_TOKEN?.trim() || env.GH_TOKEN?.trim()) ?? ''
if (!token) {
return 'GITHUB_TOKEN or GH_TOKEN is required when CLAUDE_CODE_USE_GITHUB=1.'
}
return null
}
if (!useOpenAI) {
return null
}
const request = resolveProviderRequest({
model: env.OPENAI_MODEL,
baseUrl: env.OPENAI_BASE_URL,
})
if (env.OPENAI_API_KEY === 'SUA_CHAVE') {
return 'Invalid OPENAI_API_KEY: placeholder value SUA_CHAVE detected. Set a real key or unset for local providers.'
}
if (request.transport === 'codex_responses') {
const credentials = resolveCodexApiCredentials(env)
if (!credentials.apiKey) {
const authHint = credentials.authPath
? ` or put auth.json at ${credentials.authPath}`
: ''
const safeModel =
redactSecretValueForDisplay(request.requestedModel, env) ??
'the requested model'
return `Codex auth is required for ${safeModel}. Set CODEX_API_KEY${authHint}.`
}
if (!credentials.accountId) {
return 'Codex auth is missing chatgpt_account_id. Re-login with Codex or set CHATGPT_ACCOUNT_ID/CODEX_ACCOUNT_ID.'
}
return null
}
if (!env.OPENAI_API_KEY && !isLocalProviderUrl(request.baseUrl)) {
const hasGithubToken = !!(env.GITHUB_TOKEN?.trim() || env.GH_TOKEN?.trim())
if (useGithub && hasGithubToken) {
return null
}
return 'OPENAI_API_KEY is required when CLAUDE_CODE_USE_OPENAI=1 and OPENAI_BASE_URL is not local.'
}
return null
}
function validateProviderEnvOrExit(): void {
const error = getProviderValidationError()
if (error) {
console.error(error)
process.exit(1)
}
}
/**
* Bootstrap entrypoint - checks for special flags before loading the full CLI.
* All imports are dynamic to minimize module evaluation for fast paths.
@@ -151,6 +73,8 @@ async function main(): Promise<void> {
enableConfigs()
const { applySafeConfigEnvironmentVariables } = await import('../utils/managedEnv.js')
applySafeConfigEnvironmentVariables()
const { hydrateGeminiAccessTokenFromSecureStorage } = await import('../utils/geminiCredentials.js')
hydrateGeminiAccessTokenFromSecureStorage()
const { hydrateGithubModelsTokenFromSecureStorage } = await import('../utils/githubModelsCredentials.js')
hydrateGithubModelsTokenFromSecureStorage()
}
@@ -159,7 +83,7 @@ async function main(): Promise<void> {
processEnv: process.env,
})
if (startupEnv !== process.env) {
const startupProfileError = getProviderValidationError(startupEnv)
const startupProfileError = await getProviderValidationError(startupEnv)
if (startupProfileError) {
console.error(
`Warning: ignoring saved provider profile. ${startupProfileError}`,
@@ -169,7 +93,7 @@ async function main(): Promise<void> {
}
}
validateProviderEnvOrExit()
await validateProviderEnvOrExit()
// Print the gradient startup screen before the Ink UI loads
const { printStartupScreen } = await import('../components/StartupScreen.js')