UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

1,286 lines (1,272 loc) 71.4 kB
import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js"; import { D as resolveDefaultAgentWorkspaceDir, c as resolveAgentWorkspaceDir, i as resolveAgentDir, l as resolveDefaultAgentId, o as resolveAgentModelPrimary } from "./agent-scope-BnZW9Gh2.js"; import { Dt as upsertAuthProfile, Gt as DEFAULT_PROVIDER, J as resolveEnvApiKey, Pt as resolveOpenClawAgentDir, R as SYNTHETIC_DEFAULT_MODEL_REF, W as getCustomProviderApiKey, Wt as DEFAULT_MODEL, at as discoverHuggingfaceModels, bt as generateChutesPkce, dt as resolveAuthProfileOrder, j as VENICE_DEFAULT_MODEL_REF, kt as ensureAuthProfileStore, ot as isHuggingfacePolicyLocked, p as resolveConfiguredModelRef, st as CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, vt as CHUTES_AUTHORIZE_ENDPOINT, wt as listProfilesForProvider, xt as parseOAuthCallbackInput, yt as exchangeChutesCodeForTokens } from "./model-selection-CqaTAlhy.js"; import { r as isLoopbackHost } from "./ws-CV6gEox3.js"; import { n as loadModelCatalog } from "./model-catalog-CIixTnGt.js"; import { f as openUrl } from "./onboard-helpers-DbjfBSMX.js"; import { t as enablePluginInConfig } from "./enable-Ca1P9hMP.js"; import { $ as setHuggingfaceApiKey, A as applyXaiConfig, B as applyVercelAiGatewayConfig, C as applyQianfanProviderConfig, D as applyTogetherProviderConfig, E as applyTogetherConfig, F as applyZaiProviderConfig, G as OPENROUTER_DEFAULT_MODEL_REF, H as applyAgentDefaultModelPrimary, I as applyLitellmConfig, J as XIAOMI_DEFAULT_MODEL_REF, K as TOGETHER_DEFAULT_MODEL_REF, L as applyLitellmProviderConfig, M as applyXiaomiConfig, N as applyXiaomiProviderConfig, O as applyVeniceConfig, P as applyZaiConfig, Q as setGeminiApiKey, R as applyCloudflareAiGatewayConfig, S as applyQianfanConfig, T as applySyntheticProviderConfig, U as HUGGINGFACE_DEFAULT_MODEL_REF, V as applyVercelAiGatewayProviderConfig, W as LITELLM_DEFAULT_MODEL_REF, X as setAnthropicApiKey, Y as ZAI_DEFAULT_MODEL_REF, Z as setCloudflareAiGatewayConfig, _ as applyMoonshotConfigCn, _t as QIANFAN_DEFAULT_MODEL_REF, a as applyMinimaxApiConfig, at as setOpenrouterApiKey, b as applyOpenrouterConfig, c as applyMinimaxApiProviderConfigCn, ct as setTogetherApiKey, d as applyAuthProfileConfig, dt as setXaiApiKey, et as setKimiCodingApiKey, ft as setXiaomiApiKey, g as applyMoonshotConfig, gt as MOONSHOT_DEFAULT_MODEL_REF, h as applyKimiCodeProviderConfig, ht as KIMI_CODING_MODEL_REF, i as applyOpencodeZenProviderConfig, it as setOpencodeZenApiKey, j as applyXaiProviderConfig, k as applyVeniceProviderConfig, l as applyMinimaxConfig, lt as setVeniceApiKey, m as applyKimiCodeConfig, mt as writeOAuthCredentials, n as validateAnthropicSetupToken, nt as setMinimaxApiKey, o as applyMinimaxApiConfigCn, ot as setQianfanApiKey, p as applyHuggingfaceProviderConfig, pt as setZaiApiKey, q as VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, r as applyOpencodeZenConfig, rt as setMoonshotApiKey, s as applyMinimaxApiProviderConfig, st as setSyntheticApiKey, t as buildTokenProfileId, tt as setLitellmApiKey, u as applyMinimaxProviderConfig, ut as setVercelAiGatewayApiKey, v as applyMoonshotProviderConfig, vt as XAI_DEFAULT_MODEL_REF, w as applySyntheticConfig, x as applyOpenrouterProviderConfig, y as applyMoonshotProviderConfigCn, z as applyCloudflareAiGatewayProviderConfig } from "./auth-token-CliHE70g.js"; import { a as createVpsAwareOAuthHandlers, c as githubCopilotLoginCommand, i as resolveProviderMatch, n as mergeConfigPatch, o as isRemoteEnvironment, r as pickAuthMethod, s as resolvePluginProviders, t as applyDefaultModel } from "./provider-auth-helpers-Bnx6HWum.js"; import { a as detectZaiEndpoint, c as ensureModelAllowlistEntry, i as upsertSharedEnvVar, n as applyOpenAIConfig, o as GOOGLE_GEMINI_DEFAULT_MODEL, r as applyOpenAIProviderConfig, s as applyGoogleGeminiModelDefault, t as OPENAI_DEFAULT_MODEL } from "./openai-model-default-8jds2v9m.js"; import { n as OPENAI_CODEX_DEFAULT_MODEL, r as applyOpenAICodexModelDefault, t as promptAndConfigureVllm } from "./vllm-setup-G6R-Hqd8.js"; import { randomBytes } from "node:crypto"; import { loginOpenAICodex } from "@mariozechner/pi-ai"; import { createServer } from "node:http"; //#region src/commands/auth-choice.api-key.ts const DEFAULT_KEY_PREVIEW = { head: 4, tail: 4 }; function normalizeApiKeyInput(raw) { const trimmed = String(raw ?? "").trim(); if (!trimmed) return ""; const assignmentMatch = trimmed.match(/^(?:export\s+)?[A-Za-z_][A-Za-z0-9_]*\s*=\s*(.+)$/); const valuePart = assignmentMatch ? assignmentMatch[1].trim() : trimmed; const unquoted = valuePart.length >= 2 && (valuePart.startsWith("\"") && valuePart.endsWith("\"") || valuePart.startsWith("'") && valuePart.endsWith("'") || valuePart.startsWith("`") && valuePart.endsWith("`")) ? valuePart.slice(1, -1) : valuePart; return (unquoted.endsWith(";") ? unquoted.slice(0, -1) : unquoted).trim(); } const validateApiKeyInput = (value) => normalizeApiKeyInput(value).length > 0 ? void 0 : "Required"; function formatApiKeyPreview(raw, opts = {}) { const trimmed = raw.trim(); if (!trimmed) return "…"; const head = opts.head ?? DEFAULT_KEY_PREVIEW.head; const tail = opts.tail ?? DEFAULT_KEY_PREVIEW.tail; if (trimmed.length <= head + tail) { const shortHead = Math.min(2, trimmed.length); const shortTail = Math.min(2, trimmed.length - shortHead); if (shortTail <= 0) return `${trimmed.slice(0, shortHead)}…`; return `${trimmed.slice(0, shortHead)}…${trimmed.slice(-shortTail)}`; } return `${trimmed.slice(0, head)}…${trimmed.slice(-tail)}`; } //#endregion //#region src/commands/auth-choice.apply.anthropic.ts const DEFAULT_ANTHROPIC_MODEL = "anthropic/claude-sonnet-4-6"; async function applyAuthChoiceAnthropic(params) { if (params.authChoice === "setup-token" || params.authChoice === "oauth" || params.authChoice === "token") { let nextConfig = params.config; await params.prompter.note(["Run `claude setup-token` in your terminal.", "Then paste the generated token below."].join("\n"), "Anthropic setup-token"); const tokenRaw = await params.prompter.text({ message: "Paste Anthropic setup-token", validate: (value) => validateAnthropicSetupToken(String(value ?? "")) }); const token = String(tokenRaw ?? "").trim(); const profileNameRaw = await params.prompter.text({ message: "Token name (blank = default)", placeholder: "default" }); const provider = "anthropic"; const namedProfileId = buildTokenProfileId({ provider, name: String(profileNameRaw ?? "") }); upsertAuthProfile({ profileId: namedProfileId, agentDir: params.agentDir, credential: { type: "token", provider, token } }); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: namedProfileId, provider, mode: "token" }); if (params.setDefaultModel) nextConfig = applyAgentDefaultModelPrimary(nextConfig, DEFAULT_ANTHROPIC_MODEL); return { config: nextConfig }; } if (params.authChoice === "apiKey") { if (params.opts?.tokenProvider && params.opts.tokenProvider !== "anthropic") return null; let nextConfig = params.config; let hasCredential = false; const envKey = process.env.ANTHROPIC_API_KEY?.trim(); if (params.opts?.token) { await setAnthropicApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } if (!hasCredential && envKey) { if (await params.prompter.confirm({ message: `Use existing ANTHROPIC_API_KEY (env, ${formatApiKeyPreview(envKey)})?`, initialValue: true })) { await setAnthropicApiKey(envKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter Anthropic API key", validate: validateApiKeyInput }); await setAnthropicApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "anthropic:default", provider: "anthropic", mode: "api_key" }); if (params.setDefaultModel) nextConfig = applyAgentDefaultModelPrimary(nextConfig, DEFAULT_ANTHROPIC_MODEL); return { config: nextConfig }; } return null; } //#endregion //#region src/commands/auth-choice.apply-helpers.ts function createAuthChoiceAgentModelNoter(params) { return async (model) => { if (!params.agentId) return; await params.prompter.note(`Default model set to ${model} for agent "${params.agentId}".`, "Model configured"); }; } //#endregion //#region src/commands/auth-choice.default-model.ts async function applyDefaultModelChoice(params) { if (params.setDefaultModel) { const next = params.applyDefaultConfig(params.config); if (params.noteDefault) await params.prompter.note(`Default model set to ${params.noteDefault}`, "Model configured"); return { config: next }; } const nextWithModel = ensureModelAllowlistEntry({ cfg: params.applyProviderConfig(params.config), modelRef: params.defaultModel }); await params.noteAgentModel(params.defaultModel); return { config: nextWithModel, agentModelOverride: params.defaultModel }; } //#endregion //#region src/commands/auth-choice.apply.huggingface.ts async function applyAuthChoiceHuggingface(params) { if (params.authChoice !== "huggingface-api-key") return null; let nextConfig = params.config; let agentModelOverride; const noteAgentModel = createAuthChoiceAgentModelNoter(params); let hasCredential = false; let hfKey = ""; if (!hasCredential && params.opts?.token && params.opts.tokenProvider === "huggingface") { hfKey = normalizeApiKeyInput(params.opts.token); await setHuggingfaceApiKey(hfKey, params.agentDir); hasCredential = true; } if (!hasCredential) await params.prompter.note(["Hugging Face Inference Providers offer OpenAI-compatible chat completions.", "Create a token at: https://huggingface.co/settings/tokens (fine-grained, 'Make calls to Inference Providers')."].join("\n"), "Hugging Face"); if (!hasCredential) { const envKey = resolveEnvApiKey("huggingface"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing Hugging Face token (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { hfKey = envKey.apiKey; await setHuggingfaceApiKey(hfKey, params.agentDir); hasCredential = true; } } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter Hugging Face API key (HF token)", validate: validateApiKeyInput }); hfKey = normalizeApiKeyInput(String(key ?? "")); await setHuggingfaceApiKey(hfKey, params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "huggingface:default", provider: "huggingface", mode: "api_key" }); const models = await discoverHuggingfaceModels(hfKey); const modelRefPrefix = "huggingface/"; const options = []; for (const m of models) { const baseRef = `${modelRefPrefix}${m.id}`; const label = m.name ?? m.id; options.push({ value: baseRef, label }); options.push({ value: `${baseRef}:cheapest`, label: `${label} (cheapest)` }); options.push({ value: `${baseRef}:fastest`, label: `${label} (fastest)` }); } const defaultRef = HUGGINGFACE_DEFAULT_MODEL_REF; options.sort((a, b) => { if (a.value === defaultRef) return -1; if (b.value === defaultRef) return 1; return a.label.localeCompare(b.label, void 0, { sensitivity: "base" }); }); const selectedModelRef = options.length === 0 ? defaultRef : options.length === 1 ? options[0].value : await params.prompter.select({ message: "Default Hugging Face model", options, initialValue: options.some((o) => o.value === defaultRef) ? defaultRef : options[0].value }); if (isHuggingfacePolicyLocked(selectedModelRef)) await params.prompter.note("Provider locked — router will choose backend by cost or speed.", "Hugging Face"); const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: selectedModelRef, applyDefaultConfig: (config) => { const withProvider = applyHuggingfaceProviderConfig(config); const existingModel = withProvider.agents?.defaults?.model; return ensureModelAllowlistEntry({ cfg: { ...withProvider, agents: { ...withProvider.agents, defaults: { ...withProvider.agents?.defaults, model: { ...existingModel && typeof existingModel === "object" && "fallbacks" in existingModel ? { fallbacks: existingModel.fallbacks } : {}, primary: selectedModelRef } } } }, modelRef: selectedModelRef }); }, applyProviderConfig: applyHuggingfaceProviderConfig, noteDefault: selectedModelRef, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; return { config: nextConfig, agentModelOverride }; } //#endregion //#region src/commands/auth-choice.apply.openrouter.ts async function applyAuthChoiceOpenRouter(params) { let nextConfig = params.config; let agentModelOverride; const noteAgentModel = createAuthChoiceAgentModelNoter(params); const store = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }); const existingProfileId = resolveAuthProfileOrder({ cfg: nextConfig, store, provider: "openrouter" }).find((profileId) => Boolean(store.profiles[profileId])); const existingCred = existingProfileId ? store.profiles[existingProfileId] : void 0; let profileId = "openrouter:default"; let mode = "api_key"; let hasCredential = false; if (existingProfileId && existingCred?.type) { profileId = existingProfileId; mode = existingCred.type === "oauth" ? "oauth" : existingCred.type === "token" ? "token" : "api_key"; hasCredential = true; } if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "openrouter") { await setOpenrouterApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } if (!hasCredential) { const envKey = resolveEnvApiKey("openrouter"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing OPENROUTER_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setOpenrouterApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter OpenRouter API key", validate: validateApiKeyInput }); await setOpenrouterApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); hasCredential = true; } if (hasCredential) nextConfig = applyAuthProfileConfig(nextConfig, { profileId, provider: "openrouter", mode }); const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: OPENROUTER_DEFAULT_MODEL_REF, applyDefaultConfig: applyOpenrouterConfig, applyProviderConfig: applyOpenrouterProviderConfig, noteDefault: OPENROUTER_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; return { config: nextConfig, agentModelOverride }; } //#endregion //#region src/commands/opencode-zen-model-default.ts const OPENCODE_ZEN_DEFAULT_MODEL = "opencode/claude-opus-4-6"; //#endregion //#region src/commands/auth-choice.apply.api-providers.ts async function applyAuthChoiceApiProviders(params) { let nextConfig = params.config; let agentModelOverride; const noteAgentModel = createAuthChoiceAgentModelNoter(params); let authChoice = params.authChoice; if (authChoice === "apiKey" && params.opts?.tokenProvider && params.opts.tokenProvider !== "anthropic" && params.opts.tokenProvider !== "openai") { if (params.opts.tokenProvider === "openrouter") authChoice = "openrouter-api-key"; else if (params.opts.tokenProvider === "litellm") authChoice = "litellm-api-key"; else if (params.opts.tokenProvider === "vercel-ai-gateway") authChoice = "ai-gateway-api-key"; else if (params.opts.tokenProvider === "cloudflare-ai-gateway") authChoice = "cloudflare-ai-gateway-api-key"; else if (params.opts.tokenProvider === "moonshot") authChoice = "moonshot-api-key"; else if (params.opts.tokenProvider === "kimi-code" || params.opts.tokenProvider === "kimi-coding") authChoice = "kimi-code-api-key"; else if (params.opts.tokenProvider === "google") authChoice = "gemini-api-key"; else if (params.opts.tokenProvider === "zai") authChoice = "zai-api-key"; else if (params.opts.tokenProvider === "xiaomi") authChoice = "xiaomi-api-key"; else if (params.opts.tokenProvider === "synthetic") authChoice = "synthetic-api-key"; else if (params.opts.tokenProvider === "venice") authChoice = "venice-api-key"; else if (params.opts.tokenProvider === "together") authChoice = "together-api-key"; else if (params.opts.tokenProvider === "huggingface") authChoice = "huggingface-api-key"; else if (params.opts.tokenProvider === "opencode") authChoice = "opencode-zen"; else if (params.opts.tokenProvider === "qianfan") authChoice = "qianfan-api-key"; } async function ensureMoonshotApiKeyCredential(promptMessage) { let hasCredential = false; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "moonshot") { await setMoonshotApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } const envKey = resolveEnvApiKey("moonshot"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing MOONSHOT_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setMoonshotApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: promptMessage, validate: validateApiKeyInput }); await setMoonshotApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } } if (authChoice === "openrouter-api-key") return applyAuthChoiceOpenRouter(params); if (authChoice === "litellm-api-key") { const store = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }); const existingProfileId = resolveAuthProfileOrder({ cfg: nextConfig, store, provider: "litellm" }).find((profileId) => Boolean(store.profiles[profileId])); const existingCred = existingProfileId ? store.profiles[existingProfileId] : void 0; let profileId = "litellm:default"; let hasCredential = false; if (existingProfileId && existingCred?.type === "api_key") { profileId = existingProfileId; hasCredential = true; } if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "litellm") { await setLitellmApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } if (!hasCredential) { await params.prompter.note("LiteLLM provides a unified API to 100+ LLM providers.\nGet your API key from your LiteLLM proxy or https://litellm.ai\nDefault proxy runs on http://localhost:4000", "LiteLLM"); const envKey = resolveEnvApiKey("litellm"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing LITELLM_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setLitellmApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter LiteLLM API key", validate: validateApiKeyInput }); await setLitellmApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); hasCredential = true; } } if (hasCredential) nextConfig = applyAuthProfileConfig(nextConfig, { profileId, provider: "litellm", mode: "api_key" }); const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: LITELLM_DEFAULT_MODEL_REF, applyDefaultConfig: applyLitellmConfig, applyProviderConfig: applyLitellmProviderConfig, noteDefault: LITELLM_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; return { config: nextConfig, agentModelOverride }; } if (authChoice === "ai-gateway-api-key") { let hasCredential = false; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "vercel-ai-gateway") { await setVercelAiGatewayApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } const envKey = resolveEnvApiKey("vercel-ai-gateway"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing AI_GATEWAY_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setVercelAiGatewayApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter Vercel AI Gateway API key", validate: validateApiKeyInput }); await setVercelAiGatewayApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "vercel-ai-gateway:default", provider: "vercel-ai-gateway", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, applyDefaultConfig: applyVercelAiGatewayConfig, applyProviderConfig: applyVercelAiGatewayProviderConfig, noteDefault: VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "cloudflare-ai-gateway-api-key") { let hasCredential = false; let accountId = params.opts?.cloudflareAiGatewayAccountId?.trim() ?? ""; let gatewayId = params.opts?.cloudflareAiGatewayGatewayId?.trim() ?? ""; const ensureAccountGateway = async () => { if (!accountId) { const value = await params.prompter.text({ message: "Enter Cloudflare Account ID", validate: (val) => String(val ?? "").trim() ? void 0 : "Account ID is required" }); accountId = String(value ?? "").trim(); } if (!gatewayId) { const value = await params.prompter.text({ message: "Enter Cloudflare AI Gateway ID", validate: (val) => String(val ?? "").trim() ? void 0 : "Gateway ID is required" }); gatewayId = String(value ?? "").trim(); } }; const optsApiKey = normalizeApiKeyInput(params.opts?.cloudflareAiGatewayApiKey ?? ""); if (!hasCredential && accountId && gatewayId && optsApiKey) { await setCloudflareAiGatewayConfig(accountId, gatewayId, optsApiKey, params.agentDir); hasCredential = true; } const envKey = resolveEnvApiKey("cloudflare-ai-gateway"); if (!hasCredential && envKey) { if (await params.prompter.confirm({ message: `Use existing CLOUDFLARE_AI_GATEWAY_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await ensureAccountGateway(); await setCloudflareAiGatewayConfig(accountId, gatewayId, normalizeApiKeyInput(envKey.apiKey), params.agentDir); hasCredential = true; } } if (!hasCredential && optsApiKey) { await ensureAccountGateway(); await setCloudflareAiGatewayConfig(accountId, gatewayId, optsApiKey, params.agentDir); hasCredential = true; } if (!hasCredential) { await ensureAccountGateway(); const key = await params.prompter.text({ message: "Enter Cloudflare AI Gateway API key", validate: validateApiKeyInput }); await setCloudflareAiGatewayConfig(accountId, gatewayId, normalizeApiKeyInput(String(key ?? "")), params.agentDir); hasCredential = true; } if (hasCredential) nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "cloudflare-ai-gateway:default", provider: "cloudflare-ai-gateway", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, applyDefaultConfig: (cfg) => applyCloudflareAiGatewayConfig(cfg, { accountId: accountId || params.opts?.cloudflareAiGatewayAccountId, gatewayId: gatewayId || params.opts?.cloudflareAiGatewayGatewayId }), applyProviderConfig: (cfg) => applyCloudflareAiGatewayProviderConfig(cfg, { accountId: accountId || params.opts?.cloudflareAiGatewayAccountId, gatewayId: gatewayId || params.opts?.cloudflareAiGatewayGatewayId }), noteDefault: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "moonshot-api-key") { await ensureMoonshotApiKeyCredential("Enter Moonshot API key"); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "moonshot:default", provider: "moonshot", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: MOONSHOT_DEFAULT_MODEL_REF, applyDefaultConfig: applyMoonshotConfig, applyProviderConfig: applyMoonshotProviderConfig, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "moonshot-api-key-cn") { await ensureMoonshotApiKeyCredential("Enter Moonshot API key (.cn)"); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "moonshot:default", provider: "moonshot", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: MOONSHOT_DEFAULT_MODEL_REF, applyDefaultConfig: applyMoonshotConfigCn, applyProviderConfig: applyMoonshotProviderConfigCn, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "kimi-code-api-key") { let hasCredential = false; const tokenProvider = params.opts?.tokenProvider?.trim().toLowerCase(); if (!hasCredential && params.opts?.token && (tokenProvider === "kimi-code" || tokenProvider === "kimi-coding")) { await setKimiCodingApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } if (!hasCredential) await params.prompter.note(["Kimi Coding uses a dedicated endpoint and API key.", "Get your API key at: https://www.kimi.com/code/en"].join("\n"), "Kimi Coding"); const envKey = resolveEnvApiKey("kimi-coding"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing KIMI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setKimiCodingApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter Kimi Coding API key", validate: validateApiKeyInput }); await setKimiCodingApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "kimi-coding:default", provider: "kimi-coding", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: KIMI_CODING_MODEL_REF, applyDefaultConfig: applyKimiCodeConfig, applyProviderConfig: applyKimiCodeProviderConfig, noteDefault: KIMI_CODING_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "gemini-api-key") { let hasCredential = false; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "google") { await setGeminiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } const envKey = resolveEnvApiKey("google"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing GEMINI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setGeminiApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter Gemini API key", validate: validateApiKeyInput }); await setGeminiApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "google:default", provider: "google", mode: "api_key" }); if (params.setDefaultModel) { const applied = applyGoogleGeminiModelDefault(nextConfig); nextConfig = applied.next; if (applied.changed) await params.prompter.note(`Default model set to ${GOOGLE_GEMINI_DEFAULT_MODEL}`, "Model configured"); } else { agentModelOverride = GOOGLE_GEMINI_DEFAULT_MODEL; await noteAgentModel(GOOGLE_GEMINI_DEFAULT_MODEL); } return { config: nextConfig, agentModelOverride }; } if (authChoice === "zai-api-key" || authChoice === "zai-coding-global" || authChoice === "zai-coding-cn" || authChoice === "zai-global" || authChoice === "zai-cn") { let endpoint; if (authChoice === "zai-coding-global") endpoint = "coding-global"; else if (authChoice === "zai-coding-cn") endpoint = "coding-cn"; else if (authChoice === "zai-global") endpoint = "global"; else if (authChoice === "zai-cn") endpoint = "cn"; let hasCredential = false; let apiKey = ""; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "zai") { apiKey = normalizeApiKeyInput(params.opts.token); await setZaiApiKey(apiKey, params.agentDir); hasCredential = true; } const envKey = resolveEnvApiKey("zai"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing ZAI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { apiKey = envKey.apiKey; await setZaiApiKey(apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter Z.AI API key", validate: validateApiKeyInput }); apiKey = normalizeApiKeyInput(String(key ?? "")); await setZaiApiKey(apiKey, params.agentDir); } let modelIdOverride; if (!endpoint) { const detected = await detectZaiEndpoint({ apiKey }); if (detected) { endpoint = detected.endpoint; modelIdOverride = detected.modelId; await params.prompter.note(detected.note, "Z.AI endpoint"); } else endpoint = await params.prompter.select({ message: "Select Z.AI endpoint", options: [ { value: "coding-global", label: "Coding-Plan-Global", hint: "GLM Coding Plan Global (api.z.ai)" }, { value: "coding-cn", label: "Coding-Plan-CN", hint: "GLM Coding Plan CN (open.bigmodel.cn)" }, { value: "global", label: "Global", hint: "Z.AI Global (api.z.ai)" }, { value: "cn", label: "CN", hint: "Z.AI CN (open.bigmodel.cn)" } ], initialValue: "global" }); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "zai:default", provider: "zai", mode: "api_key" }); const defaultModel = modelIdOverride ? `zai/${modelIdOverride}` : ZAI_DEFAULT_MODEL_REF; const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel, applyDefaultConfig: (config) => applyZaiConfig(config, { endpoint, ...modelIdOverride ? { modelId: modelIdOverride } : {} }), applyProviderConfig: (config) => applyZaiProviderConfig(config, { endpoint, ...modelIdOverride ? { modelId: modelIdOverride } : {} }), noteDefault: defaultModel, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; return { config: nextConfig, agentModelOverride }; } if (authChoice === "xiaomi-api-key") { let hasCredential = false; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "xiaomi") { await setXiaomiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } const envKey = resolveEnvApiKey("xiaomi"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing XIAOMI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setXiaomiApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter Xiaomi API key", validate: validateApiKeyInput }); await setXiaomiApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "xiaomi:default", provider: "xiaomi", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: XIAOMI_DEFAULT_MODEL_REF, applyDefaultConfig: applyXiaomiConfig, applyProviderConfig: applyXiaomiProviderConfig, noteDefault: XIAOMI_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "synthetic-api-key") { if (params.opts?.token && params.opts?.tokenProvider === "synthetic") await setSyntheticApiKey(String(params.opts.token ?? "").trim(), params.agentDir); else { const key = await params.prompter.text({ message: "Enter Synthetic API key", validate: (value) => value?.trim() ? void 0 : "Required" }); await setSyntheticApiKey(String(key ?? "").trim(), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "synthetic:default", provider: "synthetic", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: SYNTHETIC_DEFAULT_MODEL_REF, applyDefaultConfig: applySyntheticConfig, applyProviderConfig: applySyntheticProviderConfig, noteDefault: SYNTHETIC_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "venice-api-key") { let hasCredential = false; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "venice") { await setVeniceApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } if (!hasCredential) await params.prompter.note([ "Venice AI provides privacy-focused inference with uncensored models.", "Get your API key at: https://venice.ai/settings/api", "Supports 'private' (fully private) and 'anonymized' (proxy) modes." ].join("\n"), "Venice AI"); const envKey = resolveEnvApiKey("venice"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing VENICE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setVeniceApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter Venice AI API key", validate: validateApiKeyInput }); await setVeniceApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "venice:default", provider: "venice", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: VENICE_DEFAULT_MODEL_REF, applyDefaultConfig: applyVeniceConfig, applyProviderConfig: applyVeniceProviderConfig, noteDefault: VENICE_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "opencode-zen") { let hasCredential = false; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "opencode") { await setOpencodeZenApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } if (!hasCredential) await params.prompter.note([ "OpenCode Zen provides access to Claude, GPT, Gemini, and more models.", "Get your API key at: https://opencode.ai/auth", "OpenCode Zen bills per request. Check your OpenCode dashboard for details." ].join("\n"), "OpenCode Zen"); const envKey = resolveEnvApiKey("opencode"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing OPENCODE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setOpencodeZenApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter OpenCode Zen API key", validate: validateApiKeyInput }); await setOpencodeZenApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "opencode:default", provider: "opencode", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: OPENCODE_ZEN_DEFAULT_MODEL, applyDefaultConfig: applyOpencodeZenConfig, applyProviderConfig: applyOpencodeZenProviderConfig, noteDefault: OPENCODE_ZEN_DEFAULT_MODEL, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "together-api-key") { let hasCredential = false; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "together") { await setTogetherApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } if (!hasCredential) await params.prompter.note(["Together AI provides access to leading open-source models including Llama, DeepSeek, Qwen, and more.", "Get your API key at: https://api.together.xyz/settings/api-keys"].join("\n"), "Together AI"); const envKey = resolveEnvApiKey("together"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing TOGETHER_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setTogetherApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter Together AI API key", validate: validateApiKeyInput }); await setTogetherApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "together:default", provider: "together", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: TOGETHER_DEFAULT_MODEL_REF, applyDefaultConfig: applyTogetherConfig, applyProviderConfig: applyTogetherProviderConfig, noteDefault: TOGETHER_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } if (authChoice === "huggingface-api-key") return applyAuthChoiceHuggingface({ ...params, authChoice }); if (authChoice === "qianfan-api-key") { let hasCredential = false; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "qianfan") { setQianfanApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); hasCredential = true; } if (!hasCredential) await params.prompter.note(["Get your API key at: https://console.bce.baidu.com/qianfan/ais/console/apiKey", "API key format: bce-v3/ALTAK-..."].join("\n"), "QIANFAN"); const envKey = resolveEnvApiKey("qianfan"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing QIANFAN_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { setQianfanApiKey(envKey.apiKey, params.agentDir); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: "Enter QIANFAN API key", validate: validateApiKeyInput }); setQianfanApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir); } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "qianfan:default", provider: "qianfan", mode: "api_key" }); { const applied = await applyDefaultModelChoice({ config: nextConfig, setDefaultModel: params.setDefaultModel, defaultModel: QIANFAN_DEFAULT_MODEL_REF, applyDefaultConfig: applyQianfanConfig, applyProviderConfig: applyQianfanProviderConfig, noteDefault: QIANFAN_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter }); nextConfig = applied.config; agentModelOverride = applied.agentModelOverride ?? agentModelOverride; } return { config: nextConfig, agentModelOverride }; } return null; } //#endregion //#region src/commands/auth-choice.apply.plugin-provider.ts async function applyAuthChoicePluginProvider(params, options) { if (params.authChoice !== options.authChoice) return null; const enableResult = enablePluginInConfig(params.config, options.pluginId); let nextConfig = enableResult.config; if (!enableResult.enabled) { await params.prompter.note(`${options.label} plugin is disabled (${enableResult.reason ?? "blocked"}).`, options.label); return { config: nextConfig }; } const agentId = params.agentId ?? resolveDefaultAgentId(nextConfig); const defaultAgentId = resolveDefaultAgentId(nextConfig); const agentDir = params.agentDir ?? (agentId === defaultAgentId ? resolveOpenClawAgentDir() : resolveAgentDir(nextConfig, agentId)); const workspaceDir = resolveAgentWorkspaceDir(nextConfig, agentId) ?? resolveDefaultAgentWorkspaceDir(); const provider = resolveProviderMatch(resolvePluginProviders({ config: nextConfig, workspaceDir }), options.providerId); if (!provider) { await params.prompter.note(`${options.label} auth plugin is not available. Enable it and re-run the wizard.`, options.label); return { config: nextConfig }; } const method = pickAuthMethod(provider, options.methodId) ?? provider.auth[0]; if (!method) { await params.prompter.note(`${options.label} auth method missing.`, options.label); return { config: nextConfig }; } const isRemote = isRemoteEnvironment(); const result = await method.run({ config: nextConfig, agentDir, workspaceDir, prompter: params.prompter, runtime: params.runtime, isRemote, openUrl: async (url) => { await openUrl(url); }, oauth: { createVpsAwareHandlers: (opts) => createVpsAwareOAuthHandlers(opts) } }); if (result.configPatch) nextConfig = mergeConfigPatch(nextConfig, result.configPatch); for (const profile of result.profiles) { upsertAuthProfile({ profileId: profile.profileId, credential: profile.credential, agentDir }); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: profile.profileId, provider: profile.credential.provider, mode: profile.credential.type === "token" ? "token" : profile.credential.type, ..."email" in profile.credential && profile.credential.email ? { email: profile.credential.email } : {} }); } let agentModelOverride; if (result.defaultModel) { if (params.setDefaultModel) { nextConfig = applyDefaultModel(nextConfig, result.defaultModel); await params.prompter.note(`Default model set to ${result.defaultModel}`, "Model configured"); } else if (params.agentId) { agentModelOverride = result.defaultModel; await params.prompter.note(`Default model set to ${result.defaultModel} for agent "${params.agentId}".`, "Model configured"); } } if (result.notes && result.notes.length > 0) await params.prompter.note(result.notes.join("\n"), "Provider notes"); return { config: nextConfig, agentModelOverride }; } //#endregion //#region src/commands/auth-choice.apply.copilot-proxy.ts async function applyAuthChoiceCopilotProxy(params) { return await applyAuthChoicePluginProvider(params, { authChoice: "copilot-proxy", pluginId: "copilot-proxy", providerId: "copilot-proxy", methodId: "local", label: "Copilot Proxy" }); } //#endregion //#region src/commands/auth-choice.apply.github-copilot.ts async function applyAuthChoiceGitHubCopilot(params) { if (params.authChoice !== "github-copilot") return null; let nextConfig = params.config; await params.prompter.note(["This will open a GitHub device login to authorize Copilot.", "Requires an active GitHub Copilot subscription."].join("\n"), "GitHub Copilot"); if (!process.stdin.isTTY) { await params.prompter.note("GitHub Copilot login requires an interactive TTY.", "GitHub Copilot"); return { config: nextConfig }; } try { await githubCopilotLoginCommand({ yes: true }, params.runtime); } catch (err) { await params.prompter.note(`GitHub Copilot login failed: ${String(err)}`, "GitHub Copilot"); return { config: nextConfig }; } nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "github-copilot:github", provider: "github-copilot", mode: "token" }); if (params.setDefaultModel) { const model = "github-copilot/gpt-4o"; nextConfig = { ...nextConfig, agents: { ...nextConfig.agents, defaults: { ...nextConfig.agents?.defaults, model: { ...typeof nextConfig.agents?.defaults?.model === "object" ? nextConfig.agents.defaults.model : void 0, primary: model } } } }; await params.prompter.note(`Default model set to ${model}`, "Model configured"); } return { config: nextConfig }; } //#endregion //#region src/commands/auth-choice.apply.google-antigravity.ts async function applyAuthChoiceGoogleAntigravity(params) { return await applyAuthChoicePluginProvider(params, { authChoice: "google-antigravity", pluginId: "google-antigravity-auth", providerId: "google-antigravity", methodId: "oauth", label: "Google Antigravity" }); } //#endregion //#region src/commands/auth-choice.apply.google-gemini-cli.ts async function applyAuthChoiceGoogleGeminiCli(params) { return await applyAuthChoicePluginProvider(params, { authChoice: "google-gemini-cli", pluginId: "google-gemini-cli-auth", providerId: "google-gemini-cli", methodId: "oauth", label: "Google Gemini CLI" }); } //#endregion //#region src/commands/auth-choice.apply.minimax.ts async function applyAuthChoiceMiniMax(params) { let nextConfig = params.config; let agentModelOverride; const ensureMinimaxApiKey = async (opts) => { let hasCredential = false; const envKey = resolveEnvApiKey("minimax"); if (envKey) { if (await params.prompter.confirm({ message: `Use existing MINIMAX_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, initialValue: true })) { await setMinimaxApiKey(envKey.apiKey, params.agentDir, opts.profileId); hasCredential = true; } } if (!hasCredential) { const key = await params.prompter.text({ message: opts.promptMessage, validate: validateApiKeyInput }); await setMinimaxApiKey(normalizeApiKeyInput(String(key)), params.agentDir, opts.profileId); } }; const noteAgentModel = createAuthChoiceAgentModelNoter(params); if (params.authChoice === "minimax-portal") return await applyAuthChoicePluginProvider(params, { authChoice: "minimax-portal", pluginId: "minimax-portal-auth", providerId: "minimax-portal", methodId: await params.prompter.select({ message: "Select MiniMax endpoint", options: [{ value: "oauth", label: "Global", hint: "OAuth for international users" }, { value: "oauth-cn", label: "CN", hint: "OAuth for users in China" }] }), label: "MiniMax" }); if (params.authChoice === "minimax-cloud" || params.authChoice === "minimax-api" || params.authChoice === "minimax-api-lightning") { const modelId = params.authChoice === "minimax-api-lightning" ? "MiniMax-M2.5-Lightning" : "MiniMax-M2.5"; await ensureMinimaxApiKey({ profileId: "minimax:default", promptMessage: "Enter MiniMax API key" }); nextConfig = applyAuthProfileConfig(nextConfig, { profileId: "minimax:default", provider: "minimax"