Files
openclaw/src/agents/tools/model-config.helpers.ts
2026-03-17 09:23:35 -07:00

88 lines
2.7 KiB
TypeScript

import type { OpenClawConfig } from "../../config/config.js";
import {
resolveAgentModelFallbackValues,
resolveAgentModelPrimaryValue,
} from "../../config/model-input.js";
import type { AgentModelConfig } from "../../config/types.agents-shared.js";
import { ensureAuthProfileStore, listProfilesForProvider } from "../auth-profiles.js";
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../defaults.js";
import { resolveEnvApiKey } from "../model-auth.js";
import { resolveConfiguredModelRef } from "../model-selection.js";
export type ToolModelConfig = { primary?: string; fallbacks?: string[] };
export function hasToolModelConfig(model: ToolModelConfig | undefined): boolean {
return Boolean(
model?.primary?.trim() || (model?.fallbacks ?? []).some((entry) => entry.trim().length > 0),
);
}
export function resolveDefaultModelRef(cfg?: OpenClawConfig): { provider: string; model: string } {
if (cfg) {
const resolved = resolveConfiguredModelRef({
cfg,
defaultProvider: DEFAULT_PROVIDER,
defaultModel: DEFAULT_MODEL,
});
return { provider: resolved.provider, model: resolved.model };
}
return { provider: DEFAULT_PROVIDER, model: DEFAULT_MODEL };
}
export function hasAuthForProvider(params: { provider: string; agentDir?: string }): boolean {
if (resolveEnvApiKey(params.provider)?.apiKey) {
return true;
}
const agentDir = params.agentDir?.trim();
if (!agentDir) {
return false;
}
const store = ensureAuthProfileStore(agentDir, {
allowKeychainPrompt: false,
});
return listProfilesForProvider(store, params.provider).length > 0;
}
export function coerceToolModelConfig(model?: AgentModelConfig): ToolModelConfig {
const primary = resolveAgentModelPrimaryValue(model);
const fallbacks = resolveAgentModelFallbackValues(model);
return {
...(primary?.trim() ? { primary: primary.trim() } : {}),
...(fallbacks.length > 0 ? { fallbacks } : {}),
};
}
export function buildToolModelConfigFromCandidates(params: {
explicit: ToolModelConfig;
agentDir?: string;
candidates: Array<string | null | undefined>;
}): ToolModelConfig | null {
if (hasToolModelConfig(params.explicit)) {
return params.explicit;
}
const deduped: string[] = [];
for (const candidate of params.candidates) {
const trimmed = candidate?.trim();
if (!trimmed || !trimmed.includes("/")) {
continue;
}
const provider = trimmed.slice(0, trimmed.indexOf("/")).trim();
if (!provider || !hasAuthForProvider({ provider, agentDir: params.agentDir })) {
continue;
}
if (!deduped.includes(trimmed)) {
deduped.push(trimmed);
}
}
if (deduped.length === 0) {
return null;
}
return {
primary: deduped[0],
...(deduped.length > 1 ? { fallbacks: deduped.slice(1) } : {}),
};
}