mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 19:21:39 +00:00
refactor(onboard): unify auth-choice aliases and provider flags
This commit is contained in:
@@ -8,6 +8,7 @@ import type {
|
|||||||
TailscaleMode,
|
TailscaleMode,
|
||||||
} from "../../commands/onboard-types.js";
|
} from "../../commands/onboard-types.js";
|
||||||
import { formatAuthChoiceChoicesForCli } from "../../commands/auth-choice-options.js";
|
import { formatAuthChoiceChoicesForCli } from "../../commands/auth-choice-options.js";
|
||||||
|
import { ONBOARD_PROVIDER_AUTH_FLAGS } from "../../commands/onboard-provider-auth-flags.js";
|
||||||
import { onboardCommand } from "../../commands/onboard.js";
|
import { onboardCommand } from "../../commands/onboard.js";
|
||||||
import { defaultRuntime } from "../../runtime.js";
|
import { defaultRuntime } from "../../runtime.js";
|
||||||
import { formatDocsLink } from "../../terminal/links.js";
|
import { formatDocsLink } from "../../terminal/links.js";
|
||||||
@@ -44,7 +45,7 @@ const AUTH_CHOICE_HELP = formatAuthChoiceChoicesForCli({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export function registerOnboardCommand(program: Command) {
|
export function registerOnboardCommand(program: Command) {
|
||||||
program
|
const command = program
|
||||||
.command("onboard")
|
.command("onboard")
|
||||||
.description("Interactive wizard to set up the gateway, workspace, and skills")
|
.description("Interactive wizard to set up the gateway, workspace, and skills")
|
||||||
.addHelpText(
|
.addHelpText(
|
||||||
@@ -73,27 +74,14 @@ export function registerOnboardCommand(program: Command) {
|
|||||||
"Auth profile id (non-interactive; default: <provider>:manual)",
|
"Auth profile id (non-interactive; default: <provider>:manual)",
|
||||||
)
|
)
|
||||||
.option("--token-expires-in <duration>", "Optional token expiry duration (e.g. 365d, 12h)")
|
.option("--token-expires-in <duration>", "Optional token expiry duration (e.g. 365d, 12h)")
|
||||||
.option("--anthropic-api-key <key>", "Anthropic API key")
|
|
||||||
.option("--openai-api-key <key>", "OpenAI API key")
|
|
||||||
.option("--openrouter-api-key <key>", "OpenRouter API key")
|
|
||||||
.option("--ai-gateway-api-key <key>", "Vercel AI Gateway API key")
|
|
||||||
.option("--cloudflare-ai-gateway-account-id <id>", "Cloudflare Account ID")
|
.option("--cloudflare-ai-gateway-account-id <id>", "Cloudflare Account ID")
|
||||||
.option("--cloudflare-ai-gateway-gateway-id <id>", "Cloudflare AI Gateway ID")
|
.option("--cloudflare-ai-gateway-gateway-id <id>", "Cloudflare AI Gateway ID");
|
||||||
.option("--cloudflare-ai-gateway-api-key <key>", "Cloudflare AI Gateway API key")
|
|
||||||
.option("--moonshot-api-key <key>", "Moonshot API key")
|
for (const providerFlag of ONBOARD_PROVIDER_AUTH_FLAGS) {
|
||||||
.option("--kimi-code-api-key <key>", "Kimi Coding API key")
|
command.option(providerFlag.cliOption, providerFlag.description);
|
||||||
.option("--gemini-api-key <key>", "Gemini API key")
|
}
|
||||||
.option("--zai-api-key <key>", "Z.AI API key")
|
|
||||||
.option("--xiaomi-api-key <key>", "Xiaomi API key")
|
command
|
||||||
.option("--minimax-api-key <key>", "MiniMax API key")
|
|
||||||
.option("--synthetic-api-key <key>", "Synthetic API key")
|
|
||||||
.option("--venice-api-key <key>", "Venice API key")
|
|
||||||
.option("--together-api-key <key>", "Together AI API key")
|
|
||||||
.option("--huggingface-api-key <key>", "Hugging Face API key (HF token)")
|
|
||||||
.option("--opencode-zen-api-key <key>", "OpenCode Zen API key")
|
|
||||||
.option("--xai-api-key <key>", "xAI API key")
|
|
||||||
.option("--litellm-api-key <key>", "LiteLLM API key")
|
|
||||||
.option("--qianfan-api-key <key>", "QIANFAN API key")
|
|
||||||
.option("--custom-base-url <url>", "Custom provider base URL")
|
.option("--custom-base-url <url>", "Custom provider base URL")
|
||||||
.option("--custom-api-key <key>", "Custom provider API key (optional)")
|
.option("--custom-api-key <key>", "Custom provider API key (optional)")
|
||||||
.option("--custom-model-id <id>", "Custom provider model ID")
|
.option("--custom-model-id <id>", "Custom provider model ID")
|
||||||
@@ -120,10 +108,11 @@ export function registerOnboardCommand(program: Command) {
|
|||||||
.option("--skip-health", "Skip health check")
|
.option("--skip-health", "Skip health check")
|
||||||
.option("--skip-ui", "Skip Control UI/TUI prompts")
|
.option("--skip-ui", "Skip Control UI/TUI prompts")
|
||||||
.option("--node-manager <name>", "Node manager for skills: npm|pnpm|bun")
|
.option("--node-manager <name>", "Node manager for skills: npm|pnpm|bun")
|
||||||
.option("--json", "Output JSON summary", false)
|
.option("--json", "Output JSON summary", false);
|
||||||
.action(async (opts, command) => {
|
|
||||||
|
command.action(async (opts, commandRuntime) => {
|
||||||
await runCommandWithRuntime(defaultRuntime, async () => {
|
await runCommandWithRuntime(defaultRuntime, async () => {
|
||||||
const installDaemon = resolveInstallDaemonFlag(command, {
|
const installDaemon = resolveInstallDaemonFlag(commandRuntime, {
|
||||||
installDaemon: Boolean(opts.installDaemon),
|
installDaemon: Boolean(opts.installDaemon),
|
||||||
});
|
});
|
||||||
const gatewayPort =
|
const gatewayPort =
|
||||||
|
|||||||
28
src/commands/auth-choice-legacy.ts
Normal file
28
src/commands/auth-choice-legacy.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import type { AuthChoice } from "./onboard-types.js";
|
||||||
|
|
||||||
|
export const AUTH_CHOICE_LEGACY_ALIASES_FOR_CLI: ReadonlyArray<AuthChoice> = [
|
||||||
|
"setup-token",
|
||||||
|
"oauth",
|
||||||
|
"claude-cli",
|
||||||
|
"codex-cli",
|
||||||
|
"minimax-cloud",
|
||||||
|
"minimax",
|
||||||
|
];
|
||||||
|
|
||||||
|
export function normalizeLegacyOnboardAuthChoice(
|
||||||
|
authChoice: AuthChoice | undefined,
|
||||||
|
): AuthChoice | undefined {
|
||||||
|
if (authChoice === "oauth" || authChoice === "claude-cli") {
|
||||||
|
return "setup-token";
|
||||||
|
}
|
||||||
|
if (authChoice === "codex-cli") {
|
||||||
|
return "openai-codex";
|
||||||
|
}
|
||||||
|
return authChoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isDeprecatedAuthChoice(
|
||||||
|
authChoice: AuthChoice | undefined,
|
||||||
|
): authChoice is "claude-cli" | "codex-cli" {
|
||||||
|
return authChoice === "claude-cli" || authChoice === "codex-cli";
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
||||||
import { buildAuthChoiceOptions, formatAuthChoiceChoicesForCli } from "./auth-choice-options.js";
|
import {
|
||||||
|
buildAuthChoiceGroups,
|
||||||
|
buildAuthChoiceOptions,
|
||||||
|
formatAuthChoiceChoicesForCli,
|
||||||
|
} from "./auth-choice-options.js";
|
||||||
|
|
||||||
describe("buildAuthChoiceOptions", () => {
|
describe("buildAuthChoiceOptions", () => {
|
||||||
it("includes GitHub Copilot", () => {
|
it("includes GitHub Copilot", () => {
|
||||||
@@ -172,4 +176,16 @@ describe("buildAuthChoiceOptions", () => {
|
|||||||
expect(cliChoices).toContain("claude-cli");
|
expect(cliChoices).toContain("claude-cli");
|
||||||
expect(cliChoices).toContain("codex-cli");
|
expect(cliChoices).toContain("codex-cli");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("shows Chutes in grouped provider selection", () => {
|
||||||
|
const store: AuthProfileStore = { version: 1, profiles: {} };
|
||||||
|
const { groups } = buildAuthChoiceGroups({
|
||||||
|
store,
|
||||||
|
includeSkip: false,
|
||||||
|
});
|
||||||
|
const chutesGroup = groups.find((group) => group.value === "chutes");
|
||||||
|
|
||||||
|
expect(chutesGroup).toBeDefined();
|
||||||
|
expect(chutesGroup?.options.some((opt) => opt.value === "chutes")).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
||||||
import type { AuthChoice, AuthChoiceGroupId } from "./onboard-types.js";
|
import type { AuthChoice, AuthChoiceGroupId } from "./onboard-types.js";
|
||||||
|
import { AUTH_CHOICE_LEGACY_ALIASES_FOR_CLI } from "./auth-choice-legacy.js";
|
||||||
|
|
||||||
export type { AuthChoiceGroupId };
|
export type { AuthChoiceGroupId };
|
||||||
|
|
||||||
@@ -33,6 +34,12 @@ const AUTH_CHOICE_GROUP_DEFS: {
|
|||||||
hint: "setup-token + API key",
|
hint: "setup-token + API key",
|
||||||
choices: ["token", "apiKey"],
|
choices: ["token", "apiKey"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: "chutes",
|
||||||
|
label: "Chutes",
|
||||||
|
hint: "OAuth",
|
||||||
|
choices: ["chutes"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: "vllm",
|
value: "vllm",
|
||||||
label: "vLLM",
|
label: "vLLM",
|
||||||
@@ -287,15 +294,6 @@ const BASE_AUTH_CHOICE_OPTIONS: ReadonlyArray<AuthChoiceOption> = [
|
|||||||
{ value: "custom-api-key", label: "Custom Provider" },
|
{ 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?: {
|
export function formatAuthChoiceChoicesForCli(params?: {
|
||||||
includeSkip?: boolean;
|
includeSkip?: boolean;
|
||||||
includeLegacyAliases?: boolean;
|
includeLegacyAliases?: boolean;
|
||||||
@@ -308,7 +306,7 @@ export function formatAuthChoiceChoicesForCli(params?: {
|
|||||||
values.push("skip");
|
values.push("skip");
|
||||||
}
|
}
|
||||||
if (includeLegacyAliases) {
|
if (includeLegacyAliases) {
|
||||||
values.push(...LEGACY_AUTH_CHOICE_ALIASES);
|
values.push(...AUTH_CHOICE_LEGACY_ALIASES_FOR_CLI);
|
||||||
}
|
}
|
||||||
|
|
||||||
return values.join("|");
|
return values.join("|");
|
||||||
|
|||||||
@@ -480,6 +480,36 @@ describe("onboard (non-interactive): provider auth", () => {
|
|||||||
});
|
});
|
||||||
}, 60_000);
|
}, 60_000);
|
||||||
|
|
||||||
|
it("infers QIANFAN auth choice from --qianfan-api-key and sets default model", async () => {
|
||||||
|
await withOnboardEnv("openclaw-onboard-qianfan-infer-", async ({ configPath, runtime }) => {
|
||||||
|
await runNonInteractive(
|
||||||
|
{
|
||||||
|
nonInteractive: true,
|
||||||
|
qianfanApiKey: "qianfan-test-key",
|
||||||
|
skipHealth: true,
|
||||||
|
skipChannels: true,
|
||||||
|
skipSkills: true,
|
||||||
|
json: true,
|
||||||
|
},
|
||||||
|
runtime,
|
||||||
|
);
|
||||||
|
|
||||||
|
const cfg = await readJsonFile<{
|
||||||
|
auth?: { profiles?: Record<string, { provider?: string; mode?: string }> };
|
||||||
|
agents?: { defaults?: { model?: { primary?: string } } };
|
||||||
|
}>(configPath);
|
||||||
|
|
||||||
|
expect(cfg.auth?.profiles?.["qianfan:default"]?.provider).toBe("qianfan");
|
||||||
|
expect(cfg.auth?.profiles?.["qianfan:default"]?.mode).toBe("api_key");
|
||||||
|
expect(cfg.agents?.defaults?.model?.primary).toBe("qianfan/deepseek-v3.2");
|
||||||
|
await expectApiKeyProfile({
|
||||||
|
profileId: "qianfan:default",
|
||||||
|
provider: "qianfan",
|
||||||
|
key: "qianfan-test-key",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 60_000);
|
||||||
|
|
||||||
it("configures a custom provider from non-interactive flags", async () => {
|
it("configures a custom provider from non-interactive flags", async () => {
|
||||||
await withOnboardEnv("openclaw-onboard-custom-provider-", async ({ configPath, runtime }) => {
|
await withOnboardEnv("openclaw-onboard-custom-provider-", async ({ configPath, runtime }) => {
|
||||||
await runNonInteractive(
|
await runNonInteractive(
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { AuthChoice, OnboardOptions } from "../../onboard-types.js";
|
import type { AuthChoice, OnboardOptions } from "../../onboard-types.js";
|
||||||
|
import { ONBOARD_PROVIDER_AUTH_FLAGS } from "../../onboard-provider-auth-flags.js";
|
||||||
|
|
||||||
type AuthChoiceFlag = {
|
type AuthChoiceFlag = {
|
||||||
flag: keyof AuthChoiceFlagOptions;
|
optionKey: keyof AuthChoiceFlagOptions;
|
||||||
authChoice: AuthChoice;
|
authChoice: AuthChoice;
|
||||||
label: string;
|
label: string;
|
||||||
};
|
};
|
||||||
@@ -26,36 +27,12 @@ type AuthChoiceFlagOptions = Pick<
|
|||||||
| "opencodeZenApiKey"
|
| "opencodeZenApiKey"
|
||||||
| "xaiApiKey"
|
| "xaiApiKey"
|
||||||
| "litellmApiKey"
|
| "litellmApiKey"
|
||||||
|
| "qianfanApiKey"
|
||||||
| "customBaseUrl"
|
| "customBaseUrl"
|
||||||
| "customModelId"
|
| "customModelId"
|
||||||
| "customApiKey"
|
| "customApiKey"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
const AUTH_CHOICE_FLAG_MAP = [
|
|
||||||
{ flag: "anthropicApiKey", authChoice: "apiKey", label: "--anthropic-api-key" },
|
|
||||||
{ flag: "geminiApiKey", authChoice: "gemini-api-key", label: "--gemini-api-key" },
|
|
||||||
{ flag: "openaiApiKey", authChoice: "openai-api-key", label: "--openai-api-key" },
|
|
||||||
{ flag: "openrouterApiKey", authChoice: "openrouter-api-key", label: "--openrouter-api-key" },
|
|
||||||
{ flag: "aiGatewayApiKey", authChoice: "ai-gateway-api-key", label: "--ai-gateway-api-key" },
|
|
||||||
{
|
|
||||||
flag: "cloudflareAiGatewayApiKey",
|
|
||||||
authChoice: "cloudflare-ai-gateway-api-key",
|
|
||||||
label: "--cloudflare-ai-gateway-api-key",
|
|
||||||
},
|
|
||||||
{ flag: "moonshotApiKey", authChoice: "moonshot-api-key", label: "--moonshot-api-key" },
|
|
||||||
{ flag: "kimiCodeApiKey", authChoice: "kimi-code-api-key", label: "--kimi-code-api-key" },
|
|
||||||
{ flag: "syntheticApiKey", authChoice: "synthetic-api-key", label: "--synthetic-api-key" },
|
|
||||||
{ flag: "veniceApiKey", authChoice: "venice-api-key", label: "--venice-api-key" },
|
|
||||||
{ flag: "togetherApiKey", authChoice: "together-api-key", label: "--together-api-key" },
|
|
||||||
{ flag: "zaiApiKey", authChoice: "zai-api-key", label: "--zai-api-key" },
|
|
||||||
{ flag: "xiaomiApiKey", authChoice: "xiaomi-api-key", label: "--xiaomi-api-key" },
|
|
||||||
{ flag: "xaiApiKey", authChoice: "xai-api-key", label: "--xai-api-key" },
|
|
||||||
{ flag: "minimaxApiKey", authChoice: "minimax-api", label: "--minimax-api-key" },
|
|
||||||
{ flag: "opencodeZenApiKey", authChoice: "opencode-zen", label: "--opencode-zen-api-key" },
|
|
||||||
{ flag: "huggingfaceApiKey", authChoice: "huggingface-api-key", label: "--huggingface-api-key" },
|
|
||||||
{ flag: "litellmApiKey", authChoice: "litellm-api-key", label: "--litellm-api-key" },
|
|
||||||
] satisfies ReadonlyArray<AuthChoiceFlag>;
|
|
||||||
|
|
||||||
export type AuthChoiceInference = {
|
export type AuthChoiceInference = {
|
||||||
choice?: AuthChoice;
|
choice?: AuthChoice;
|
||||||
matches: AuthChoiceFlag[];
|
matches: AuthChoiceFlag[];
|
||||||
@@ -67,9 +44,13 @@ function hasStringValue(value: unknown): boolean {
|
|||||||
|
|
||||||
// Infer auth choice from explicit provider API key flags.
|
// Infer auth choice from explicit provider API key flags.
|
||||||
export function inferAuthChoiceFromFlags(opts: OnboardOptions): AuthChoiceInference {
|
export function inferAuthChoiceFromFlags(opts: OnboardOptions): AuthChoiceInference {
|
||||||
const matches: AuthChoiceFlag[] = AUTH_CHOICE_FLAG_MAP.filter(({ flag }) =>
|
const matches: AuthChoiceFlag[] = ONBOARD_PROVIDER_AUTH_FLAGS.filter(({ optionKey }) =>
|
||||||
hasStringValue(opts[flag]),
|
hasStringValue(opts[optionKey]),
|
||||||
);
|
).map((flag) => ({
|
||||||
|
optionKey: flag.optionKey,
|
||||||
|
authChoice: flag.authChoice,
|
||||||
|
label: flag.cliFlag,
|
||||||
|
}));
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasStringValue(opts.customBaseUrl) ||
|
hasStringValue(opts.customBaseUrl) ||
|
||||||
@@ -77,7 +58,7 @@ export function inferAuthChoiceFromFlags(opts: OnboardOptions): AuthChoiceInfere
|
|||||||
hasStringValue(opts.customApiKey)
|
hasStringValue(opts.customApiKey)
|
||||||
) {
|
) {
|
||||||
matches.push({
|
matches.push({
|
||||||
flag: "customBaseUrl",
|
optionKey: "customBaseUrl",
|
||||||
authChoice: "custom-api-key",
|
authChoice: "custom-api-key",
|
||||||
label: "--custom-base-url/--custom-model-id/--custom-api-key",
|
label: "--custom-base-url/--custom-model-id/--custom-api-key",
|
||||||
});
|
});
|
||||||
|
|||||||
169
src/commands/onboard-provider-auth-flags.ts
Normal file
169
src/commands/onboard-provider-auth-flags.ts
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
import type { AuthChoice, OnboardOptions } from "./onboard-types.js";
|
||||||
|
|
||||||
|
type OnboardProviderAuthOptionKey = keyof Pick<
|
||||||
|
OnboardOptions,
|
||||||
|
| "anthropicApiKey"
|
||||||
|
| "openaiApiKey"
|
||||||
|
| "openrouterApiKey"
|
||||||
|
| "aiGatewayApiKey"
|
||||||
|
| "cloudflareAiGatewayApiKey"
|
||||||
|
| "moonshotApiKey"
|
||||||
|
| "kimiCodeApiKey"
|
||||||
|
| "geminiApiKey"
|
||||||
|
| "zaiApiKey"
|
||||||
|
| "xiaomiApiKey"
|
||||||
|
| "minimaxApiKey"
|
||||||
|
| "syntheticApiKey"
|
||||||
|
| "veniceApiKey"
|
||||||
|
| "togetherApiKey"
|
||||||
|
| "huggingfaceApiKey"
|
||||||
|
| "opencodeZenApiKey"
|
||||||
|
| "xaiApiKey"
|
||||||
|
| "litellmApiKey"
|
||||||
|
| "qianfanApiKey"
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type OnboardProviderAuthFlag = {
|
||||||
|
optionKey: OnboardProviderAuthOptionKey;
|
||||||
|
authChoice: AuthChoice;
|
||||||
|
cliFlag: `--${string}`;
|
||||||
|
cliOption: `--${string} <key>`;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shared source for provider API-key flags used by CLI registration + non-interactive inference.
|
||||||
|
export const ONBOARD_PROVIDER_AUTH_FLAGS: ReadonlyArray<OnboardProviderAuthFlag> = [
|
||||||
|
{
|
||||||
|
optionKey: "anthropicApiKey",
|
||||||
|
authChoice: "apiKey",
|
||||||
|
cliFlag: "--anthropic-api-key",
|
||||||
|
cliOption: "--anthropic-api-key <key>",
|
||||||
|
description: "Anthropic API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "openaiApiKey",
|
||||||
|
authChoice: "openai-api-key",
|
||||||
|
cliFlag: "--openai-api-key",
|
||||||
|
cliOption: "--openai-api-key <key>",
|
||||||
|
description: "OpenAI API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "openrouterApiKey",
|
||||||
|
authChoice: "openrouter-api-key",
|
||||||
|
cliFlag: "--openrouter-api-key",
|
||||||
|
cliOption: "--openrouter-api-key <key>",
|
||||||
|
description: "OpenRouter API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "aiGatewayApiKey",
|
||||||
|
authChoice: "ai-gateway-api-key",
|
||||||
|
cliFlag: "--ai-gateway-api-key",
|
||||||
|
cliOption: "--ai-gateway-api-key <key>",
|
||||||
|
description: "Vercel AI Gateway API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "cloudflareAiGatewayApiKey",
|
||||||
|
authChoice: "cloudflare-ai-gateway-api-key",
|
||||||
|
cliFlag: "--cloudflare-ai-gateway-api-key",
|
||||||
|
cliOption: "--cloudflare-ai-gateway-api-key <key>",
|
||||||
|
description: "Cloudflare AI Gateway API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "moonshotApiKey",
|
||||||
|
authChoice: "moonshot-api-key",
|
||||||
|
cliFlag: "--moonshot-api-key",
|
||||||
|
cliOption: "--moonshot-api-key <key>",
|
||||||
|
description: "Moonshot API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "kimiCodeApiKey",
|
||||||
|
authChoice: "kimi-code-api-key",
|
||||||
|
cliFlag: "--kimi-code-api-key",
|
||||||
|
cliOption: "--kimi-code-api-key <key>",
|
||||||
|
description: "Kimi Coding API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "geminiApiKey",
|
||||||
|
authChoice: "gemini-api-key",
|
||||||
|
cliFlag: "--gemini-api-key",
|
||||||
|
cliOption: "--gemini-api-key <key>",
|
||||||
|
description: "Gemini API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "zaiApiKey",
|
||||||
|
authChoice: "zai-api-key",
|
||||||
|
cliFlag: "--zai-api-key",
|
||||||
|
cliOption: "--zai-api-key <key>",
|
||||||
|
description: "Z.AI API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "xiaomiApiKey",
|
||||||
|
authChoice: "xiaomi-api-key",
|
||||||
|
cliFlag: "--xiaomi-api-key",
|
||||||
|
cliOption: "--xiaomi-api-key <key>",
|
||||||
|
description: "Xiaomi API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "minimaxApiKey",
|
||||||
|
authChoice: "minimax-api",
|
||||||
|
cliFlag: "--minimax-api-key",
|
||||||
|
cliOption: "--minimax-api-key <key>",
|
||||||
|
description: "MiniMax API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "syntheticApiKey",
|
||||||
|
authChoice: "synthetic-api-key",
|
||||||
|
cliFlag: "--synthetic-api-key",
|
||||||
|
cliOption: "--synthetic-api-key <key>",
|
||||||
|
description: "Synthetic API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "veniceApiKey",
|
||||||
|
authChoice: "venice-api-key",
|
||||||
|
cliFlag: "--venice-api-key",
|
||||||
|
cliOption: "--venice-api-key <key>",
|
||||||
|
description: "Venice API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "togetherApiKey",
|
||||||
|
authChoice: "together-api-key",
|
||||||
|
cliFlag: "--together-api-key",
|
||||||
|
cliOption: "--together-api-key <key>",
|
||||||
|
description: "Together AI API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "huggingfaceApiKey",
|
||||||
|
authChoice: "huggingface-api-key",
|
||||||
|
cliFlag: "--huggingface-api-key",
|
||||||
|
cliOption: "--huggingface-api-key <key>",
|
||||||
|
description: "Hugging Face API key (HF token)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "opencodeZenApiKey",
|
||||||
|
authChoice: "opencode-zen",
|
||||||
|
cliFlag: "--opencode-zen-api-key",
|
||||||
|
cliOption: "--opencode-zen-api-key <key>",
|
||||||
|
description: "OpenCode Zen API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "xaiApiKey",
|
||||||
|
authChoice: "xai-api-key",
|
||||||
|
cliFlag: "--xai-api-key",
|
||||||
|
cliOption: "--xai-api-key <key>",
|
||||||
|
description: "xAI API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "litellmApiKey",
|
||||||
|
authChoice: "litellm-api-key",
|
||||||
|
cliFlag: "--litellm-api-key",
|
||||||
|
cliOption: "--litellm-api-key <key>",
|
||||||
|
description: "LiteLLM API key",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
optionKey: "qianfanApiKey",
|
||||||
|
authChoice: "qianfan-api-key",
|
||||||
|
cliFlag: "--qianfan-api-key",
|
||||||
|
cliOption: "--qianfan-api-key <key>",
|
||||||
|
description: "QIANFAN API key",
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -50,6 +50,7 @@ export type AuthChoice =
|
|||||||
export type AuthChoiceGroupId =
|
export type AuthChoiceGroupId =
|
||||||
| "openai"
|
| "openai"
|
||||||
| "anthropic"
|
| "anthropic"
|
||||||
|
| "chutes"
|
||||||
| "vllm"
|
| "vllm"
|
||||||
| "google"
|
| "google"
|
||||||
| "copilot"
|
| "copilot"
|
||||||
|
|||||||
@@ -5,33 +5,29 @@ import { readConfigFileSnapshot } from "../config/config.js";
|
|||||||
import { assertSupportedRuntime } from "../infra/runtime-guard.js";
|
import { assertSupportedRuntime } from "../infra/runtime-guard.js";
|
||||||
import { defaultRuntime } from "../runtime.js";
|
import { defaultRuntime } from "../runtime.js";
|
||||||
import { resolveUserPath } from "../utils.js";
|
import { resolveUserPath } from "../utils.js";
|
||||||
|
import { isDeprecatedAuthChoice, normalizeLegacyOnboardAuthChoice } from "./auth-choice-legacy.js";
|
||||||
import { DEFAULT_WORKSPACE, handleReset } from "./onboard-helpers.js";
|
import { DEFAULT_WORKSPACE, handleReset } from "./onboard-helpers.js";
|
||||||
import { runInteractiveOnboarding } from "./onboard-interactive.js";
|
import { runInteractiveOnboarding } from "./onboard-interactive.js";
|
||||||
import { runNonInteractiveOnboarding } from "./onboard-non-interactive.js";
|
import { runNonInteractiveOnboarding } from "./onboard-non-interactive.js";
|
||||||
|
|
||||||
export async function onboardCommand(opts: OnboardOptions, runtime: RuntimeEnv = defaultRuntime) {
|
export async function onboardCommand(opts: OnboardOptions, runtime: RuntimeEnv = defaultRuntime) {
|
||||||
assertSupportedRuntime(runtime);
|
assertSupportedRuntime(runtime);
|
||||||
const authChoice = opts.authChoice === "oauth" ? ("setup-token" as const) : opts.authChoice;
|
const originalAuthChoice = opts.authChoice;
|
||||||
const normalizedAuthChoice =
|
const normalizedAuthChoice = normalizeLegacyOnboardAuthChoice(originalAuthChoice);
|
||||||
authChoice === "claude-cli"
|
if (opts.nonInteractive && isDeprecatedAuthChoice(originalAuthChoice)) {
|
||||||
? ("setup-token" as const)
|
|
||||||
: authChoice === "codex-cli"
|
|
||||||
? ("openai-codex" as const)
|
|
||||||
: authChoice;
|
|
||||||
if (opts.nonInteractive && (authChoice === "claude-cli" || authChoice === "codex-cli")) {
|
|
||||||
runtime.error(
|
runtime.error(
|
||||||
[
|
[
|
||||||
`Auth choice "${authChoice}" is deprecated.`,
|
`Auth choice "${String(originalAuthChoice)}" is deprecated.`,
|
||||||
'Use "--auth-choice token" (Anthropic setup-token) or "--auth-choice openai-codex".',
|
'Use "--auth-choice token" (Anthropic setup-token) or "--auth-choice openai-codex".',
|
||||||
].join("\n"),
|
].join("\n"),
|
||||||
);
|
);
|
||||||
runtime.exit(1);
|
runtime.exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (authChoice === "claude-cli") {
|
if (originalAuthChoice === "claude-cli") {
|
||||||
runtime.log('Auth choice "claude-cli" is deprecated; using setup-token flow instead.');
|
runtime.log('Auth choice "claude-cli" is deprecated; using setup-token flow instead.');
|
||||||
}
|
}
|
||||||
if (authChoice === "codex-cli") {
|
if (originalAuthChoice === "codex-cli") {
|
||||||
runtime.log('Auth choice "codex-cli" is deprecated; using OpenAI Codex OAuth instead.');
|
runtime.log('Auth choice "codex-cli" is deprecated; using OpenAI Codex OAuth instead.');
|
||||||
}
|
}
|
||||||
const flow = opts.flow === "manual" ? ("advanced" as const) : opts.flow;
|
const flow = opts.flow === "manual" ? ("advanced" as const) : opts.flow;
|
||||||
|
|||||||
Reference in New Issue
Block a user