fix: support direct token and provider in auth apply commands (#1485)

This commit is contained in:
Ian Hildebrand
2026-01-23 01:27:52 -06:00
committed by GitHub
parent 60a60779d7
commit ff78e9a564
5 changed files with 140 additions and 34 deletions

View File

@@ -198,10 +198,20 @@ export async function applyAuthChoiceAnthropic(
}
if (params.authChoice === "apiKey") {
if (params.opts?.tokenProvider && params.opts.tokenProvider !== "anthropic") {
return null;
}
let nextConfig = params.config;
let hasCredential = false;
const envKey = process.env.ANTHROPIC_API_KEY?.trim();
if (envKey) {
if (params.opts?.token) {
await setAnthropicApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
if (!hasCredential && envKey) {
const useExisting = await params.prompter.confirm({
message: `Use existing ANTHROPIC_API_KEY (env, ${formatApiKeyPreview(envKey)})?`,
initialValue: true,

View File

@@ -56,7 +56,33 @@ export async function applyAuthChoiceApiProviders(
);
};
if (params.authChoice === "openrouter-api-key") {
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") {
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 === "synthetic") {
authChoice = "synthetic-api-key";
} else if (params.opts.tokenProvider === "opencode") {
authChoice = "opencode-zen";
}
}
if (authChoice === "openrouter-api-key") {
const store = ensureAuthProfileStore(params.agentDir, {
allowKeychainPrompt: false,
});
@@ -82,6 +108,11 @@ export async function applyAuthChoiceApiProviders(
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) {
@@ -129,8 +160,18 @@ export async function applyAuthChoiceApiProviders(
return { config: nextConfig, agentModelOverride };
}
if (params.authChoice === "ai-gateway-api-key") {
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({
@@ -171,8 +212,14 @@ export async function applyAuthChoiceApiProviders(
return { config: nextConfig, agentModelOverride };
}
if (params.authChoice === "moonshot-api-key") {
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({
@@ -212,15 +259,22 @@ export async function applyAuthChoiceApiProviders(
return { config: nextConfig, agentModelOverride };
}
if (params.authChoice === "kimi-code-api-key") {
await params.prompter.note(
[
"Kimi Code uses a dedicated endpoint and API key.",
"Get your API key at: https://www.kimi.com/code/en",
].join("\n"),
"Kimi Code",
);
if (authChoice === "kimi-code-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "kimi-code") {
await setKimiCodeApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
if (!hasCredential) {
await params.prompter.note(
[
"Kimi Code uses a dedicated endpoint and API key.",
"Get your API key at: https://www.kimi.com/code/en",
].join("\n"),
"Kimi Code",
);
}
const envKey = resolveEnvApiKey("kimi-code");
if (envKey) {
const useExisting = await params.prompter.confirm({
@@ -261,8 +315,14 @@ export async function applyAuthChoiceApiProviders(
return { config: nextConfig, agentModelOverride };
}
if (params.authChoice === "gemini-api-key") {
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({
@@ -302,8 +362,14 @@ export async function applyAuthChoiceApiProviders(
return { config: nextConfig, agentModelOverride };
}
if (params.authChoice === "zai-api-key") {
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({
@@ -359,12 +425,16 @@ export async function applyAuthChoiceApiProviders(
return { config: nextConfig, agentModelOverride };
}
if (params.authChoice === "synthetic-api-key") {
const key = await params.prompter.text({
message: "Enter Synthetic API key",
validate: (value) => (value?.trim() ? undefined : "Required"),
});
await setSyntheticApiKey(String(key).trim(), params.agentDir);
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",
@@ -387,16 +457,23 @@ export async function applyAuthChoiceApiProviders(
return { config: nextConfig, agentModelOverride };
}
if (params.authChoice === "opencode-zen") {
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",
);
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({

View File

@@ -20,7 +20,12 @@ import {
export async function applyAuthChoiceOpenAI(
params: ApplyAuthChoiceParams,
): Promise<ApplyAuthChoiceResult | null> {
if (params.authChoice === "openai-api-key") {
let authChoice = params.authChoice;
if (authChoice === "apiKey" && params.opts?.tokenProvider === "openai") {
authChoice = "openai-api-key";
}
if (authChoice === "openai-api-key") {
const envKey = resolveEnvApiKey("openai");
if (envKey) {
const useExisting = await params.prompter.confirm({
@@ -43,10 +48,16 @@ export async function applyAuthChoiceOpenAI(
}
}
const key = await params.prompter.text({
message: "Enter OpenAI API key",
validate: validateApiKeyInput,
});
let key: string | undefined;
if (params.opts?.token && params.opts?.tokenProvider === "openai") {
key = params.opts.token;
} else {
key = await params.prompter.text({
message: "Enter OpenAI API key",
validate: validateApiKeyInput,
});
}
const trimmed = normalizeApiKeyInput(String(key));
const result = upsertSharedEnvVar({
key: "OPENAI_API_KEY",

View File

@@ -21,6 +21,10 @@ export type ApplyAuthChoiceParams = {
agentDir?: string;
setDefaultModel: boolean;
agentId?: string;
opts?: {
tokenProvider?: string;
token?: string;
};
};
export type ApplyAuthChoiceResult = {

View File

@@ -356,6 +356,10 @@ export async function runOnboardingWizard(
prompter,
runtime,
setDefaultModel: true,
opts: {
tokenProvider: opts.tokenProvider,
token: opts.authChoice === "apiKey" && opts.token ? opts.token : undefined,
},
});
nextConfig = authResult.config;