fix(litellm): honor CLI flags during onboarding
Add support for --litellm-api-key, --litellm-base-url, and --litellm-model CLI flags to enable non-interactive/automation use cases for LiteLLM provider onboarding. Co-Authored-By: Claude (claude-opus-4-5) <noreply@anthropic.com>
This commit is contained in:
parent
efd827b526
commit
f30e9c466f
@ -588,7 +588,12 @@ export async function applyAuthChoiceApiProviders(
|
|||||||
let hasCredential = false;
|
let hasCredential = false;
|
||||||
let apiKey: string | undefined;
|
let apiKey: string | undefined;
|
||||||
|
|
||||||
// Check for pre-provided credentials via CLI options
|
// Check for pre-provided API key via CLI options (--litellm-api-key or --token with --token-provider litellm)
|
||||||
|
if (!hasCredential && params.opts?.litellmApiKey) {
|
||||||
|
apiKey = normalizeApiKeyInput(params.opts.litellmApiKey);
|
||||||
|
await setLitellmApiKey(apiKey, params.agentDir);
|
||||||
|
hasCredential = true;
|
||||||
|
}
|
||||||
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "litellm") {
|
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "litellm") {
|
||||||
apiKey = normalizeApiKeyInput(params.opts.token);
|
apiKey = normalizeApiKeyInput(params.opts.token);
|
||||||
await setLitellmApiKey(apiKey, params.agentDir);
|
await setLitellmApiKey(apiKey, params.agentDir);
|
||||||
@ -610,7 +615,7 @@ export async function applyAuthChoiceApiProviders(
|
|||||||
|
|
||||||
// Check for existing env key
|
// Check for existing env key
|
||||||
const envKey = resolveEnvApiKey("litellm");
|
const envKey = resolveEnvApiKey("litellm");
|
||||||
if (envKey) {
|
if (!hasCredential && envKey) {
|
||||||
const useExisting = await params.prompter.confirm({
|
const useExisting = await params.prompter.confirm({
|
||||||
message: `Use existing LITELLM_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
message: `Use existing LITELLM_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
||||||
initialValue: true,
|
initialValue: true,
|
||||||
@ -631,24 +636,28 @@ export async function applyAuthChoiceApiProviders(
|
|||||||
await setLitellmApiKey(apiKey, params.agentDir);
|
await setLitellmApiKey(apiKey, params.agentDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prompt for base URL
|
// Check for pre-provided base URL via CLI option (--litellm-base-url)
|
||||||
const defaultBaseUrl = process.env.LITELLM_BASE_URL ?? "http://localhost:4000";
|
let normalizedBaseUrl: string;
|
||||||
const baseUrl = await params.prompter.text({
|
if (params.opts?.litellmBaseUrl) {
|
||||||
message: "Enter LiteLLM base URL",
|
normalizedBaseUrl = params.opts.litellmBaseUrl.trim();
|
||||||
initialValue: defaultBaseUrl,
|
} else {
|
||||||
placeholder: defaultBaseUrl,
|
const defaultBaseUrl = process.env.LITELLM_BASE_URL ?? "http://localhost:4000";
|
||||||
validate: (value) => {
|
const baseUrl = await params.prompter.text({
|
||||||
if (!value?.trim()) return "Base URL is required";
|
message: "Enter LiteLLM base URL",
|
||||||
try {
|
initialValue: defaultBaseUrl,
|
||||||
new URL(value);
|
placeholder: defaultBaseUrl,
|
||||||
return undefined;
|
validate: (value) => {
|
||||||
} catch {
|
if (!value?.trim()) return "Base URL is required";
|
||||||
return "Invalid URL format";
|
try {
|
||||||
}
|
new URL(value);
|
||||||
},
|
return undefined;
|
||||||
});
|
} catch {
|
||||||
|
return "Invalid URL format";
|
||||||
const normalizedBaseUrl = String(baseUrl).trim();
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
normalizedBaseUrl = String(baseUrl).trim();
|
||||||
|
}
|
||||||
|
|
||||||
// Try to fetch available models from LiteLLM
|
// Try to fetch available models from LiteLLM
|
||||||
type LitellmModelInfo = { id: string; maxInputTokens?: number; maxOutputTokens?: number };
|
type LitellmModelInfo = { id: string; maxInputTokens?: number; maxOutputTokens?: number };
|
||||||
@ -722,7 +731,18 @@ export async function applyAuthChoiceApiProviders(
|
|||||||
let contextWindow: number | undefined;
|
let contextWindow: number | undefined;
|
||||||
let maxTokens: number | undefined;
|
let maxTokens: number | undefined;
|
||||||
|
|
||||||
if (availableModels.length > 0) {
|
// Check for pre-provided model via CLI option (--litellm-model)
|
||||||
|
if (params.opts?.litellmModel) {
|
||||||
|
normalizedModelId = params.opts.litellmModel.trim();
|
||||||
|
// Try to get context info from model info map
|
||||||
|
const modelInfo = availableModels.find((m) => m.id === normalizedModelId);
|
||||||
|
if (modelInfo?.maxInputTokens) {
|
||||||
|
contextWindow = modelInfo.maxInputTokens;
|
||||||
|
}
|
||||||
|
if (modelInfo?.maxOutputTokens) {
|
||||||
|
maxTokens = modelInfo.maxOutputTokens;
|
||||||
|
}
|
||||||
|
} else if (availableModels.length > 0) {
|
||||||
// Let user select from available models
|
// Let user select from available models
|
||||||
type SelectOption = { value: string; label: string; hint?: string };
|
type SelectOption = { value: string; label: string; hint?: string };
|
||||||
const modelOptions: SelectOption[] = availableModels.map((m) => ({
|
const modelOptions: SelectOption[] = availableModels.map((m) => ({
|
||||||
@ -765,8 +785,8 @@ export async function applyAuthChoiceApiProviders(
|
|||||||
normalizedModelId = String(modelId).trim();
|
normalizedModelId = String(modelId).trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If context window wasn't auto-detected, prompt for it
|
// If context window wasn't auto-detected, prompt for it (skip in non-interactive mode)
|
||||||
if (!contextWindow) {
|
if (!contextWindow && !params.opts?.nonInteractive) {
|
||||||
const contextInput = await params.prompter.text({
|
const contextInput = await params.prompter.text({
|
||||||
message: "Enter context window size (tokens)",
|
message: "Enter context window size (tokens)",
|
||||||
initialValue: "128000",
|
initialValue: "128000",
|
||||||
|
|||||||
@ -24,6 +24,12 @@ export type ApplyAuthChoiceParams = {
|
|||||||
opts?: {
|
opts?: {
|
||||||
tokenProvider?: string;
|
tokenProvider?: string;
|
||||||
token?: string;
|
token?: string;
|
||||||
|
// LiteLLM-specific options
|
||||||
|
litellmApiKey?: string;
|
||||||
|
litellmBaseUrl?: string;
|
||||||
|
litellmModel?: string;
|
||||||
|
// Non-interactive mode flag
|
||||||
|
nonInteractive?: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -417,7 +417,7 @@ export function applyVeniceConfig(cfg: MoltbotConfig): MoltbotConfig {
|
|||||||
* are user-configurable.
|
* are user-configurable.
|
||||||
*/
|
*/
|
||||||
export function applyLitellmProviderConfig(
|
export function applyLitellmProviderConfig(
|
||||||
cfg: ClawdbotConfig,
|
cfg: MoltbotConfig,
|
||||||
params: {
|
params: {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
modelId: string;
|
modelId: string;
|
||||||
@ -425,7 +425,7 @@ export function applyLitellmProviderConfig(
|
|||||||
contextWindow?: number;
|
contextWindow?: number;
|
||||||
maxTokens?: number;
|
maxTokens?: number;
|
||||||
},
|
},
|
||||||
): ClawdbotConfig {
|
): MoltbotConfig {
|
||||||
const modelRef = `litellm/${params.modelId}`;
|
const modelRef = `litellm/${params.modelId}`;
|
||||||
const models = { ...cfg.agents?.defaults?.models };
|
const models = { ...cfg.agents?.defaults?.models };
|
||||||
models[modelRef] = {
|
models[modelRef] = {
|
||||||
@ -485,7 +485,7 @@ export function applyLitellmProviderConfig(
|
|||||||
* Use this when LiteLLM is the primary provider choice during onboarding.
|
* Use this when LiteLLM is the primary provider choice during onboarding.
|
||||||
*/
|
*/
|
||||||
export function applyLitellmConfig(
|
export function applyLitellmConfig(
|
||||||
cfg: ClawdbotConfig,
|
cfg: MoltbotConfig,
|
||||||
params: {
|
params: {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
modelId: string;
|
modelId: string;
|
||||||
@ -493,7 +493,7 @@ export function applyLitellmConfig(
|
|||||||
contextWindow?: number;
|
contextWindow?: number;
|
||||||
maxTokens?: number;
|
maxTokens?: number;
|
||||||
},
|
},
|
||||||
): ClawdbotConfig {
|
): MoltbotConfig {
|
||||||
const next = applyLitellmProviderConfig(cfg, params);
|
const next = applyLitellmProviderConfig(cfg, params);
|
||||||
const modelRef = `litellm/${params.modelId}`;
|
const modelRef = `litellm/${params.modelId}`;
|
||||||
const existingModel = next.agents?.defaults?.model;
|
const existingModel = next.agents?.defaults?.model;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user