Spaces:
Running
Running
| import type { ApplyAuthChoiceParams, ApplyAuthChoiceResult } from "./auth-choice.apply.js"; | |
| import { ensureAuthProfileStore, resolveAuthProfileOrder } from "../agents/auth-profiles.js"; | |
| import { resolveEnvApiKey } from "../agents/model-auth.js"; | |
| import { | |
| formatApiKeyPreview, | |
| normalizeApiKeyInput, | |
| validateApiKeyInput, | |
| } from "./auth-choice.api-key.js"; | |
| import { applyDefaultModelChoice } from "./auth-choice.default-model.js"; | |
| import { | |
| applyGoogleGeminiModelDefault, | |
| GOOGLE_GEMINI_DEFAULT_MODEL, | |
| } from "./google-gemini-model-default.js"; | |
| import { | |
| applyAuthProfileConfig, | |
| applyKimiCodeConfig, | |
| applyKimiCodeProviderConfig, | |
| applyMoonshotConfig, | |
| applyMoonshotProviderConfig, | |
| applyOpencodeZenConfig, | |
| applyOpencodeZenProviderConfig, | |
| applyOpenrouterConfig, | |
| applyOpenrouterProviderConfig, | |
| applySyntheticConfig, | |
| applySyntheticProviderConfig, | |
| applyVeniceConfig, | |
| applyVeniceProviderConfig, | |
| applyVercelAiGatewayConfig, | |
| applyVercelAiGatewayProviderConfig, | |
| applyXiaomiConfig, | |
| applyXiaomiProviderConfig, | |
| applyZaiConfig, | |
| KIMI_CODING_MODEL_REF, | |
| MOONSHOT_DEFAULT_MODEL_REF, | |
| OPENROUTER_DEFAULT_MODEL_REF, | |
| SYNTHETIC_DEFAULT_MODEL_REF, | |
| VENICE_DEFAULT_MODEL_REF, | |
| VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, | |
| XIAOMI_DEFAULT_MODEL_REF, | |
| setGeminiApiKey, | |
| setKimiCodingApiKey, | |
| setMoonshotApiKey, | |
| setOpencodeZenApiKey, | |
| setOpenrouterApiKey, | |
| setSyntheticApiKey, | |
| setVeniceApiKey, | |
| setVercelAiGatewayApiKey, | |
| setXiaomiApiKey, | |
| setZaiApiKey, | |
| ZAI_DEFAULT_MODEL_REF, | |
| } from "./onboard-auth.js"; | |
| import { OPENCODE_ZEN_DEFAULT_MODEL } from "./opencode-zen-model-default.js"; | |
| export async function applyAuthChoiceApiProviders( | |
| params: ApplyAuthChoiceParams, | |
| ): Promise<ApplyAuthChoiceResult | null> { | |
| let nextConfig = params.config; | |
| let agentModelOverride: string | undefined; | |
| const noteAgentModel = async (model: string) => { | |
| if (!params.agentId) { | |
| return; | |
| } | |
| await params.prompter.note( | |
| `Default model set to ${model} for agent "${params.agentId}".`, | |
| "Model configured", | |
| ); | |
| }; | |
| 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 === "vercel-ai-gateway") { | |
| authChoice = "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 === "opencode") { | |
| authChoice = "opencode-zen"; | |
| } | |
| } | |
| if (authChoice === "openrouter-api-key") { | |
| const store = ensureAuthProfileStore(params.agentDir, { | |
| allowKeychainPrompt: false, | |
| }); | |
| const profileOrder = resolveAuthProfileOrder({ | |
| cfg: nextConfig, | |
| store, | |
| provider: "openrouter", | |
| }); | |
| const existingProfileId = profileOrder.find((profileId) => Boolean(store.profiles[profileId])); | |
| const existingCred = existingProfileId ? store.profiles[existingProfileId] : undefined; | |
| let profileId = "openrouter:default"; | |
| let mode: "api_key" | "oauth" | "token" = "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) { | |
| const useExisting = await params.prompter.confirm({ | |
| message: `Use existing OPENROUTER_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, | |
| initialValue: true, | |
| }); | |
| if (useExisting) { | |
| 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 }; | |
| } | |
| 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) { | |
| const useExisting = await params.prompter.confirm({ | |
| message: `Use existing AI_GATEWAY_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, | |
| initialValue: true, | |
| }); | |
| if (useExisting) { | |
| 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 === "moonshot-api-key") { | |
| 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) { | |
| const useExisting = await params.prompter.confirm({ | |
| message: `Use existing MOONSHOT_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, | |
| initialValue: true, | |
| }); | |
| if (useExisting) { | |
| await setMoonshotApiKey(envKey.apiKey, params.agentDir); | |
| hasCredential = true; | |
| } | |
| } | |
| if (!hasCredential) { | |
| const key = await params.prompter.text({ | |
| message: "Enter Moonshot API key", | |
| validate: validateApiKeyInput, | |
| }); | |
| await setMoonshotApiKey(normalizeApiKeyInput(String(key)), params.agentDir); | |
| } | |
| 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 === "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) { | |
| const useExisting = await params.prompter.confirm({ | |
| message: `Use existing KIMI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, | |
| initialValue: true, | |
| }); | |
| if (useExisting) { | |
| 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) { | |
| const useExisting = await params.prompter.confirm({ | |
| message: `Use existing GEMINI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, | |
| initialValue: true, | |
| }); | |
| if (useExisting) { | |
| 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") { | |
| let hasCredential = false; | |
| if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "zai") { | |
| await setZaiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); | |
| hasCredential = true; | |
| } | |
| const envKey = resolveEnvApiKey("zai"); | |
| if (envKey) { | |
| const useExisting = await params.prompter.confirm({ | |
| message: `Use existing ZAI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, | |
| initialValue: true, | |
| }); | |
| if (useExisting) { | |
| await setZaiApiKey(envKey.apiKey, params.agentDir); | |
| hasCredential = true; | |
| } | |
| } | |
| if (!hasCredential) { | |
| const key = await params.prompter.text({ | |
| message: "Enter Z.AI API key", | |
| validate: validateApiKeyInput, | |
| }); | |
| await setZaiApiKey(normalizeApiKeyInput(String(key)), params.agentDir); | |
| } | |
| nextConfig = applyAuthProfileConfig(nextConfig, { | |
| profileId: "zai:default", | |
| provider: "zai", | |
| mode: "api_key", | |
| }); | |
| { | |
| const applied = await applyDefaultModelChoice({ | |
| config: nextConfig, | |
| setDefaultModel: params.setDefaultModel, | |
| defaultModel: ZAI_DEFAULT_MODEL_REF, | |
| applyDefaultConfig: applyZaiConfig, | |
| applyProviderConfig: (config) => ({ | |
| ...config, | |
| agents: { | |
| ...config.agents, | |
| defaults: { | |
| ...config.agents?.defaults, | |
| models: { | |
| ...config.agents?.defaults?.models, | |
| [ZAI_DEFAULT_MODEL_REF]: { | |
| ...config.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF], | |
| alias: config.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF]?.alias ?? "GLM", | |
| }, | |
| }, | |
| }, | |
| }, | |
| }), | |
| noteDefault: ZAI_DEFAULT_MODEL_REF, | |
| 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) { | |
| const useExisting = await params.prompter.confirm({ | |
| message: `Use existing XIAOMI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, | |
| initialValue: true, | |
| }); | |
| if (useExisting) { | |
| 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() ? undefined : "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) { | |
| const useExisting = await params.prompter.confirm({ | |
| message: `Use existing VENICE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, | |
| initialValue: true, | |
| }); | |
| if (useExisting) { | |
| 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", | |
| "Requires an active OpenCode Zen subscription.", | |
| ].join("\n"), | |
| "OpenCode Zen", | |
| ); | |
| } | |
| const envKey = resolveEnvApiKey("opencode"); | |
| if (envKey) { | |
| const useExisting = await params.prompter.confirm({ | |
| message: `Use existing OPENCODE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, | |
| initialValue: true, | |
| }); | |
| if (useExisting) { | |
| 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 }; | |
| } | |
| return null; | |
| } | |