import { CLAUDE_CLI_PROFILE_ID, CODEX_CLI_PROFILE_ID, ensureAuthProfileStore, upsertAuthProfile, } from "../../../agents/auth-profiles.js"; import { normalizeProviderId } from "../../../agents/model-selection.js"; import { parseDurationMs } from "../../../cli/parse-duration.js"; import type { ClawdbotConfig } from "../../../config/config.js"; import { upsertSharedEnvVar } from "../../../infra/env-file.js"; import type { RuntimeEnv } from "../../../runtime.js"; import { buildTokenProfileId, validateAnthropicSetupToken } from "../../auth-token.js"; import { applyGoogleGeminiModelDefault } from "../../google-gemini-model-default.js"; import { applyAuthProfileConfig, applyMinimaxApiConfig, applyMinimaxConfig, applyMoonshotConfig, applyOpencodeZenConfig, applyOpenrouterConfig, applySyntheticConfig, applyZaiConfig, setAnthropicApiKey, setGeminiApiKey, setMinimaxApiKey, setMoonshotApiKey, setOpencodeZenApiKey, setOpenrouterApiKey, setSyntheticApiKey, setZaiApiKey, } from "../../onboard-auth.js"; import type { AuthChoice, OnboardOptions } from "../../onboard-types.js"; import { applyOpenAICodexModelDefault } from "../../openai-codex-model-default.js"; import { resolveNonInteractiveApiKey } from "../api-keys.js"; export async function applyNonInteractiveAuthChoice(params: { nextConfig: ClawdbotConfig; authChoice: AuthChoice; opts: OnboardOptions; runtime: RuntimeEnv; baseConfig: ClawdbotConfig; }): Promise { const { authChoice, opts, runtime, baseConfig } = params; let nextConfig = params.nextConfig; if (authChoice === "apiKey") { const resolved = await resolveNonInteractiveApiKey({ provider: "anthropic", cfg: baseConfig, flagValue: opts.anthropicApiKey, flagName: "--anthropic-api-key", envVar: "ANTHROPIC_API_KEY", runtime, }); if (!resolved) return null; if (resolved.source !== "profile") await setAnthropicApiKey(resolved.key); return applyAuthProfileConfig(nextConfig, { profileId: "anthropic:default", provider: "anthropic", mode: "api_key", }); } if (authChoice === "token") { const providerRaw = opts.tokenProvider?.trim(); if (!providerRaw) { runtime.error("Missing --token-provider for --auth-choice token."); runtime.exit(1); return null; } const provider = normalizeProviderId(providerRaw); if (provider !== "anthropic") { runtime.error("Only --token-provider anthropic is supported for --auth-choice token."); runtime.exit(1); return null; } const tokenRaw = opts.token?.trim(); if (!tokenRaw) { runtime.error("Missing --token for --auth-choice token."); runtime.exit(1); return null; } const tokenError = validateAnthropicSetupToken(tokenRaw); if (tokenError) { runtime.error(tokenError); runtime.exit(1); return null; } let expires: number | undefined; const expiresInRaw = opts.tokenExpiresIn?.trim(); if (expiresInRaw) { try { expires = Date.now() + parseDurationMs(expiresInRaw, { defaultUnit: "d" }); } catch (err) { runtime.error(`Invalid --token-expires-in: ${String(err)}`); runtime.exit(1); return null; } } const profileId = opts.tokenProfileId?.trim() || buildTokenProfileId({ provider, name: "" }); upsertAuthProfile({ profileId, credential: { type: "token", provider, token: tokenRaw.trim(), ...(expires ? { expires } : {}), }, }); return applyAuthProfileConfig(nextConfig, { profileId, provider, mode: "token", }); } if (authChoice === "gemini-api-key") { const resolved = await resolveNonInteractiveApiKey({ provider: "google", cfg: baseConfig, flagValue: opts.geminiApiKey, flagName: "--gemini-api-key", envVar: "GEMINI_API_KEY", runtime, }); if (!resolved) return null; if (resolved.source !== "profile") await setGeminiApiKey(resolved.key); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "google:default", provider: "google", mode: "api_key", }); return applyGoogleGeminiModelDefault(nextConfig).next; } if (authChoice === "zai-api-key") { const resolved = await resolveNonInteractiveApiKey({ provider: "zai", cfg: baseConfig, flagValue: opts.zaiApiKey, flagName: "--zai-api-key", envVar: "ZAI_API_KEY", runtime, }); if (!resolved) return null; if (resolved.source !== "profile") await setZaiApiKey(resolved.key); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "zai:default", provider: "zai", mode: "api_key", }); return applyZaiConfig(nextConfig); } if (authChoice === "openai-api-key") { const resolved = await resolveNonInteractiveApiKey({ provider: "openai", cfg: baseConfig, flagValue: opts.openaiApiKey, flagName: "--openai-api-key", envVar: "OPENAI_API_KEY", runtime, allowProfile: false, }); if (!resolved) return null; const key = resolved.key; const result = upsertSharedEnvVar({ key: "OPENAI_API_KEY", value: key }); process.env.OPENAI_API_KEY = key; runtime.log(`Saved OPENAI_API_KEY to ${result.path}`); return nextConfig; } if (authChoice === "openrouter-api-key") { const resolved = await resolveNonInteractiveApiKey({ provider: "openrouter", cfg: baseConfig, flagValue: opts.openrouterApiKey, flagName: "--openrouter-api-key", envVar: "OPENROUTER_API_KEY", runtime, }); if (!resolved) return null; if (resolved.source !== "profile") await setOpenrouterApiKey(resolved.key); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "openrouter:default", provider: "openrouter", mode: "api_key", }); return applyOpenrouterConfig(nextConfig); } if (authChoice === "moonshot-api-key") { const resolved = await resolveNonInteractiveApiKey({ provider: "moonshot", cfg: baseConfig, flagValue: opts.moonshotApiKey, flagName: "--moonshot-api-key", envVar: "MOONSHOT_API_KEY", runtime, }); if (!resolved) return null; if (resolved.source !== "profile") await setMoonshotApiKey(resolved.key); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "moonshot:default", provider: "moonshot", mode: "api_key", }); return applyMoonshotConfig(nextConfig); } if (authChoice === "synthetic-api-key") { const resolved = await resolveNonInteractiveApiKey({ provider: "synthetic", cfg: baseConfig, flagValue: opts.syntheticApiKey, flagName: "--synthetic-api-key", envVar: "SYNTHETIC_API_KEY", runtime, }); if (!resolved) return null; if (resolved.source !== "profile") await setSyntheticApiKey(resolved.key); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "synthetic:default", provider: "synthetic", mode: "api_key", }); return applySyntheticConfig(nextConfig); } if ( authChoice === "minimax-cloud" || authChoice === "minimax-api" || authChoice === "minimax-api-lightning" ) { const resolved = await resolveNonInteractiveApiKey({ provider: "minimax", cfg: baseConfig, flagValue: opts.minimaxApiKey, flagName: "--minimax-api-key", envVar: "MINIMAX_API_KEY", runtime, }); if (!resolved) return null; if (resolved.source !== "profile") await setMinimaxApiKey(resolved.key); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "minimax:default", provider: "minimax", mode: "api_key", }); const modelId = authChoice === "minimax-api-lightning" ? "MiniMax-M2.1-lightning" : "MiniMax-M2.1"; return applyMinimaxApiConfig(nextConfig, modelId); } if (authChoice === "claude-cli") { const store = ensureAuthProfileStore(undefined, { allowKeychainPrompt: false, }); if (!store.profiles[CLAUDE_CLI_PROFILE_ID]) { runtime.error( process.platform === "darwin" ? 'No Claude Code CLI credentials found. Run interactive onboarding to approve Keychain access for "Claude Code-credentials".' : "No Claude Code CLI credentials found at ~/.claude/.credentials.json", ); runtime.exit(1); return null; } return applyAuthProfileConfig(nextConfig, { profileId: CLAUDE_CLI_PROFILE_ID, provider: "anthropic", mode: "token", }); } if (authChoice === "codex-cli") { const store = ensureAuthProfileStore(); if (!store.profiles[CODEX_CLI_PROFILE_ID]) { runtime.error("No Codex CLI credentials found at ~/.codex/auth.json"); runtime.exit(1); return null; } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: CODEX_CLI_PROFILE_ID, provider: "openai-codex", mode: "oauth", }); return applyOpenAICodexModelDefault(nextConfig).next; } if (authChoice === "minimax") return applyMinimaxConfig(nextConfig); if (authChoice === "opencode-zen") { const resolved = await resolveNonInteractiveApiKey({ provider: "opencode", cfg: baseConfig, flagValue: opts.opencodeZenApiKey, flagName: "--opencode-zen-api-key", envVar: "OPENCODE_API_KEY (or OPENCODE_ZEN_API_KEY)", runtime, }); if (!resolved) return null; if (resolved.source !== "profile") await setOpencodeZenApiKey(resolved.key); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "opencode:default", provider: "opencode", mode: "api_key", }); return applyOpencodeZenConfig(nextConfig); } if ( authChoice === "oauth" || authChoice === "chutes" || authChoice === "openai-codex" || authChoice === "antigravity" ) { const label = authChoice === "antigravity" ? "Antigravity" : "OAuth"; runtime.error(`${label} requires interactive mode.`); runtime.exit(1); return null; } return nextConfig; }