refactor(onboard): unify auth-choice catalog for CLI help

This commit is contained in:
Peter Steinberger
2026-02-14 05:51:01 +01:00
parent fdda261478
commit eab9dc538a
3 changed files with 196 additions and 139 deletions

View File

@@ -7,6 +7,7 @@ import type {
NodeManagerChoice,
TailscaleMode,
} from "../../commands/onboard-types.js";
import { formatAuthChoiceChoicesForCli } from "../../commands/auth-choice-options.js";
import { onboardCommand } from "../../commands/onboard.js";
import { defaultRuntime } from "../../runtime.js";
import { formatDocsLink } from "../../terminal/links.js";
@@ -37,6 +38,11 @@ function resolveInstallDaemonFlag(
return undefined;
}
const AUTH_CHOICE_HELP = formatAuthChoiceChoicesForCli({
includeLegacyAliases: true,
includeSkip: true,
});
export function registerOnboardCommand(program: Command) {
program
.command("onboard")
@@ -56,11 +62,7 @@ export function registerOnboardCommand(program: Command) {
)
.option("--flow <flow>", "Wizard flow: quickstart|advanced|manual")
.option("--mode <mode>", "Wizard mode: local|remote")
.option(
"--auth-choice <choice>",
"Auth: setup-token|token|chutes|openai-codex|openai-api-key|xai-api-key|qianfan-api-key|openrouter-api-key|litellm-api-key|ai-gateway-api-key|cloudflare-ai-gateway-api-key|moonshot-api-key|moonshot-api-key-cn|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|zai-coding-global|zai-coding-cn|zai-global|zai-cn|xiaomi-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|custom-api-key|skip|together-api-key|huggingface-api-key",
"Auth: setup-token|token|chutes|vllm|openai-codex|openai-api-key|xai-api-key|qianfan-api-key|openrouter-api-key|litellm-api-key|ai-gateway-api-key|cloudflare-ai-gateway-api-key|moonshot-api-key|moonshot-api-key-cn|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|zai-coding-global|zai-coding-cn|zai-global|zai-cn|xiaomi-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|custom-api-key|skip|together-api-key|huggingface-api-key",
)
.option("--auth-choice <choice>", `Auth: ${AUTH_CHOICE_HELP}`)
.option(
"--token-provider <id>",
"Token provider id (non-interactive; used with --auth-choice token)",

View File

@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import type { AuthProfileStore } from "../agents/auth-profiles.js";
import { buildAuthChoiceOptions } from "./auth-choice-options.js";
import { buildAuthChoiceOptions, formatAuthChoiceChoicesForCli } from "./auth-choice-options.js";
describe("buildAuthChoiceOptions", () => {
it("includes GitHub Copilot", () => {
@@ -144,4 +144,32 @@ describe("buildAuthChoiceOptions", () => {
expect(options.some((opt) => opt.value === "vllm")).toBe(true);
});
it("builds cli help choices from the same catalog", () => {
const store: AuthProfileStore = { version: 1, profiles: {} };
const options = buildAuthChoiceOptions({
store,
includeSkip: true,
});
const cliChoices = formatAuthChoiceChoicesForCli({
includeLegacyAliases: false,
includeSkip: true,
}).split("|");
for (const option of options) {
expect(cliChoices).toContain(option.value);
}
});
it("can include legacy aliases in cli help choices", () => {
const cliChoices = formatAuthChoiceChoicesForCli({
includeLegacyAliases: true,
includeSkip: true,
}).split("|");
expect(cliChoices).toContain("setup-token");
expect(cliChoices).toContain("oauth");
expect(cliChoices).toContain("claude-cli");
expect(cliChoices).toContain("codex-cli");
});
});

View File

@@ -155,144 +155,171 @@ const AUTH_CHOICE_GROUP_DEFS: {
},
];
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)" },
{
value: "vllm",
label: "vLLM (custom URL + model)",
hint: "Local/self-hosted OpenAI-compatible server",
},
{ value: "openai-api-key", label: "OpenAI API key" },
{ value: "xai-api-key", label: "xAI (Grok) API key" },
{
value: "qianfan-api-key",
label: "Qianfan API key",
},
{ value: "openrouter-api-key", label: "OpenRouter API key" },
{
value: "litellm-api-key",
label: "LiteLLM API key",
hint: "Unified gateway for 100+ LLM providers",
},
{
value: "ai-gateway-api-key",
label: "Vercel AI Gateway API key",
},
{
value: "cloudflare-ai-gateway-api-key",
label: "Cloudflare AI Gateway",
hint: "Account ID + Gateway ID + API key",
},
{
value: "moonshot-api-key",
label: "Kimi API key (.ai)",
},
{
value: "moonshot-api-key-cn",
label: "Kimi API key (.cn)",
},
{
value: "kimi-code-api-key",
label: "Kimi Code API key (subscription)",
},
{ value: "synthetic-api-key", label: "Synthetic API key" },
{
value: "venice-api-key",
label: "Venice AI API key",
hint: "Privacy-focused inference (uncensored models)",
},
{
value: "together-api-key",
label: "Together AI API key",
hint: "Access to Llama, DeepSeek, Qwen, and more open models",
},
{
value: "huggingface-api-key",
label: "Hugging Face API key (HF token)",
hint: "Inference Providers — OpenAI-compatible chat",
},
{
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-antigravity",
label: "Google Antigravity OAuth",
hint: "Uses the bundled Antigravity auth plugin",
},
{
value: "google-gemini-cli",
label: "Google Gemini CLI OAuth",
hint: "Uses the bundled Gemini CLI auth plugin",
},
{ 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-portal",
label: "MiniMax OAuth",
hint: "Oauth plugin for MiniMax",
},
{ 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 (multi-model proxy)",
hint: "Claude, GPT, Gemini via opencode.ai/zen",
},
{ value: "minimax-api", label: "MiniMax M2.5" },
{
value: "minimax-api-lightning",
label: "MiniMax M2.5 Lightning",
hint: "Faster, higher output cost",
},
{ value: "custom-api-key", label: "Custom Provider" },
];
const LEGACY_AUTH_CHOICE_ALIASES: ReadonlyArray<AuthChoice> = [
"setup-token",
"oauth",
"claude-cli",
"codex-cli",
"minimax-cloud",
"minimax",
];
export function formatAuthChoiceChoicesForCli(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(...LEGACY_AUTH_CHOICE_ALIASES);
}
return values.join("|");
}
export function buildAuthChoiceOptions(params: {
store: AuthProfileStore;
includeSkip: boolean;
}): AuthChoiceOption[] {
void params.store;
const options: AuthChoiceOption[] = [];
options.push({
value: "token",
label: "Anthropic token (paste setup-token)",
hint: "run `claude setup-token` elsewhere, then paste the token here",
});
options.push({
value: "openai-codex",
label: "OpenAI Codex (ChatGPT OAuth)",
});
options.push({ value: "chutes", label: "Chutes (OAuth)" });
options.push({
value: "vllm",
label: "vLLM (custom URL + model)",
hint: "Local/self-hosted OpenAI-compatible server",
});
options.push({ value: "openai-api-key", label: "OpenAI API key" });
options.push({ value: "xai-api-key", label: "xAI (Grok) API key" });
options.push({
value: "qianfan-api-key",
label: "Qianfan API key",
});
options.push({ value: "openrouter-api-key", label: "OpenRouter API key" });
options.push({
value: "litellm-api-key",
label: "LiteLLM API key",
hint: "Unified gateway for 100+ LLM providers",
});
options.push({
value: "ai-gateway-api-key",
label: "Vercel AI Gateway API key",
});
options.push({
value: "cloudflare-ai-gateway-api-key",
label: "Cloudflare AI Gateway",
hint: "Account ID + Gateway ID + API key",
});
options.push({
value: "moonshot-api-key",
label: "Kimi API key (.ai)",
});
options.push({
value: "moonshot-api-key-cn",
label: "Kimi API key (.cn)",
});
options.push({
value: "kimi-code-api-key",
label: "Kimi Code API key (subscription)",
});
options.push({ value: "synthetic-api-key", label: "Synthetic API key" });
options.push({
value: "venice-api-key",
label: "Venice AI API key",
hint: "Privacy-focused inference (uncensored models)",
});
options.push({
value: "together-api-key",
label: "Together AI API key",
hint: "Access to Llama, DeepSeek, Qwen, and more open models",
});
options.push({
value: "huggingface-api-key",
label: "Hugging Face API key (HF token)",
hint: "Inference Providers — OpenAI-compatible chat",
});
options.push({
value: "github-copilot",
label: "GitHub Copilot (GitHub device login)",
hint: "Uses GitHub device flow",
});
options.push({ value: "gemini-api-key", label: "Google Gemini API key" });
options.push({
value: "google-antigravity",
label: "Google Antigravity OAuth",
hint: "Uses the bundled Antigravity auth plugin",
});
options.push({
value: "google-gemini-cli",
label: "Google Gemini CLI OAuth",
hint: "Uses the bundled Gemini CLI auth plugin",
});
options.push({ value: "zai-api-key", label: "Z.AI API key" });
options.push({
value: "zai-coding-global",
label: "Coding-Plan-Global",
hint: "GLM Coding Plan Global (api.z.ai)",
});
options.push({
value: "zai-coding-cn",
label: "Coding-Plan-CN",
hint: "GLM Coding Plan CN (open.bigmodel.cn)",
});
options.push({
value: "zai-global",
label: "Global",
hint: "Z.AI Global (api.z.ai)",
});
options.push({
value: "zai-cn",
label: "CN",
hint: "Z.AI CN (open.bigmodel.cn)",
});
options.push({
value: "xiaomi-api-key",
label: "Xiaomi API key",
});
options.push({
value: "minimax-portal",
label: "MiniMax OAuth",
hint: "Oauth plugin for MiniMax",
});
options.push({ value: "qwen-portal", label: "Qwen OAuth" });
options.push({
value: "copilot-proxy",
label: "Copilot Proxy (local)",
hint: "Local proxy for VS Code Copilot models",
});
options.push({ value: "apiKey", label: "Anthropic API key" });
// Token flow is currently Anthropic-only; use CLI for advanced providers.
options.push({
value: "opencode-zen",
label: "OpenCode Zen (multi-model proxy)",
hint: "Claude, GPT, Gemini via opencode.ai/zen",
});
options.push({ value: "minimax-api", label: "MiniMax M2.5" });
options.push({
value: "minimax-api-lightning",
label: "MiniMax M2.5 Lightning",
hint: "Faster, higher output cost",
});
options.push({ value: "custom-api-key", label: "Custom Provider" });
const options: AuthChoiceOption[] = [...BASE_AUTH_CHOICE_OPTIONS];
if (params.includeSkip) {
options.push({ value: "skip", label: "Skip for now" });