mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 17:18:25 +00:00
169 lines
5.1 KiB
TypeScript
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;
|
|
}
|