From 33d8f6d6f1d8620fec658ea60326644ca5e8d9ad Mon Sep 17 00:00:00 2001 From: Kyle Howells Date: Thu, 29 Jan 2026 16:19:03 +0000 Subject: [PATCH] feat(onboard): add CLI flags and auth handlers for Z.AI/Zhipu variants Add onboarding support for all four GLM provider variants: - CLI flags: --zai-coding-api-key, --zhipu-api-key, --zhipu-coding-api-key - Auth choice menu options with regional grouping - Interactive and non-interactive auth handlers - hasCredential guards for proper token/env var precedence - OAuth rejection for non-API-key auth methods Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- src/cli/program/register.onboard.ts | 8 +- src/commands/auth-choice-options.ts | 26 +- .../auth-choice.apply.api-providers.ts | 326 +++++++++++++----- .../local/auth-choice.ts | 69 +++- src/commands/onboard-types.ts | 6 + 5 files changed, 350 insertions(+), 85 deletions(-) diff --git a/src/cli/program/register.onboard.ts b/src/cli/program/register.onboard.ts index 8f31635f0..699c418c7 100644 --- a/src/cli/program/register.onboard.ts +++ b/src/cli/program/register.onboard.ts @@ -52,7 +52,7 @@ export function registerOnboardCommand(program: Command) { .option("--mode ", "Wizard mode: local|remote") .option( "--auth-choice ", - "Auth: setup-token|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip", + "Auth: setup-token|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|zai-coding-api-key|zhipu-api-key|zhipu-coding-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip", ) .option( "--token-provider ", @@ -72,6 +72,9 @@ export function registerOnboardCommand(program: Command) { .option("--kimi-code-api-key ", "Kimi Code API key") .option("--gemini-api-key ", "Gemini API key") .option("--zai-api-key ", "Z.AI API key") + .option("--zai-coding-api-key ", "Z.AI Coding Plan API key") + .option("--zhipu-api-key ", "Zhipu AI API key") + .option("--zhipu-coding-api-key ", "Zhipu AI Coding Plan API key") .option("--minimax-api-key ", "MiniMax API key") .option("--synthetic-api-key ", "Synthetic API key") .option("--venice-api-key ", "Venice API key") @@ -122,6 +125,9 @@ export function registerOnboardCommand(program: Command) { kimiCodeApiKey: opts.kimiCodeApiKey as string | undefined, geminiApiKey: opts.geminiApiKey as string | undefined, zaiApiKey: opts.zaiApiKey as string | undefined, + zaiCodingApiKey: opts.zaiCodingApiKey as string | undefined, + zhipuApiKey: opts.zhipuApiKey as string | undefined, + zhipuCodingApiKey: opts.zhipuCodingApiKey as string | undefined, minimaxApiKey: opts.minimaxApiKey as string | undefined, syntheticApiKey: opts.syntheticApiKey as string | undefined, veniceApiKey: opts.veniceApiKey as string | undefined, diff --git a/src/commands/auth-choice-options.ts b/src/commands/auth-choice-options.ts index 6b49ff17b..8b8f5ee77 100644 --- a/src/commands/auth-choice-options.ts +++ b/src/commands/auth-choice-options.ts @@ -16,6 +16,7 @@ export type AuthChoiceGroupId = | "ai-gateway" | "moonshot" | "zai" + | "zhipu" | "opencode-zen" | "minimax" | "synthetic" @@ -103,9 +104,15 @@ const AUTH_CHOICE_GROUP_DEFS: { }, { value: "zai", - label: "Z.AI (GLM 4.7)", - hint: "API key", - choices: ["zai-api-key"], + label: "Z.AI (International)", + hint: "GLM models via api.z.ai", + choices: ["zai-api-key", "zai-coding-api-key"], + }, + { + value: "zhipu", + label: "Zhipu AI (China)", + hint: "GLM models via bigmodel.cn", + choices: ["zhipu-api-key", "zhipu-coding-api-key"], }, { value: "opencode-zen", @@ -163,7 +170,18 @@ export function buildAuthChoiceOptions(params: { label: "Google Gemini CLI OAuth", hint: "Uses the bundled Gemini CLI auth plugin", }); - options.push({ value: "zai-api-key", label: "Z.AI (GLM 4.7) API key" }); + options.push({ value: "zai-api-key", label: "Z.AI API key (pay-as-you-go)" }); + options.push({ + value: "zai-coding-api-key", + label: "Z.AI Coding Plan API key", + hint: "Subscription-based, optimized for coding tools", + }); + options.push({ value: "zhipu-api-key", label: "Zhipu AI API key (pay-as-you-go)" }); + options.push({ + value: "zhipu-coding-api-key", + label: "Zhipu AI Coding Plan API key", + hint: "China mainland, subscription-based", + }); options.push({ value: "qwen-portal", label: "Qwen OAuth" }); options.push({ value: "copilot-proxy", diff --git a/src/commands/auth-choice.apply.api-providers.ts b/src/commands/auth-choice.apply.api-providers.ts index 8be02008b..467838626 100644 --- a/src/commands/auth-choice.apply.api-providers.ts +++ b/src/commands/auth-choice.apply.api-providers.ts @@ -27,7 +27,14 @@ import { applyVeniceProviderConfig, applyVercelAiGatewayConfig, applyVercelAiGatewayProviderConfig, + applyZaiCodingConfig, + applyZaiCodingProviderConfig, applyZaiConfig, + applyZaiProviderConfig, + applyZhipuCodingConfig, + applyZhipuCodingProviderConfig, + applyZhipuConfig, + applyZhipuProviderConfig, KIMI_CODE_MODEL_REF, MOONSHOT_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF, @@ -43,7 +50,13 @@ import { setVeniceApiKey, setVercelAiGatewayApiKey, setZaiApiKey, + setZaiCodingApiKey, + setZhipuApiKey, + setZhipuCodingApiKey, + ZAI_CODING_DEFAULT_MODEL_REF, ZAI_DEFAULT_MODEL_REF, + ZHIPU_CODING_DEFAULT_MODEL_REF, + ZHIPU_DEFAULT_MODEL_REF, } from "./onboard-auth.js"; import { OPENCODE_ZEN_DEFAULT_MODEL } from "./opencode-zen-model-default.js"; @@ -79,6 +92,12 @@ export async function applyAuthChoiceApiProviders( authChoice = "gemini-api-key"; } else if (params.opts.tokenProvider === "zai") { authChoice = "zai-api-key"; + } else if (params.opts.tokenProvider === "zai-coding") { + authChoice = "zai-coding-api-key"; + } else if (params.opts.tokenProvider === "zhipu") { + authChoice = "zhipu-api-key"; + } else if (params.opts.tokenProvider === "zhipu-coding") { + authChoice = "zhipu-coding-api-key"; } else if (params.opts.tokenProvider === "synthetic") { authChoice = "synthetic-api-key"; } else if (params.opts.tokenProvider === "venice") { @@ -178,15 +197,17 @@ export async function applyAuthChoiceApiProviders( 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 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) { @@ -226,15 +247,17 @@ export async function applyAuthChoiceApiProviders( 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 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) { @@ -281,15 +304,17 @@ export async function applyAuthChoiceApiProviders( "Kimi Code", ); } - const envKey = resolveEnvApiKey("kimi-code"); - if (envKey) { - const useExisting = await params.prompter.confirm({ - message: `Use existing KIMICODE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, - initialValue: true, - }); - if (useExisting) { - await setKimiCodeApiKey(envKey.apiKey, params.agentDir); - hasCredential = true; + if (!hasCredential) { + const envKey = resolveEnvApiKey("kimi-code"); + if (envKey) { + const useExisting = await params.prompter.confirm({ + message: `Use existing KIMICODE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, + initialValue: true, + }); + if (useExisting) { + await setKimiCodeApiKey(envKey.apiKey, params.agentDir); + hasCredential = true; + } } } if (!hasCredential) { @@ -329,15 +354,17 @@ export async function applyAuthChoiceApiProviders( 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 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) { @@ -376,15 +403,17 @@ export async function applyAuthChoiceApiProviders( 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 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) { @@ -405,22 +434,7 @@ export async function applyAuthChoiceApiProviders( 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", - }, - }, - }, - }, - }), + applyProviderConfig: applyZaiProviderConfig, noteDefault: ZAI_DEFAULT_MODEL_REF, noteAgentModel, prompter: params.prompter, @@ -431,6 +445,156 @@ export async function applyAuthChoiceApiProviders( return { config: nextConfig, agentModelOverride }; } + if (authChoice === "zai-coding-api-key") { + let hasCredential = false; + + if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "zai-coding") { + await setZaiCodingApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); + hasCredential = true; + } + + if (!hasCredential) { + const envKey = resolveEnvApiKey("zai-coding"); + if (envKey) { + const useExisting = await params.prompter.confirm({ + message: `Use existing API key (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, + initialValue: true, + }); + if (useExisting) { + await setZaiCodingApiKey(envKey.apiKey, params.agentDir); + hasCredential = true; + } + } + } + if (!hasCredential) { + const key = await params.prompter.text({ + message: "Enter Z.AI Coding Plan API key", + validate: validateApiKeyInput, + }); + await setZaiCodingApiKey(normalizeApiKeyInput(String(key)), params.agentDir); + } + nextConfig = applyAuthProfileConfig(nextConfig, { + profileId: "zai-coding:default", + provider: "zai-coding", + mode: "api_key", + }); + { + const applied = await applyDefaultModelChoice({ + config: nextConfig, + setDefaultModel: params.setDefaultModel, + defaultModel: ZAI_CODING_DEFAULT_MODEL_REF, + applyDefaultConfig: applyZaiCodingConfig, + applyProviderConfig: applyZaiCodingProviderConfig, + noteDefault: ZAI_CODING_DEFAULT_MODEL_REF, + noteAgentModel, + prompter: params.prompter, + }); + nextConfig = applied.config; + agentModelOverride = applied.agentModelOverride ?? agentModelOverride; + } + return { config: nextConfig, agentModelOverride }; + } + + if (authChoice === "zhipu-api-key") { + let hasCredential = false; + + if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "zhipu") { + await setZhipuApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); + hasCredential = true; + } + + if (!hasCredential) { + const envKey = resolveEnvApiKey("zhipu"); + if (envKey) { + const useExisting = await params.prompter.confirm({ + message: `Use existing ZHIPU_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, + initialValue: true, + }); + if (useExisting) { + await setZhipuApiKey(envKey.apiKey, params.agentDir); + hasCredential = true; + } + } + } + if (!hasCredential) { + const key = await params.prompter.text({ + message: "Enter Zhipu AI API key", + validate: validateApiKeyInput, + }); + await setZhipuApiKey(normalizeApiKeyInput(String(key)), params.agentDir); + } + nextConfig = applyAuthProfileConfig(nextConfig, { + profileId: "zhipu:default", + provider: "zhipu", + mode: "api_key", + }); + { + const applied = await applyDefaultModelChoice({ + config: nextConfig, + setDefaultModel: params.setDefaultModel, + defaultModel: ZHIPU_DEFAULT_MODEL_REF, + applyDefaultConfig: applyZhipuConfig, + applyProviderConfig: applyZhipuProviderConfig, + noteDefault: ZHIPU_DEFAULT_MODEL_REF, + noteAgentModel, + prompter: params.prompter, + }); + nextConfig = applied.config; + agentModelOverride = applied.agentModelOverride ?? agentModelOverride; + } + return { config: nextConfig, agentModelOverride }; + } + + if (authChoice === "zhipu-coding-api-key") { + let hasCredential = false; + + if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "zhipu-coding") { + await setZhipuCodingApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); + hasCredential = true; + } + + if (!hasCredential) { + const envKey = resolveEnvApiKey("zhipu-coding"); + if (envKey) { + const useExisting = await params.prompter.confirm({ + message: `Use existing API key (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, + initialValue: true, + }); + if (useExisting) { + await setZhipuCodingApiKey(envKey.apiKey, params.agentDir); + hasCredential = true; + } + } + } + if (!hasCredential) { + const key = await params.prompter.text({ + message: "Enter Zhipu AI Coding Plan API key", + validate: validateApiKeyInput, + }); + await setZhipuCodingApiKey(normalizeApiKeyInput(String(key)), params.agentDir); + } + nextConfig = applyAuthProfileConfig(nextConfig, { + profileId: "zhipu-coding:default", + provider: "zhipu-coding", + mode: "api_key", + }); + { + const applied = await applyDefaultModelChoice({ + config: nextConfig, + setDefaultModel: params.setDefaultModel, + defaultModel: ZHIPU_CODING_DEFAULT_MODEL_REF, + applyDefaultConfig: applyZhipuCodingConfig, + applyProviderConfig: applyZhipuCodingProviderConfig, + noteDefault: ZHIPU_CODING_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); @@ -482,15 +646,17 @@ export async function applyAuthChoiceApiProviders( ); } - 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 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) { @@ -539,15 +705,17 @@ export async function applyAuthChoiceApiProviders( "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 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) { diff --git a/src/commands/onboard-non-interactive/local/auth-choice.ts b/src/commands/onboard-non-interactive/local/auth-choice.ts index 7d952730c..ca3216774 100644 --- a/src/commands/onboard-non-interactive/local/auth-choice.ts +++ b/src/commands/onboard-non-interactive/local/auth-choice.ts @@ -17,7 +17,10 @@ import { applySyntheticConfig, applyVeniceConfig, applyVercelAiGatewayConfig, + applyZaiCodingConfig, applyZaiConfig, + applyZhipuCodingConfig, + applyZhipuConfig, setAnthropicApiKey, setGeminiApiKey, setKimiCodeApiKey, @@ -29,6 +32,9 @@ import { setVeniceApiKey, setVercelAiGatewayApiKey, setZaiApiKey, + setZaiCodingApiKey, + setZhipuApiKey, + setZhipuCodingApiKey, } from "../../onboard-auth.js"; import type { AuthChoice, OnboardOptions } from "../../onboard-types.js"; import { resolveNonInteractiveApiKey } from "../api-keys.js"; @@ -177,6 +183,63 @@ export async function applyNonInteractiveAuthChoice(params: { return applyZaiConfig(nextConfig); } + if (authChoice === "zai-coding-api-key") { + const resolved = await resolveNonInteractiveApiKey({ + provider: "zai-coding", + cfg: baseConfig, + flagValue: opts.zaiCodingApiKey ?? opts.zaiApiKey, + flagName: "--zai-coding-api-key", + envVar: "ZAI_CODING_API_KEY (or ZAI_API_KEY)", + runtime, + }); + if (!resolved) return null; + if (resolved.source !== "profile") await setZaiCodingApiKey(resolved.key); + nextConfig = applyAuthProfileConfig(nextConfig, { + profileId: "zai-coding:default", + provider: "zai-coding", + mode: "api_key", + }); + return applyZaiCodingConfig(nextConfig); + } + + if (authChoice === "zhipu-api-key") { + const resolved = await resolveNonInteractiveApiKey({ + provider: "zhipu", + cfg: baseConfig, + flagValue: opts.zhipuApiKey, + flagName: "--zhipu-api-key", + envVar: "ZHIPU_API_KEY", + runtime, + }); + if (!resolved) return null; + if (resolved.source !== "profile") await setZhipuApiKey(resolved.key); + nextConfig = applyAuthProfileConfig(nextConfig, { + profileId: "zhipu:default", + provider: "zhipu", + mode: "api_key", + }); + return applyZhipuConfig(nextConfig); + } + + if (authChoice === "zhipu-coding-api-key") { + const resolved = await resolveNonInteractiveApiKey({ + provider: "zhipu-coding", + cfg: baseConfig, + flagValue: opts.zhipuCodingApiKey ?? opts.zhipuApiKey, + flagName: "--zhipu-coding-api-key", + envVar: "ZHIPU_CODING_API_KEY (or ZHIPU_API_KEY)", + runtime, + }); + if (!resolved) return null; + if (resolved.source !== "profile") await setZhipuCodingApiKey(resolved.key); + nextConfig = applyAuthProfileConfig(nextConfig, { + profileId: "zhipu-coding:default", + provider: "zhipu-coding", + mode: "api_key", + }); + return applyZhipuCodingConfig(nextConfig); + } + if (authChoice === "openai-api-key") { const resolved = await resolveNonInteractiveApiKey({ provider: "openai", @@ -359,7 +422,11 @@ export async function applyNonInteractiveAuthChoice(params: { authChoice === "oauth" || authChoice === "chutes" || authChoice === "openai-codex" || - authChoice === "qwen-portal" + authChoice === "qwen-portal" || + authChoice === "github-copilot" || + authChoice === "google-gemini-cli" || + authChoice === "google-antigravity" || + authChoice === "copilot-proxy" ) { runtime.error("OAuth requires interactive mode."); runtime.exit(1); diff --git a/src/commands/onboard-types.ts b/src/commands/onboard-types.ts index aa1d9afe0..83fa8dc9d 100644 --- a/src/commands/onboard-types.ts +++ b/src/commands/onboard-types.ts @@ -23,6 +23,9 @@ export type AuthChoice = | "google-antigravity" | "google-gemini-cli" | "zai-api-key" + | "zai-coding-api-key" + | "zhipu-api-key" + | "zhipu-coding-api-key" | "minimax-cloud" | "minimax" | "minimax-api" @@ -67,6 +70,9 @@ export type OnboardOptions = { kimiCodeApiKey?: string; geminiApiKey?: string; zaiApiKey?: string; + zaiCodingApiKey?: string; + zhipuApiKey?: string; + zhipuCodingApiKey?: string; minimaxApiKey?: string; syntheticApiKey?: string; veniceApiKey?: string;