perf(agents): isolate thinking default helper

This commit is contained in:
Vincent Koc
2026-04-13 18:39:38 +01:00
parent 5b11985439
commit 117ae85bf5
3 changed files with 73 additions and 62 deletions

View File

@@ -1,4 +1,3 @@
import { resolveThinkingDefaultForModel } from "../auto-reply/thinking.shared.js";
import {
resolveAgentModelFallbackValues,
resolveAgentModelPrimaryValue,
@@ -8,7 +7,6 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
normalizeOptionalString,
} from "../shared/string-coerce.js";
import { sanitizeForLog, stripAnsi } from "../terminal/ansi.js";
@@ -21,6 +19,7 @@ import { resolveConfiguredProviderFallback } from "./configured-provider-fallbac
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "./defaults.js";
import type { ModelCatalogEntry } from "./model-catalog.types.js";
import { splitTrailingAuthProfile } from "./model-ref-profile.js";
export { resolveThinkingDefault } from "./model-thinking-default.js";
import {
type ModelRef,
findNormalizedProviderKey,
@@ -761,65 +760,6 @@ export function resolveAllowedModelRef(params: {
return { ref: resolved.ref, key: status.key };
}
export function resolveThinkingDefault(params: {
cfg: OpenClawConfig;
provider: string;
model: string;
catalog?: ModelCatalogEntry[];
}): ThinkLevel {
const normalizedProvider = normalizeProviderId(params.provider);
const normalizedModel = normalizeLowercaseStringOrEmpty(params.model).replace(/\./g, "-");
const catalogCandidate = params.catalog?.find(
(entry) => entry.provider === params.provider && entry.id === params.model,
);
const configuredModels = params.cfg.agents?.defaults?.models;
const canonicalKey = modelKey(params.provider, params.model);
const legacyKey = legacyModelKey(params.provider, params.model);
const normalizedCanonicalKey = normalizeLowercaseStringOrEmpty(canonicalKey);
const normalizedLegacyKey = normalizeOptionalLowercaseString(legacyKey);
const primarySelection = normalizeModelSelection(params.cfg.agents?.defaults?.model);
const normalizedPrimarySelection = normalizeOptionalLowercaseString(primarySelection);
const explicitModelConfigured =
(configuredModels ? canonicalKey in configuredModels : false) ||
Boolean(legacyKey && configuredModels && legacyKey in configuredModels) ||
normalizedPrimarySelection === normalizedCanonicalKey ||
Boolean(normalizedLegacyKey && normalizedPrimarySelection === normalizedLegacyKey) ||
normalizedPrimarySelection === normalizeLowercaseStringOrEmpty(params.model);
const perModelThinking =
configuredModels?.[canonicalKey]?.params?.thinking ??
(legacyKey ? configuredModels?.[legacyKey]?.params?.thinking : undefined);
if (
perModelThinking === "off" ||
perModelThinking === "minimal" ||
perModelThinking === "low" ||
perModelThinking === "medium" ||
perModelThinking === "high" ||
perModelThinking === "xhigh" ||
perModelThinking === "adaptive"
) {
return perModelThinking;
}
const configured = params.cfg.agents?.defaults?.thinkingDefault;
if (configured) {
return configured;
}
if (
normalizedProvider === "anthropic" &&
explicitModelConfigured &&
typeof catalogCandidate?.name === "string" &&
/4\.6\b/.test(catalogCandidate.name) &&
(normalizedModel.startsWith("claude-opus-4-6") ||
normalizedModel.startsWith("claude-sonnet-4-6"))
) {
return "adaptive";
}
return resolveThinkingDefaultForModel({
provider: params.provider,
model: params.model,
catalog: params.catalog,
});
}
/** Default reasoning level when session/directive do not set it: "on" if model supports reasoning, else "off". */
export function resolveReasoningDefault(params: {
provider: string;

View File

@@ -0,0 +1,70 @@
import { resolveThinkingDefaultForModel } from "../auto-reply/thinking.shared.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "../shared/string-coerce.js";
import type { ModelCatalogEntry } from "./model-catalog.types.js";
import { legacyModelKey, modelKey, normalizeProviderId } from "./model-selection-normalize.js";
import { normalizeModelSelection } from "./model-selection-resolve.js";
type ThinkLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive";
export function resolveThinkingDefault(params: {
cfg: OpenClawConfig;
provider: string;
model: string;
catalog?: ModelCatalogEntry[];
}): ThinkLevel {
const normalizedProvider = normalizeProviderId(params.provider);
const normalizedModel = normalizeLowercaseStringOrEmpty(params.model).replace(/\./g, "-");
const catalogCandidate = params.catalog?.find(
(entry) => entry.provider === params.provider && entry.id === params.model,
);
const configuredModels = params.cfg.agents?.defaults?.models;
const canonicalKey = modelKey(params.provider, params.model);
const legacyKey = legacyModelKey(params.provider, params.model);
const normalizedCanonicalKey = normalizeLowercaseStringOrEmpty(canonicalKey);
const normalizedLegacyKey = normalizeOptionalLowercaseString(legacyKey);
const primarySelection = normalizeModelSelection(params.cfg.agents?.defaults?.model);
const normalizedPrimarySelection = normalizeOptionalLowercaseString(primarySelection);
const explicitModelConfigured =
(configuredModels ? canonicalKey in configuredModels : false) ||
Boolean(legacyKey && configuredModels && legacyKey in configuredModels) ||
normalizedPrimarySelection === normalizedCanonicalKey ||
Boolean(normalizedLegacyKey && normalizedPrimarySelection === normalizedLegacyKey) ||
normalizedPrimarySelection === normalizeLowercaseStringOrEmpty(params.model);
const perModelThinking =
configuredModels?.[canonicalKey]?.params?.thinking ??
(legacyKey ? configuredModels?.[legacyKey]?.params?.thinking : undefined);
if (
perModelThinking === "off" ||
perModelThinking === "minimal" ||
perModelThinking === "low" ||
perModelThinking === "medium" ||
perModelThinking === "high" ||
perModelThinking === "xhigh" ||
perModelThinking === "adaptive"
) {
return perModelThinking;
}
const configured = params.cfg.agents?.defaults?.thinkingDefault;
if (configured) {
return configured;
}
if (
normalizedProvider === "anthropic" &&
explicitModelConfigured &&
typeof catalogCandidate?.name === "string" &&
/4\.6\b/.test(catalogCandidate.name) &&
(normalizedModel.startsWith("claude-opus-4-6") ||
normalizedModel.startsWith("claude-sonnet-4-6"))
) {
return "adaptive";
}
return resolveThinkingDefaultForModel({
provider: params.provider,
model: params.model,
catalog: params.catalog,
});
}

View File

@@ -7,7 +7,8 @@ export {
} from "../../agents/agent-scope.js";
export { resolveCronStyleNow } from "../../agents/current-time.js";
export { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js";
export { isCliProvider, resolveThinkingDefault } from "../../agents/model-selection.js";
export { isCliProvider } from "../../agents/model-selection-cli.js";
export { resolveThinkingDefault } from "../../agents/model-thinking-default.js";
export { resolveAgentTimeoutMs } from "../../agents/timeout.js";
export { deriveSessionTotalTokens, hasNonzeroUsage } from "../../agents/usage.js";
export { DEFAULT_IDENTITY_FILENAME, ensureAgentWorkspace } from "../../agents/workspace.js";