fix(litellm): handle AUTH_CHOICE_CANCELLED to retry auth selection

- Add retry loops in configure.gateway-auth and agents.commands.add
- Catch AUTH_CHOICE_CANCELLED error and re-prompt for auth method
- Users can now go back to auth method selection when LiteLLM setup fails
- Import AuthChoice type for proper typing

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Charles-Henri ROBICHE 2026-01-29 10:59:30 +01:00
parent d531f7d9a4
commit ce8fd694ae
No known key found for this signature in database
2 changed files with 75 additions and 44 deletions

View File

@ -254,27 +254,41 @@ export async function agentsAddCommand(
const authStore = ensureAuthProfileStore(agentDir, { const authStore = ensureAuthProfileStore(agentDir, {
allowKeychainPrompt: false, allowKeychainPrompt: false,
}); });
const authChoice = await promptAuthChoiceGrouped({
prompter,
store: authStore,
includeSkip: true,
});
const authResult = await applyAuthChoice({ // Loop to allow retrying auth choice if user cancels during configuration
authChoice, while (true) {
config: nextConfig, const authChoice = await promptAuthChoiceGrouped({
prompter, prompter,
runtime, store: authStore,
agentDir, includeSkip: true,
setDefaultModel: false,
agentId,
});
nextConfig = authResult.config;
if (authResult.agentModelOverride) {
nextConfig = applyAgentConfig(nextConfig, {
agentId,
model: authResult.agentModelOverride,
}); });
try {
const authResult = await applyAuthChoice({
authChoice,
config: nextConfig,
prompter,
runtime,
agentDir,
setDefaultModel: false,
agentId,
});
nextConfig = authResult.config;
if (authResult.agentModelOverride) {
nextConfig = applyAgentConfig(nextConfig, {
agentId,
model: authResult.agentModelOverride,
});
}
break; // Success - exit the loop
} catch (error) {
// If user cancelled to go back to auth selection, loop again
if (error instanceof Error && error.message === "AUTH_CHOICE_CANCELLED") {
continue;
}
// Re-throw other errors
throw error;
}
} }
} }

View File

@ -4,6 +4,7 @@ import type { RuntimeEnv } from "../runtime.js";
import type { WizardPrompter } from "../wizard/prompts.js"; import type { WizardPrompter } from "../wizard/prompts.js";
import { applyAuthChoice, resolvePreferredProviderForAuthChoice } from "./auth-choice.js"; import { applyAuthChoice, resolvePreferredProviderForAuthChoice } from "./auth-choice.js";
import { promptAuthChoiceGrouped } from "./auth-choice-prompt.js"; import { promptAuthChoiceGrouped } from "./auth-choice-prompt.js";
import type { AuthChoice } from "./onboard-types.js";
import { import {
applyModelAllowlist, applyModelAllowlist,
applyModelFallbacksFromSelection, applyModelFallbacksFromSelection,
@ -41,34 +42,50 @@ export async function promptAuthConfig(
runtime: RuntimeEnv, runtime: RuntimeEnv,
prompter: WizardPrompter, prompter: WizardPrompter,
): Promise<MoltbotConfig> { ): Promise<MoltbotConfig> {
const authChoice = await promptAuthChoiceGrouped({
prompter,
store: ensureAuthProfileStore(undefined, {
allowKeychainPrompt: false,
}),
includeSkip: true,
});
let next = cfg; let next = cfg;
if (authChoice !== "skip") { let authChoice: AuthChoice;
const applied = await applyAuthChoice({
authChoice, // Loop to allow retrying auth choice if user cancels during configuration
config: next, while (true) {
authChoice = await promptAuthChoiceGrouped({
prompter, prompter,
runtime, store: ensureAuthProfileStore(undefined, {
setDefaultModel: true, allowKeychainPrompt: false,
}),
includeSkip: true,
}); });
next = applied.config;
} else { if (authChoice !== "skip") {
const modelSelection = await promptDefaultModel({ try {
config: next, const applied = await applyAuthChoice({
prompter, authChoice,
allowKeep: true, config: next,
ignoreAllowlist: true, prompter,
preferredProvider: resolvePreferredProviderForAuthChoice(authChoice), runtime,
}); setDefaultModel: true,
if (modelSelection.model) { });
next = applyPrimaryModel(next, modelSelection.model); next = applied.config;
break; // Success - exit the loop
} catch (error) {
// If user cancelled to go back to auth selection, loop again
if (error instanceof Error && error.message === "AUTH_CHOICE_CANCELLED") {
continue;
}
// Re-throw other errors
throw error;
}
} else {
const modelSelection = await promptDefaultModel({
config: next,
prompter,
allowKeep: true,
ignoreAllowlist: true,
preferredProvider: resolvePreferredProviderForAuthChoice(authChoice),
});
if (modelSelection.model) {
next = applyPrimaryModel(next, modelSelection.model);
}
break; // Skip selected - exit the loop
} }
} }