fix: centralize provider thinking profiles

This commit is contained in:
Peter Steinberger
2026-04-21 09:04:37 +01:00
parent 1cc2fc82ca
commit f1805ab54d
57 changed files with 718 additions and 572 deletions

View File

@@ -19,6 +19,7 @@ import {
} from "./provider-hook-runtime.js";
import { resolveBundledProviderPolicySurface } from "./provider-public-artifacts.js";
import type { ProviderRuntimeModel } from "./provider-runtime-model.types.js";
import type { ProviderThinkingProfile } from "./provider-thinking.types.js";
import { resolveCatalogHookProviderPluginIds } from "./providers.js";
import { getActivePluginRegistryWorkspaceDirFromState } from "./runtime-state.js";
import { resolveRuntimeTextTransforms } from "./text-transforms.runtime.js";
@@ -640,24 +641,14 @@ export function resolveProviderXHighThinking(params: {
return resolveProviderRuntimePlugin(params)?.supportsXHighThinking?.(params.context);
}
export function resolveProviderAdaptiveThinking(params: {
export function resolveProviderThinkingProfile(params: {
provider: string;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
context: ProviderThinkingPolicyContext;
}) {
return resolveProviderRuntimePlugin(params)?.supportsAdaptiveThinking?.(params.context);
}
export function resolveProviderMaxThinking(params: {
provider: string;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
context: ProviderThinkingPolicyContext;
}) {
return resolveProviderRuntimePlugin(params)?.supportsMaxThinking?.(params.context);
context: ProviderDefaultThinkingPolicyContext;
}): ProviderThinkingProfile | null | undefined {
return resolveProviderRuntimePlugin(params)?.resolveThinkingProfile?.(params.context);
}
export function resolveProviderDefaultThinkingLevel(params: {

View File

@@ -1,6 +1,7 @@
import { normalizeProviderId } from "../agents/provider-id.js";
import type {
ProviderDefaultThinkingPolicyContext,
ProviderThinkingProfile,
ProviderThinkingPolicyContext,
} from "./provider-thinking.types.js";
@@ -8,22 +9,13 @@ type ThinkingProviderPlugin = {
id: string;
aliases?: string[];
isBinaryThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
supportsAdaptiveThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
supportsMaxThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
supportsXHighThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
resolveThinkingProfile?: (
ctx: ProviderDefaultThinkingPolicyContext,
) => ProviderThinkingProfile | null | undefined;
resolveDefaultThinkingLevel?: (
ctx: ProviderDefaultThinkingPolicyContext,
) =>
| "off"
| "minimal"
| "low"
| "medium"
| "high"
| "xhigh"
| "adaptive"
| "max"
| null
| undefined;
) => "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | null | undefined;
};
const PLUGIN_REGISTRY_STATE = Symbol.for("openclaw.pluginRegistryState");
@@ -73,16 +65,10 @@ export function resolveProviderXHighThinking(
return resolveActiveThinkingProvider(params.provider)?.supportsXHighThinking?.(params.context);
}
export function resolveProviderAdaptiveThinking(
params: ThinkingHookParams<ProviderThinkingPolicyContext>,
export function resolveProviderThinkingProfile(
params: ThinkingHookParams<ProviderDefaultThinkingPolicyContext>,
) {
return resolveActiveThinkingProvider(params.provider)?.supportsAdaptiveThinking?.(params.context);
}
export function resolveProviderMaxThinking(
params: ThinkingHookParams<ProviderThinkingPolicyContext>,
) {
return resolveActiveThinkingProvider(params.provider)?.supportsMaxThinking?.(params.context);
return resolveActiveThinkingProvider(params.provider)?.resolveThinkingProfile?.(params.context);
}
export function resolveProviderDefaultThinkingLevel(

View File

@@ -20,3 +20,33 @@ export type ProviderThinkingPolicyContext = {
export type ProviderDefaultThinkingPolicyContext = ProviderThinkingPolicyContext & {
reasoning?: boolean;
};
export type ProviderThinkingLevelId =
| "off"
| "minimal"
| "low"
| "medium"
| "high"
| "xhigh"
| "adaptive"
| "max";
export type ProviderThinkingLevel = {
id: ProviderThinkingLevelId;
/**
* Optional display label. Use this when the stored value differs from the
* provider-facing UX, for example binary providers storing `low` but showing
* `on`.
*/
label?: string;
/**
* Relative strength used when downgrading a stored level that the selected
* model no longer supports.
*/
rank?: number;
};
export type ProviderThinkingProfile = {
levels: ProviderThinkingLevel[] | ReadonlyArray<ProviderThinkingLevel>;
defaultLevel?: ProviderThinkingLevelId | null;
};

View File

@@ -109,6 +109,7 @@ import type { createVpsAwareOAuthHandlers } from "./provider-oauth-flow.js";
import type { ProviderRuntimeModel } from "./provider-runtime-model.types.js";
import type {
ProviderDefaultThinkingPolicyContext,
ProviderThinkingProfile,
ProviderThinkingPolicyContext,
} from "./provider-thinking.types.js";
import type { PluginRuntime } from "./runtime/types.js";
@@ -902,6 +903,7 @@ export type ProviderBuiltInModelSuppressionResult = {
export type {
ProviderDefaultThinkingPolicyContext,
ProviderThinkingProfile,
ProviderThinkingPolicyContext,
} from "./provider-thinking.types.js";
@@ -1399,45 +1401,40 @@ export type ProviderPlugin = {
*
* Return true when the provider exposes a coarse on/off reasoning control
* instead of the normal multi-level ladder shown by `/think`.
*
* @deprecated Prefer `resolveThinkingProfile`.
*/
isBinaryThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
/**
* Provider-owned xhigh reasoning support.
*
* Return true only for models that should expose the `xhigh` thinking level.
*
* @deprecated Prefer `resolveThinkingProfile`.
*/
supportsXHighThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
/**
* Provider-owned adaptive thinking support.
* Provider-owned thinking level profile.
*
* Return true only for models that should expose the `adaptive` thinking level.
* Prefer this over the individual thinking capability hooks when a provider
* or model exposes a custom set of thinking levels. OpenClaw stores the
* canonical `id`, shows `label` when provided, and downgrades stale stored
* values by profile rank.
*/
supportsAdaptiveThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
/**
* Provider-owned max thinking support.
*
* Return true only for models that should expose the `max` thinking level.
*/
supportsMaxThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
resolveThinkingProfile?: (
ctx: ProviderDefaultThinkingPolicyContext,
) => ProviderThinkingProfile | null | undefined;
/**
* Provider-owned default thinking level.
*
* Use this to keep model-family defaults (for example Claude 4.6 =>
* adaptive) out of core command logic.
*
* @deprecated Prefer `resolveThinkingProfile`.
*/
resolveDefaultThinkingLevel?: (
ctx: ProviderDefaultThinkingPolicyContext,
) =>
| "off"
| "minimal"
| "low"
| "medium"
| "high"
| "xhigh"
| "adaptive"
| "max"
| null
| undefined;
) => "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | null | undefined;
/**
* Provider-owned system-prompt contribution.
*