mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 01:40:23 +00:00
refactor(providers): move defaults and error policy into plugins
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "../agents/defaults.js";
|
||||
import { normalizeProviderId, parseModelRef } from "../agents/model-selection.js";
|
||||
import { normalizeProviderId } from "../agents/model-selection.js";
|
||||
import { normalizeProviderSpecificConfig } from "../agents/models-config.providers.policy.js";
|
||||
import { applyProviderConfigDefaultsWithPlugin } from "../plugins/provider-runtime.js";
|
||||
import { DEFAULT_AGENT_MAX_CONCURRENT, DEFAULT_SUBAGENT_MAX_CONCURRENT } from "./agent-limits.js";
|
||||
import { resolveAgentModelPrimaryValue } from "./model-input.js";
|
||||
import {
|
||||
LEGACY_TALK_PROVIDER_ID,
|
||||
normalizeTalkConfig,
|
||||
@@ -16,8 +17,6 @@ type WarnState = { warned: boolean };
|
||||
|
||||
let defaultWarnState: WarnState = { warned: false };
|
||||
|
||||
type AnthropicAuthDefaultsMode = "api_key" | "oauth";
|
||||
|
||||
const DEFAULT_MODEL_ALIASES: Readonly<Record<string, string>> = {
|
||||
// Anthropic (pi-ai catalog uses "latest" ids without date suffix)
|
||||
opus: "anthropic/claude-opus-4-6",
|
||||
@@ -54,16 +53,6 @@ const MISTRAL_SAFE_MAX_TOKENS_BY_MODEL = {
|
||||
type ModelDefinitionLike = Partial<ModelDefinitionConfig> &
|
||||
Pick<ModelDefinitionConfig, "id" | "name">;
|
||||
|
||||
function resolveDefaultProviderApi(
|
||||
providerId: string,
|
||||
providerApi: ModelDefinitionConfig["api"] | undefined,
|
||||
): ModelDefinitionConfig["api"] | undefined {
|
||||
if (providerApi) {
|
||||
return providerApi;
|
||||
}
|
||||
return normalizeProviderId(providerId) === "anthropic" ? "anthropic-messages" : undefined;
|
||||
}
|
||||
|
||||
function isPositiveNumber(value: unknown): value is number {
|
||||
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
||||
}
|
||||
@@ -98,58 +87,6 @@ export function resolveNormalizedProviderModelMaxTokens(params: {
|
||||
return Math.min(safeMaxTokens, params.contextWindow);
|
||||
}
|
||||
|
||||
function resolveAnthropicDefaultAuthMode(cfg: OpenClawConfig): AnthropicAuthDefaultsMode | null {
|
||||
const profiles = cfg.auth?.profiles ?? {};
|
||||
const anthropicProfiles = Object.entries(profiles).filter(
|
||||
([, profile]) => profile?.provider === "anthropic",
|
||||
);
|
||||
|
||||
const order = cfg.auth?.order?.anthropic ?? [];
|
||||
for (const profileId of order) {
|
||||
const entry = profiles[profileId];
|
||||
if (!entry || entry.provider !== "anthropic") {
|
||||
continue;
|
||||
}
|
||||
if (entry.mode === "api_key") {
|
||||
return "api_key";
|
||||
}
|
||||
if (entry.mode === "oauth" || entry.mode === "token") {
|
||||
return "oauth";
|
||||
}
|
||||
}
|
||||
|
||||
const hasApiKey = anthropicProfiles.some(([, profile]) => profile?.mode === "api_key");
|
||||
const hasOauth = anthropicProfiles.some(
|
||||
([, profile]) => profile?.mode === "oauth" || profile?.mode === "token",
|
||||
);
|
||||
if (hasApiKey && !hasOauth) {
|
||||
return "api_key";
|
||||
}
|
||||
if (hasOauth && !hasApiKey) {
|
||||
return "oauth";
|
||||
}
|
||||
|
||||
if (process.env.ANTHROPIC_OAUTH_TOKEN?.trim()) {
|
||||
return "oauth";
|
||||
}
|
||||
if (process.env.ANTHROPIC_API_KEY?.trim()) {
|
||||
return "api_key";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolvePrimaryModelRef(raw?: string): string | null {
|
||||
if (!raw || typeof raw !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
const aliasKey = trimmed.toLowerCase();
|
||||
return DEFAULT_MODEL_ALIASES[aliasKey] ?? trimmed;
|
||||
}
|
||||
|
||||
export type SessionDefaultsOptions = {
|
||||
warn?: (message: string) => void;
|
||||
warnState?: WarnState;
|
||||
@@ -242,15 +179,19 @@ export function applyModelDefaults(cfg: OpenClawConfig): OpenClawConfig {
|
||||
if (providerConfig) {
|
||||
const nextProviders = { ...providerConfig };
|
||||
for (const [providerId, provider] of Object.entries(providerConfig)) {
|
||||
const models = provider.models;
|
||||
const normalizedProvider = normalizeProviderSpecificConfig(providerId, provider);
|
||||
const models = normalizedProvider.models;
|
||||
if (!Array.isArray(models) || models.length === 0) {
|
||||
if (normalizedProvider !== provider) {
|
||||
nextProviders[providerId] = normalizedProvider;
|
||||
mutated = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const providerApi = resolveDefaultProviderApi(providerId, provider.api);
|
||||
let nextProvider = provider;
|
||||
if (providerApi && provider.api !== providerApi) {
|
||||
const providerApi = normalizedProvider.api;
|
||||
let nextProvider = normalizedProvider;
|
||||
if (nextProvider !== provider) {
|
||||
mutated = true;
|
||||
nextProvider = { ...nextProvider, api: providerApi };
|
||||
}
|
||||
let providerMutated = false;
|
||||
const nextModels = models.map((model) => {
|
||||
@@ -434,105 +375,16 @@ export function applyLoggingDefaults(cfg: OpenClawConfig): OpenClawConfig {
|
||||
}
|
||||
|
||||
export function applyContextPruningDefaults(cfg: OpenClawConfig): OpenClawConfig {
|
||||
const defaults = cfg.agents?.defaults;
|
||||
if (!defaults) {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
const authMode = resolveAnthropicDefaultAuthMode(cfg);
|
||||
if (!authMode) {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
let mutated = false;
|
||||
const nextDefaults = { ...defaults };
|
||||
const contextPruning = defaults.contextPruning ?? {};
|
||||
const heartbeat = defaults.heartbeat ?? {};
|
||||
|
||||
if (defaults.contextPruning?.mode === undefined) {
|
||||
nextDefaults.contextPruning = {
|
||||
...contextPruning,
|
||||
mode: "cache-ttl",
|
||||
ttl: defaults.contextPruning?.ttl ?? "1h",
|
||||
};
|
||||
mutated = true;
|
||||
}
|
||||
|
||||
if (defaults.heartbeat?.every === undefined) {
|
||||
nextDefaults.heartbeat = {
|
||||
...heartbeat,
|
||||
every: authMode === "oauth" ? "1h" : "30m",
|
||||
};
|
||||
mutated = true;
|
||||
}
|
||||
|
||||
if (authMode === "api_key") {
|
||||
const nextModels = defaults.models ? { ...defaults.models } : {};
|
||||
let modelsMutated = false;
|
||||
const isAnthropicCacheRetentionTarget = (
|
||||
parsed: { provider: string; model: string } | null | undefined,
|
||||
): parsed is { provider: string; model: string } =>
|
||||
Boolean(
|
||||
parsed &&
|
||||
(parsed.provider === "anthropic" ||
|
||||
(parsed.provider === "amazon-bedrock" &&
|
||||
parsed.model.toLowerCase().includes("anthropic.claude"))),
|
||||
);
|
||||
|
||||
for (const [key, entry] of Object.entries(nextModels)) {
|
||||
const parsed = parseModelRef(key, "anthropic");
|
||||
if (!isAnthropicCacheRetentionTarget(parsed)) {
|
||||
continue;
|
||||
}
|
||||
const current = entry ?? {};
|
||||
const params = (current as { params?: Record<string, unknown> }).params ?? {};
|
||||
if (typeof params.cacheRetention === "string") {
|
||||
continue;
|
||||
}
|
||||
nextModels[key] = {
|
||||
...(current as Record<string, unknown>),
|
||||
params: { ...params, cacheRetention: "short" },
|
||||
};
|
||||
modelsMutated = true;
|
||||
}
|
||||
|
||||
const primary = resolvePrimaryModelRef(
|
||||
resolveAgentModelPrimaryValue(defaults.model) ?? undefined,
|
||||
);
|
||||
if (primary) {
|
||||
const parsedPrimary = parseModelRef(primary, "anthropic");
|
||||
if (isAnthropicCacheRetentionTarget(parsedPrimary)) {
|
||||
const key = `${parsedPrimary.provider}/${parsedPrimary.model}`;
|
||||
const entry = nextModels[key];
|
||||
const current = entry ?? {};
|
||||
const params = (current as { params?: Record<string, unknown> }).params ?? {};
|
||||
if (typeof params.cacheRetention !== "string") {
|
||||
nextModels[key] = {
|
||||
...(current as Record<string, unknown>),
|
||||
params: { ...params, cacheRetention: "short" },
|
||||
};
|
||||
modelsMutated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modelsMutated) {
|
||||
nextDefaults.models = nextModels;
|
||||
mutated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mutated) {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
return {
|
||||
...cfg,
|
||||
agents: {
|
||||
...cfg.agents,
|
||||
defaults: nextDefaults,
|
||||
},
|
||||
};
|
||||
return (
|
||||
applyProviderConfigDefaultsWithPlugin({
|
||||
provider: "anthropic",
|
||||
context: {
|
||||
provider: "anthropic",
|
||||
config: cfg,
|
||||
env: process.env,
|
||||
},
|
||||
}) ?? cfg
|
||||
);
|
||||
}
|
||||
|
||||
export function applyCompactionDefaults(cfg: OpenClawConfig): OpenClawConfig {
|
||||
|
||||
Reference in New Issue
Block a user