mirror of https://github.com/openclaw/openclaw.git
Commands: split static onboard auth choice help (#47545)
* Commands: split static onboard auth choice help * Tests: cover static onboard auth choice help * Changelog: note static onboard auth choice help
This commit is contained in:
parent
c9a8b6f82f
commit
dd2eb29038
|
|
@ -97,6 +97,7 @@ Docs: https://docs.openclaw.ai
|
|||
- macOS/exec approvals: respect per-agent exec approval settings in the gateway prompter, including allowlist fallback when the native prompt cannot be shown, so gateway-triggered `system.run` requests follow configured policy instead of always prompting or denying unexpectedly. (#13707) Thanks @sliekens.
|
||||
- Telegram/media downloads: thread the same direct or proxy transport policy into SSRF-guarded file fetches so inbound attachments keep working when Telegram falls back between env-proxy and direct networking. (#44639) Thanks @obviyus.
|
||||
- Telegram/inbound media IPv4 fallback: retry SSRF-guarded Telegram file downloads once with the same IPv4 fallback policy as Bot API calls so fresh installs on IPv6-broken hosts no longer fail to download inbound images.
|
||||
- Commands/onboarding: split static auth-choice help from the plugin-backed onboarding catalog so `openclaw onboard` registration no longer pulls provider-wizard imports just to describe `--auth-choice`. (#47545) Thanks @vincentkoc.
|
||||
- Windows/gateway install: bound `schtasks` calls and fall back to the Startup-folder login item when task creation hangs, so native `openclaw gateway install` fails fast instead of wedging forever on broken Scheduled Task setups.
|
||||
- Windows/gateway stop: resolve Startup-folder fallback listeners from the installed `gateway.cmd` port, so `openclaw gateway stop` now actually kills fallback-launched gateway processes before restart.
|
||||
- Windows/gateway status: reuse the installed service command environment when reading runtime status, so startup-fallback gateways keep reporting the configured port and running state in `gateway status --json` instead of falling back to `gateway port unknown`.
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ const runtime = {
|
|||
exit: vi.fn(),
|
||||
};
|
||||
|
||||
vi.mock("../../commands/auth-choice-options.js", () => ({
|
||||
formatAuthChoiceChoicesForCli: () => "token|oauth",
|
||||
vi.mock("../../commands/auth-choice-options.static.js", () => ({
|
||||
formatStaticAuthChoiceChoicesForCli: () => "token|oauth",
|
||||
}));
|
||||
|
||||
vi.mock("../../commands/onboard-provider-auth-flags.js", () => ({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Command } from "commander";
|
||||
import { formatAuthChoiceChoicesForCli } from "../../commands/auth-choice-options.js";
|
||||
import { formatStaticAuthChoiceChoicesForCli } from "../../commands/auth-choice-options.static.js";
|
||||
import type { GatewayDaemonRuntime } from "../../commands/daemon-runtime.js";
|
||||
import { ONBOARD_PROVIDER_AUTH_FLAGS } from "../../commands/onboard-provider-auth-flags.js";
|
||||
import type {
|
||||
|
|
@ -41,7 +41,7 @@ function resolveInstallDaemonFlag(
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const AUTH_CHOICE_HELP = formatAuthChoiceChoicesForCli({
|
||||
const AUTH_CHOICE_HELP = formatStaticAuthChoiceChoicesForCli({
|
||||
includeLegacyAliases: true,
|
||||
includeSkip: true,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,332 @@
|
|||
import { AUTH_CHOICE_LEGACY_ALIASES_FOR_CLI } from "./auth-choice-legacy.js";
|
||||
import { ONBOARD_PROVIDER_AUTH_FLAGS } from "./onboard-provider-auth-flags.js";
|
||||
import type { AuthChoice, AuthChoiceGroupId } from "./onboard-types.js";
|
||||
|
||||
export type { AuthChoiceGroupId };
|
||||
|
||||
export type AuthChoiceOption = {
|
||||
value: AuthChoice;
|
||||
label: string;
|
||||
hint?: string;
|
||||
};
|
||||
export type AuthChoiceGroup = {
|
||||
value: AuthChoiceGroupId;
|
||||
label: string;
|
||||
hint?: string;
|
||||
options: AuthChoiceOption[];
|
||||
};
|
||||
|
||||
export const AUTH_CHOICE_GROUP_DEFS: {
|
||||
value: AuthChoiceGroupId;
|
||||
label: string;
|
||||
hint?: string;
|
||||
choices: AuthChoice[];
|
||||
}[] = [
|
||||
{
|
||||
value: "openai",
|
||||
label: "OpenAI",
|
||||
hint: "Codex OAuth + API key",
|
||||
choices: ["openai-codex", "openai-api-key"],
|
||||
},
|
||||
{
|
||||
value: "anthropic",
|
||||
label: "Anthropic",
|
||||
hint: "setup-token + API key",
|
||||
choices: ["token", "apiKey"],
|
||||
},
|
||||
{
|
||||
value: "chutes",
|
||||
label: "Chutes",
|
||||
hint: "OAuth",
|
||||
choices: ["chutes"],
|
||||
},
|
||||
{
|
||||
value: "minimax",
|
||||
label: "MiniMax",
|
||||
hint: "M2.5 (recommended)",
|
||||
choices: ["minimax-global-oauth", "minimax-global-api", "minimax-cn-oauth", "minimax-cn-api"],
|
||||
},
|
||||
{
|
||||
value: "moonshot",
|
||||
label: "Moonshot AI (Kimi K2.5)",
|
||||
hint: "Kimi K2.5 + Kimi Coding",
|
||||
choices: ["moonshot-api-key", "moonshot-api-key-cn", "kimi-code-api-key"],
|
||||
},
|
||||
{
|
||||
value: "google",
|
||||
label: "Google",
|
||||
hint: "Gemini API key + OAuth",
|
||||
choices: ["gemini-api-key", "google-gemini-cli"],
|
||||
},
|
||||
{
|
||||
value: "xai",
|
||||
label: "xAI (Grok)",
|
||||
hint: "API key",
|
||||
choices: ["xai-api-key"],
|
||||
},
|
||||
{
|
||||
value: "mistral",
|
||||
label: "Mistral AI",
|
||||
hint: "API key",
|
||||
choices: ["mistral-api-key"],
|
||||
},
|
||||
{
|
||||
value: "volcengine",
|
||||
label: "Volcano Engine",
|
||||
hint: "API key",
|
||||
choices: ["volcengine-api-key"],
|
||||
},
|
||||
{
|
||||
value: "byteplus",
|
||||
label: "BytePlus",
|
||||
hint: "API key",
|
||||
choices: ["byteplus-api-key"],
|
||||
},
|
||||
{
|
||||
value: "openrouter",
|
||||
label: "OpenRouter",
|
||||
hint: "API key",
|
||||
choices: ["openrouter-api-key"],
|
||||
},
|
||||
{
|
||||
value: "kilocode",
|
||||
label: "Kilo Gateway",
|
||||
hint: "API key (OpenRouter-compatible)",
|
||||
choices: ["kilocode-api-key"],
|
||||
},
|
||||
{
|
||||
value: "qwen",
|
||||
label: "Qwen",
|
||||
hint: "OAuth",
|
||||
choices: ["qwen-portal"],
|
||||
},
|
||||
{
|
||||
value: "zai",
|
||||
label: "Z.AI",
|
||||
hint: "GLM Coding Plan / Global / CN",
|
||||
choices: ["zai-coding-global", "zai-coding-cn", "zai-global", "zai-cn"],
|
||||
},
|
||||
{
|
||||
value: "qianfan",
|
||||
label: "Qianfan",
|
||||
hint: "API key",
|
||||
choices: ["qianfan-api-key"],
|
||||
},
|
||||
{
|
||||
value: "modelstudio",
|
||||
label: "Alibaba Cloud Model Studio",
|
||||
hint: "Coding Plan API key (CN / Global)",
|
||||
choices: ["modelstudio-api-key-cn", "modelstudio-api-key"],
|
||||
},
|
||||
{
|
||||
value: "copilot",
|
||||
label: "Copilot",
|
||||
hint: "GitHub + local proxy",
|
||||
choices: ["github-copilot", "copilot-proxy"],
|
||||
},
|
||||
{
|
||||
value: "ai-gateway",
|
||||
label: "Vercel AI Gateway",
|
||||
hint: "API key",
|
||||
choices: ["ai-gateway-api-key"],
|
||||
},
|
||||
{
|
||||
value: "opencode",
|
||||
label: "OpenCode",
|
||||
hint: "Shared API key for Zen + Go catalogs",
|
||||
choices: ["opencode-zen", "opencode-go"],
|
||||
},
|
||||
{
|
||||
value: "xiaomi",
|
||||
label: "Xiaomi",
|
||||
hint: "API key",
|
||||
choices: ["xiaomi-api-key"],
|
||||
},
|
||||
{
|
||||
value: "synthetic",
|
||||
label: "Synthetic",
|
||||
hint: "Anthropic-compatible (multi-model)",
|
||||
choices: ["synthetic-api-key"],
|
||||
},
|
||||
{
|
||||
value: "together",
|
||||
label: "Together AI",
|
||||
hint: "API key",
|
||||
choices: ["together-api-key"],
|
||||
},
|
||||
{
|
||||
value: "huggingface",
|
||||
label: "Hugging Face",
|
||||
hint: "Inference API (HF token)",
|
||||
choices: ["huggingface-api-key"],
|
||||
},
|
||||
{
|
||||
value: "venice",
|
||||
label: "Venice AI",
|
||||
hint: "Privacy-focused (uncensored models)",
|
||||
choices: ["venice-api-key"],
|
||||
},
|
||||
{
|
||||
value: "litellm",
|
||||
label: "LiteLLM",
|
||||
hint: "Unified LLM gateway (100+ providers)",
|
||||
choices: ["litellm-api-key"],
|
||||
},
|
||||
{
|
||||
value: "cloudflare-ai-gateway",
|
||||
label: "Cloudflare AI Gateway",
|
||||
hint: "Account ID + Gateway ID + API key",
|
||||
choices: ["cloudflare-ai-gateway-api-key"],
|
||||
},
|
||||
{
|
||||
value: "custom",
|
||||
label: "Custom Provider",
|
||||
hint: "Any OpenAI or Anthropic compatible endpoint",
|
||||
choices: ["custom-api-key"],
|
||||
},
|
||||
];
|
||||
|
||||
const PROVIDER_AUTH_CHOICE_OPTION_HINTS: Partial<Record<AuthChoice, string>> = {
|
||||
"litellm-api-key": "Unified gateway for 100+ LLM providers",
|
||||
"cloudflare-ai-gateway-api-key": "Account ID + Gateway ID + API key",
|
||||
"venice-api-key": "Privacy-focused inference (uncensored models)",
|
||||
"together-api-key": "Access to Llama, DeepSeek, Qwen, and more open models",
|
||||
"huggingface-api-key": "Inference Providers — OpenAI-compatible chat",
|
||||
"opencode-zen": "Shared OpenCode key; curated Zen catalog",
|
||||
"opencode-go": "Shared OpenCode key; Kimi/GLM/MiniMax Go catalog",
|
||||
};
|
||||
|
||||
const PROVIDER_AUTH_CHOICE_OPTION_LABELS: Partial<Record<AuthChoice, string>> = {
|
||||
"moonshot-api-key": "Kimi API key (.ai)",
|
||||
"moonshot-api-key-cn": "Kimi API key (.cn)",
|
||||
"kimi-code-api-key": "Kimi Code API key (subscription)",
|
||||
"cloudflare-ai-gateway-api-key": "Cloudflare AI Gateway",
|
||||
"opencode-zen": "OpenCode Zen catalog",
|
||||
"opencode-go": "OpenCode Go catalog",
|
||||
};
|
||||
|
||||
function buildProviderAuthChoiceOptions(): AuthChoiceOption[] {
|
||||
return ONBOARD_PROVIDER_AUTH_FLAGS.map((flag) => ({
|
||||
value: flag.authChoice,
|
||||
label: PROVIDER_AUTH_CHOICE_OPTION_LABELS[flag.authChoice] ?? flag.description,
|
||||
...(PROVIDER_AUTH_CHOICE_OPTION_HINTS[flag.authChoice]
|
||||
? { hint: PROVIDER_AUTH_CHOICE_OPTION_HINTS[flag.authChoice] }
|
||||
: {}),
|
||||
}));
|
||||
}
|
||||
|
||||
export const BASE_AUTH_CHOICE_OPTIONS: ReadonlyArray<AuthChoiceOption> = [
|
||||
{
|
||||
value: "token",
|
||||
label: "Anthropic token (paste setup-token)",
|
||||
hint: "run `claude setup-token` elsewhere, then paste the token here",
|
||||
},
|
||||
{
|
||||
value: "openai-codex",
|
||||
label: "OpenAI Codex (ChatGPT OAuth)",
|
||||
},
|
||||
{ value: "chutes", label: "Chutes (OAuth)" },
|
||||
...buildProviderAuthChoiceOptions(),
|
||||
{
|
||||
value: "moonshot-api-key-cn",
|
||||
label: "Kimi API key (.cn)",
|
||||
},
|
||||
{
|
||||
value: "github-copilot",
|
||||
label: "GitHub Copilot (GitHub device login)",
|
||||
hint: "Uses GitHub device flow",
|
||||
},
|
||||
{ value: "gemini-api-key", label: "Google Gemini API key" },
|
||||
{
|
||||
value: "google-gemini-cli",
|
||||
label: "Google Gemini CLI OAuth",
|
||||
hint: "Unofficial flow; review account-risk warning before use",
|
||||
},
|
||||
{ value: "zai-api-key", label: "Z.AI API key" },
|
||||
{
|
||||
value: "zai-coding-global",
|
||||
label: "Coding-Plan-Global",
|
||||
hint: "GLM Coding Plan Global (api.z.ai)",
|
||||
},
|
||||
{
|
||||
value: "zai-coding-cn",
|
||||
label: "Coding-Plan-CN",
|
||||
hint: "GLM Coding Plan CN (open.bigmodel.cn)",
|
||||
},
|
||||
{
|
||||
value: "zai-global",
|
||||
label: "Global",
|
||||
hint: "Z.AI Global (api.z.ai)",
|
||||
},
|
||||
{
|
||||
value: "zai-cn",
|
||||
label: "CN",
|
||||
hint: "Z.AI CN (open.bigmodel.cn)",
|
||||
},
|
||||
{
|
||||
value: "xiaomi-api-key",
|
||||
label: "Xiaomi API key",
|
||||
},
|
||||
{
|
||||
value: "minimax-global-oauth",
|
||||
label: "MiniMax Global — OAuth (minimax.io)",
|
||||
hint: "Only supports OAuth for the coding plan",
|
||||
},
|
||||
{
|
||||
value: "minimax-global-api",
|
||||
label: "MiniMax Global — API Key (minimax.io)",
|
||||
hint: "sk-api- or sk-cp- keys supported",
|
||||
},
|
||||
{
|
||||
value: "minimax-cn-oauth",
|
||||
label: "MiniMax CN — OAuth (minimaxi.com)",
|
||||
hint: "Only supports OAuth for the coding plan",
|
||||
},
|
||||
{
|
||||
value: "minimax-cn-api",
|
||||
label: "MiniMax CN — API Key (minimaxi.com)",
|
||||
hint: "sk-api- or sk-cp- keys supported",
|
||||
},
|
||||
{ value: "qwen-portal", label: "Qwen OAuth" },
|
||||
{
|
||||
value: "copilot-proxy",
|
||||
label: "Copilot Proxy (local)",
|
||||
hint: "Local proxy for VS Code Copilot models",
|
||||
},
|
||||
{ value: "apiKey", label: "Anthropic API key" },
|
||||
{
|
||||
value: "opencode-zen",
|
||||
label: "OpenCode Zen catalog",
|
||||
hint: "Claude, GPT, Gemini via opencode.ai/zen",
|
||||
},
|
||||
{ value: "qianfan-api-key", label: "Qianfan API key" },
|
||||
{
|
||||
value: "modelstudio-api-key-cn",
|
||||
label: "Coding Plan API Key for China (subscription)",
|
||||
hint: "Endpoint: coding.dashscope.aliyuncs.com",
|
||||
},
|
||||
{
|
||||
value: "modelstudio-api-key",
|
||||
label: "Coding Plan API Key for Global/Intl (subscription)",
|
||||
hint: "Endpoint: coding-intl.dashscope.aliyuncs.com",
|
||||
},
|
||||
{ value: "custom-api-key", label: "Custom Provider" },
|
||||
];
|
||||
|
||||
export function formatStaticAuthChoiceChoicesForCli(params?: {
|
||||
includeSkip?: boolean;
|
||||
includeLegacyAliases?: boolean;
|
||||
}): string {
|
||||
const includeSkip = params?.includeSkip ?? true;
|
||||
const includeLegacyAliases = params?.includeLegacyAliases ?? false;
|
||||
const values = BASE_AUTH_CHOICE_OPTIONS.map((opt) => opt.value);
|
||||
|
||||
if (includeSkip) {
|
||||
values.push("skip");
|
||||
}
|
||||
if (includeLegacyAliases) {
|
||||
values.push(...AUTH_CHOICE_LEGACY_ALIASES_FOR_CLI);
|
||||
}
|
||||
|
||||
return values.join("|");
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import {
|
|||
buildAuthChoiceOptions,
|
||||
formatAuthChoiceChoicesForCli,
|
||||
} from "./auth-choice-options.js";
|
||||
import { formatStaticAuthChoiceChoicesForCli } from "./auth-choice-options.static.js";
|
||||
|
||||
const resolveProviderWizardOptions = vi.hoisted(() =>
|
||||
vi.fn<() => ProviderWizardOption[]>(() => []),
|
||||
|
|
@ -104,6 +105,26 @@ describe("buildAuthChoiceOptions", () => {
|
|||
expect(cliChoices).toContain("codex-cli");
|
||||
});
|
||||
|
||||
it("keeps static cli help choices off the plugin-backed catalog", () => {
|
||||
resolveProviderWizardOptions.mockReturnValue([
|
||||
{
|
||||
value: "ollama",
|
||||
label: "Ollama",
|
||||
hint: "Cloud and local open models",
|
||||
groupId: "ollama",
|
||||
groupLabel: "Ollama",
|
||||
},
|
||||
]);
|
||||
|
||||
const cliChoices = formatStaticAuthChoiceChoicesForCli({
|
||||
includeLegacyAliases: false,
|
||||
includeSkip: true,
|
||||
}).split("|");
|
||||
|
||||
expect(cliChoices).not.toContain("ollama");
|
||||
expect(cliChoices).toContain("skip");
|
||||
});
|
||||
|
||||
it("shows Chutes in grouped provider selection", () => {
|
||||
const { groups } = buildAuthChoiceGroups({
|
||||
store: EMPTY_STORE,
|
||||
|
|
|
|||
|
|
@ -1,321 +1,15 @@
|
|||
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveProviderWizardOptions } from "../plugins/provider-wizard.js";
|
||||
import { AUTH_CHOICE_LEGACY_ALIASES_FOR_CLI } from "./auth-choice-legacy.js";
|
||||
import { ONBOARD_PROVIDER_AUTH_FLAGS } from "./onboard-provider-auth-flags.js";
|
||||
import {
|
||||
AUTH_CHOICE_GROUP_DEFS,
|
||||
BASE_AUTH_CHOICE_OPTIONS,
|
||||
type AuthChoiceGroup,
|
||||
type AuthChoiceOption,
|
||||
formatStaticAuthChoiceChoicesForCli,
|
||||
} from "./auth-choice-options.static.js";
|
||||
import type { AuthChoice, AuthChoiceGroupId } from "./onboard-types.js";
|
||||
|
||||
export type { AuthChoiceGroupId };
|
||||
|
||||
export type AuthChoiceOption = {
|
||||
value: AuthChoice;
|
||||
label: string;
|
||||
hint?: string;
|
||||
};
|
||||
export type AuthChoiceGroup = {
|
||||
value: AuthChoiceGroupId;
|
||||
label: string;
|
||||
hint?: string;
|
||||
options: AuthChoiceOption[];
|
||||
};
|
||||
|
||||
const AUTH_CHOICE_GROUP_DEFS: {
|
||||
value: AuthChoiceGroupId;
|
||||
label: string;
|
||||
hint?: string;
|
||||
choices: AuthChoice[];
|
||||
}[] = [
|
||||
{
|
||||
value: "openai",
|
||||
label: "OpenAI",
|
||||
hint: "Codex OAuth + API key",
|
||||
choices: ["openai-codex", "openai-api-key"],
|
||||
},
|
||||
{
|
||||
value: "anthropic",
|
||||
label: "Anthropic",
|
||||
hint: "setup-token + API key",
|
||||
choices: ["token", "apiKey"],
|
||||
},
|
||||
{
|
||||
value: "chutes",
|
||||
label: "Chutes",
|
||||
hint: "OAuth",
|
||||
choices: ["chutes"],
|
||||
},
|
||||
{
|
||||
value: "minimax",
|
||||
label: "MiniMax",
|
||||
hint: "M2.5 (recommended)",
|
||||
choices: ["minimax-global-oauth", "minimax-global-api", "minimax-cn-oauth", "minimax-cn-api"],
|
||||
},
|
||||
{
|
||||
value: "moonshot",
|
||||
label: "Moonshot AI (Kimi K2.5)",
|
||||
hint: "Kimi K2.5 + Kimi Coding",
|
||||
choices: ["moonshot-api-key", "moonshot-api-key-cn", "kimi-code-api-key"],
|
||||
},
|
||||
{
|
||||
value: "google",
|
||||
label: "Google",
|
||||
hint: "Gemini API key + OAuth",
|
||||
choices: ["gemini-api-key", "google-gemini-cli"],
|
||||
},
|
||||
{
|
||||
value: "xai",
|
||||
label: "xAI (Grok)",
|
||||
hint: "API key",
|
||||
choices: ["xai-api-key"],
|
||||
},
|
||||
{
|
||||
value: "mistral",
|
||||
label: "Mistral AI",
|
||||
hint: "API key",
|
||||
choices: ["mistral-api-key"],
|
||||
},
|
||||
{
|
||||
value: "volcengine",
|
||||
label: "Volcano Engine",
|
||||
hint: "API key",
|
||||
choices: ["volcengine-api-key"],
|
||||
},
|
||||
{
|
||||
value: "byteplus",
|
||||
label: "BytePlus",
|
||||
hint: "API key",
|
||||
choices: ["byteplus-api-key"],
|
||||
},
|
||||
{
|
||||
value: "openrouter",
|
||||
label: "OpenRouter",
|
||||
hint: "API key",
|
||||
choices: ["openrouter-api-key"],
|
||||
},
|
||||
{
|
||||
value: "kilocode",
|
||||
label: "Kilo Gateway",
|
||||
hint: "API key (OpenRouter-compatible)",
|
||||
choices: ["kilocode-api-key"],
|
||||
},
|
||||
{
|
||||
value: "qwen",
|
||||
label: "Qwen",
|
||||
hint: "OAuth",
|
||||
choices: ["qwen-portal"],
|
||||
},
|
||||
{
|
||||
value: "zai",
|
||||
label: "Z.AI",
|
||||
hint: "GLM Coding Plan / Global / CN",
|
||||
choices: ["zai-coding-global", "zai-coding-cn", "zai-global", "zai-cn"],
|
||||
},
|
||||
{
|
||||
value: "qianfan",
|
||||
label: "Qianfan",
|
||||
hint: "API key",
|
||||
choices: ["qianfan-api-key"],
|
||||
},
|
||||
{
|
||||
value: "modelstudio",
|
||||
label: "Alibaba Cloud Model Studio",
|
||||
hint: "Coding Plan API key (CN / Global)",
|
||||
choices: ["modelstudio-api-key-cn", "modelstudio-api-key"],
|
||||
},
|
||||
{
|
||||
value: "copilot",
|
||||
label: "Copilot",
|
||||
hint: "GitHub + local proxy",
|
||||
choices: ["github-copilot", "copilot-proxy"],
|
||||
},
|
||||
{
|
||||
value: "ai-gateway",
|
||||
label: "Vercel AI Gateway",
|
||||
hint: "API key",
|
||||
choices: ["ai-gateway-api-key"],
|
||||
},
|
||||
{
|
||||
value: "opencode",
|
||||
label: "OpenCode",
|
||||
hint: "Shared API key for Zen + Go catalogs",
|
||||
choices: ["opencode-zen", "opencode-go"],
|
||||
},
|
||||
{
|
||||
value: "xiaomi",
|
||||
label: "Xiaomi",
|
||||
hint: "API key",
|
||||
choices: ["xiaomi-api-key"],
|
||||
},
|
||||
{
|
||||
value: "synthetic",
|
||||
label: "Synthetic",
|
||||
hint: "Anthropic-compatible (multi-model)",
|
||||
choices: ["synthetic-api-key"],
|
||||
},
|
||||
{
|
||||
value: "together",
|
||||
label: "Together AI",
|
||||
hint: "API key",
|
||||
choices: ["together-api-key"],
|
||||
},
|
||||
{
|
||||
value: "huggingface",
|
||||
label: "Hugging Face",
|
||||
hint: "Inference API (HF token)",
|
||||
choices: ["huggingface-api-key"],
|
||||
},
|
||||
{
|
||||
value: "venice",
|
||||
label: "Venice AI",
|
||||
hint: "Privacy-focused (uncensored models)",
|
||||
choices: ["venice-api-key"],
|
||||
},
|
||||
{
|
||||
value: "litellm",
|
||||
label: "LiteLLM",
|
||||
hint: "Unified LLM gateway (100+ providers)",
|
||||
choices: ["litellm-api-key"],
|
||||
},
|
||||
{
|
||||
value: "cloudflare-ai-gateway",
|
||||
label: "Cloudflare AI Gateway",
|
||||
hint: "Account ID + Gateway ID + API key",
|
||||
choices: ["cloudflare-ai-gateway-api-key"],
|
||||
},
|
||||
{
|
||||
value: "custom",
|
||||
label: "Custom Provider",
|
||||
hint: "Any OpenAI or Anthropic compatible endpoint",
|
||||
choices: ["custom-api-key"],
|
||||
},
|
||||
];
|
||||
|
||||
const PROVIDER_AUTH_CHOICE_OPTION_HINTS: Partial<Record<AuthChoice, string>> = {
|
||||
"litellm-api-key": "Unified gateway for 100+ LLM providers",
|
||||
"cloudflare-ai-gateway-api-key": "Account ID + Gateway ID + API key",
|
||||
"venice-api-key": "Privacy-focused inference (uncensored models)",
|
||||
"together-api-key": "Access to Llama, DeepSeek, Qwen, and more open models",
|
||||
"huggingface-api-key": "Inference Providers — OpenAI-compatible chat",
|
||||
"opencode-zen": "Shared OpenCode key; curated Zen catalog",
|
||||
"opencode-go": "Shared OpenCode key; Kimi/GLM/MiniMax Go catalog",
|
||||
};
|
||||
|
||||
const PROVIDER_AUTH_CHOICE_OPTION_LABELS: Partial<Record<AuthChoice, string>> = {
|
||||
"moonshot-api-key": "Kimi API key (.ai)",
|
||||
"moonshot-api-key-cn": "Kimi API key (.cn)",
|
||||
"kimi-code-api-key": "Kimi Code API key (subscription)",
|
||||
"cloudflare-ai-gateway-api-key": "Cloudflare AI Gateway",
|
||||
"opencode-zen": "OpenCode Zen catalog",
|
||||
"opencode-go": "OpenCode Go catalog",
|
||||
};
|
||||
|
||||
function buildProviderAuthChoiceOptions(): AuthChoiceOption[] {
|
||||
return ONBOARD_PROVIDER_AUTH_FLAGS.map((flag) => ({
|
||||
value: flag.authChoice,
|
||||
label: PROVIDER_AUTH_CHOICE_OPTION_LABELS[flag.authChoice] ?? flag.description,
|
||||
...(PROVIDER_AUTH_CHOICE_OPTION_HINTS[flag.authChoice]
|
||||
? { hint: PROVIDER_AUTH_CHOICE_OPTION_HINTS[flag.authChoice] }
|
||||
: {}),
|
||||
}));
|
||||
}
|
||||
|
||||
const BASE_AUTH_CHOICE_OPTIONS: ReadonlyArray<AuthChoiceOption> = [
|
||||
{
|
||||
value: "token",
|
||||
label: "Anthropic token (paste setup-token)",
|
||||
hint: "run `claude setup-token` elsewhere, then paste the token here",
|
||||
},
|
||||
{
|
||||
value: "openai-codex",
|
||||
label: "OpenAI Codex (ChatGPT OAuth)",
|
||||
},
|
||||
{ value: "chutes", label: "Chutes (OAuth)" },
|
||||
...buildProviderAuthChoiceOptions(),
|
||||
{
|
||||
value: "moonshot-api-key-cn",
|
||||
label: "Kimi API key (.cn)",
|
||||
},
|
||||
{
|
||||
value: "github-copilot",
|
||||
label: "GitHub Copilot (GitHub device login)",
|
||||
hint: "Uses GitHub device flow",
|
||||
},
|
||||
{ value: "gemini-api-key", label: "Google Gemini API key" },
|
||||
{
|
||||
value: "google-gemini-cli",
|
||||
label: "Google Gemini CLI OAuth",
|
||||
hint: "Unofficial flow; review account-risk warning before use",
|
||||
},
|
||||
{ value: "zai-api-key", label: "Z.AI API key" },
|
||||
{
|
||||
value: "zai-coding-global",
|
||||
label: "Coding-Plan-Global",
|
||||
hint: "GLM Coding Plan Global (api.z.ai)",
|
||||
},
|
||||
{
|
||||
value: "zai-coding-cn",
|
||||
label: "Coding-Plan-CN",
|
||||
hint: "GLM Coding Plan CN (open.bigmodel.cn)",
|
||||
},
|
||||
{
|
||||
value: "zai-global",
|
||||
label: "Global",
|
||||
hint: "Z.AI Global (api.z.ai)",
|
||||
},
|
||||
{
|
||||
value: "zai-cn",
|
||||
label: "CN",
|
||||
hint: "Z.AI CN (open.bigmodel.cn)",
|
||||
},
|
||||
{
|
||||
value: "xiaomi-api-key",
|
||||
label: "Xiaomi API key",
|
||||
},
|
||||
{
|
||||
value: "minimax-global-oauth",
|
||||
label: "MiniMax Global — OAuth (minimax.io)",
|
||||
hint: "Only supports OAuth for the coding plan",
|
||||
},
|
||||
{
|
||||
value: "minimax-global-api",
|
||||
label: "MiniMax Global — API Key (minimax.io)",
|
||||
hint: "sk-api- or sk-cp- keys supported",
|
||||
},
|
||||
{
|
||||
value: "minimax-cn-oauth",
|
||||
label: "MiniMax CN — OAuth (minimaxi.com)",
|
||||
hint: "Only supports OAuth for the coding plan",
|
||||
},
|
||||
{
|
||||
value: "minimax-cn-api",
|
||||
label: "MiniMax CN — API Key (minimaxi.com)",
|
||||
hint: "sk-api- or sk-cp- keys supported",
|
||||
},
|
||||
{ value: "qwen-portal", label: "Qwen OAuth" },
|
||||
{
|
||||
value: "copilot-proxy",
|
||||
label: "Copilot Proxy (local)",
|
||||
hint: "Local proxy for VS Code Copilot models",
|
||||
},
|
||||
{ value: "apiKey", label: "Anthropic API key" },
|
||||
{
|
||||
value: "opencode-zen",
|
||||
label: "OpenCode Zen catalog",
|
||||
hint: "Claude, GPT, Gemini via opencode.ai/zen",
|
||||
},
|
||||
{ value: "qianfan-api-key", label: "Qianfan API key" },
|
||||
{
|
||||
value: "modelstudio-api-key-cn",
|
||||
label: "Coding Plan API Key for China (subscription)",
|
||||
hint: "Endpoint: coding.dashscope.aliyuncs.com",
|
||||
},
|
||||
{
|
||||
value: "modelstudio-api-key",
|
||||
label: "Coding Plan API Key for Global/Intl (subscription)",
|
||||
hint: "Endpoint: coding-intl.dashscope.aliyuncs.com",
|
||||
},
|
||||
{ value: "custom-api-key", label: "Custom Provider" },
|
||||
];
|
||||
|
||||
function resolveDynamicProviderCliChoices(params?: {
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
|
|
@ -331,20 +25,11 @@ export function formatAuthChoiceChoicesForCli(params?: {
|
|||
workspaceDir?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}): string {
|
||||
const includeSkip = params?.includeSkip ?? true;
|
||||
const includeLegacyAliases = params?.includeLegacyAliases ?? false;
|
||||
const values = [
|
||||
...BASE_AUTH_CHOICE_OPTIONS.map((opt) => opt.value),
|
||||
...formatStaticAuthChoiceChoicesForCli(params).split("|"),
|
||||
...resolveDynamicProviderCliChoices(params),
|
||||
];
|
||||
|
||||
if (includeSkip) {
|
||||
values.push("skip");
|
||||
}
|
||||
if (includeLegacyAliases) {
|
||||
values.push(...AUTH_CHOICE_LEGACY_ALIASES_FOR_CLI);
|
||||
}
|
||||
|
||||
return values.join("|");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue