Files
openclaw/src/commands/auth-choice.apply-helpers.ts
2026-02-22 11:16:30 +00:00

169 lines
5.1 KiB
TypeScript

import { resolveEnvApiKey } from "../agents/model-auth.js";
import type { WizardPrompter } from "../wizard/prompts.js";
import { formatApiKeyPreview } from "./auth-choice.api-key.js";
import type { ApplyAuthChoiceParams } from "./auth-choice.apply.js";
import { applyDefaultModelChoice } from "./auth-choice.default-model.js";
export function createAuthChoiceAgentModelNoter(
params: ApplyAuthChoiceParams,
): (model: string) => Promise<void> {
return async (model: string) => {
if (!params.agentId) {
return;
}
await params.prompter.note(
`Default model set to ${model} for agent "${params.agentId}".`,
"Model configured",
);
};
}
export interface ApplyAuthChoiceModelState {
config: ApplyAuthChoiceParams["config"];
agentModelOverride: string | undefined;
}
export function createAuthChoiceModelStateBridge(bindings: {
getConfig: () => ApplyAuthChoiceParams["config"];
setConfig: (config: ApplyAuthChoiceParams["config"]) => void;
getAgentModelOverride: () => string | undefined;
setAgentModelOverride: (model: string | undefined) => void;
}): ApplyAuthChoiceModelState {
return {
get config() {
return bindings.getConfig();
},
set config(config) {
bindings.setConfig(config);
},
get agentModelOverride() {
return bindings.getAgentModelOverride();
},
set agentModelOverride(model) {
bindings.setAgentModelOverride(model);
},
};
}
export function createAuthChoiceDefaultModelApplier(
params: ApplyAuthChoiceParams,
state: ApplyAuthChoiceModelState,
): (
options: Omit<
Parameters<typeof applyDefaultModelChoice>[0],
"config" | "setDefaultModel" | "noteAgentModel" | "prompter"
>,
) => Promise<void> {
const noteAgentModel = createAuthChoiceAgentModelNoter(params);
return async (options) => {
const applied = await applyDefaultModelChoice({
config: state.config,
setDefaultModel: params.setDefaultModel,
noteAgentModel,
prompter: params.prompter,
...options,
});
state.config = applied.config;
state.agentModelOverride = applied.agentModelOverride ?? state.agentModelOverride;
};
}
export function normalizeTokenProviderInput(
tokenProvider: string | null | undefined,
): string | undefined {
const normalized = String(tokenProvider ?? "")
.trim()
.toLowerCase();
return normalized || undefined;
}
export async function maybeApplyApiKeyFromOption(params: {
token: string | undefined;
tokenProvider: string | undefined;
expectedProviders: string[];
normalize: (value: string) => string;
setCredential: (apiKey: string) => Promise<void>;
}): Promise<string | undefined> {
const tokenProvider = normalizeTokenProviderInput(params.tokenProvider);
const expectedProviders = params.expectedProviders
.map((provider) => normalizeTokenProviderInput(provider))
.filter((provider): provider is string => Boolean(provider));
if (!params.token || !tokenProvider || !expectedProviders.includes(tokenProvider)) {
return undefined;
}
const apiKey = params.normalize(params.token);
await params.setCredential(apiKey);
return apiKey;
}
export async function ensureApiKeyFromOptionEnvOrPrompt(params: {
token: string | undefined;
tokenProvider: string | undefined;
expectedProviders: string[];
provider: string;
envLabel: string;
promptMessage: string;
normalize: (value: string) => string;
validate: (value: string) => string | undefined;
prompter: WizardPrompter;
setCredential: (apiKey: string) => Promise<void>;
noteMessage?: string;
noteTitle?: string;
}): Promise<string> {
const optionApiKey = await maybeApplyApiKeyFromOption({
token: params.token,
tokenProvider: params.tokenProvider,
expectedProviders: params.expectedProviders,
normalize: params.normalize,
setCredential: params.setCredential,
});
if (optionApiKey) {
return optionApiKey;
}
if (params.noteMessage) {
await params.prompter.note(params.noteMessage, params.noteTitle);
}
return await ensureApiKeyFromEnvOrPrompt({
provider: params.provider,
envLabel: params.envLabel,
promptMessage: params.promptMessage,
normalize: params.normalize,
validate: params.validate,
prompter: params.prompter,
setCredential: params.setCredential,
});
}
export async function ensureApiKeyFromEnvOrPrompt(params: {
provider: string;
envLabel: string;
promptMessage: string;
normalize: (value: string) => string;
validate: (value: string) => string | undefined;
prompter: WizardPrompter;
setCredential: (apiKey: string) => Promise<void>;
}): Promise<string> {
const envKey = resolveEnvApiKey(params.provider);
if (envKey) {
const useExisting = await params.prompter.confirm({
message: `Use existing ${params.envLabel} (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true,
});
if (useExisting) {
await params.setCredential(envKey.apiKey);
return envKey.apiKey;
}
}
const key = await params.prompter.text({
message: params.promptMessage,
validate: params.validate,
});
const apiKey = params.normalize(String(key ?? ""));
await params.setCredential(apiKey);
return apiKey;
}