diff --git a/CHANGELOG.md b/CHANGELOG.md index 12b583626a2..70ebb2e4540 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Plugins/Anthropic: expose Claude thinking profiles from the bundled provider-policy artifact so non-runtime callers keep Opus 4.7 `adaptive`, `xhigh`, and `max` instead of downgrading to `high`. Fixes #76779. Thanks @tomascupr and @iAbhi001. - Discord/native commands: skip slash-command registration and cleanup REST calls when `channels.discord.commands.native=false`, letting low-power gateways start without waiting on disabled native-command lifecycle requests. Fixes #76202. Thanks @vincentkoc. - Plugins/commands: normalize empty plugin command handler results and let Telegram native plugin commands send the empty-response fallback instead of throwing when a handler returns `undefined`. Fixes #74800. Thanks @vincentkoc. - Plugins/tools: cold-load selected plugin tool registries when the active registry only has partial tool coverage, so wildcard-expanded allowlists no longer hide installed plugin tools from `tools.effective`. Fixes #76780. Thanks @lilesjtu. diff --git a/extensions/anthropic/provider-policy-api.test.ts b/extensions/anthropic/provider-policy-api.test.ts index b1beddbcaf8..d1cd3a835d1 100644 --- a/extensions/anthropic/provider-policy-api.test.ts +++ b/extensions/anthropic/provider-policy-api.test.ts @@ -1,6 +1,10 @@ import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-types"; import { describe, expect, it } from "vitest"; -import { applyConfigDefaults, normalizeConfig } from "./provider-policy-api.js"; +import { + applyConfigDefaults, + normalizeConfig, + resolveThinkingProfile, +} from "./provider-policy-api.js"; function createModel(id: string, name: string): ModelDefinitionConfig { return { @@ -87,4 +91,41 @@ describe("anthropic provider policy public artifact", () => { ttl: "1h", }); }); + + it("exposes Claude Opus 4.7 thinking levels without loading the full provider plugin", () => { + expect( + resolveThinkingProfile({ + provider: "anthropic", + modelId: "claude-opus-4-7", + }), + ).toMatchObject({ + levels: expect.arrayContaining([{ id: "xhigh" }, { id: "adaptive" }, { id: "max" }]), + defaultLevel: "off", + }); + }); + + it("keeps adaptive-only Claude profiles aligned with the runtime provider", () => { + const profile = resolveThinkingProfile({ + provider: "anthropic", + modelId: "claude-opus-4-6", + }); + + expect(profile).toMatchObject({ + levels: expect.arrayContaining([{ id: "adaptive" }]), + defaultLevel: "adaptive", + }); + if (!profile) { + throw new Error("Expected Anthropic policy profile"); + } + expect(profile.levels.some((level) => level.id === "xhigh" || level.id === "max")).toBe(false); + }); + + it("does not expose Anthropic thinking profiles for unrelated providers", () => { + expect( + resolveThinkingProfile({ + provider: "openai", + modelId: "claude-opus-4-7", + }), + ).toBeNull(); + }); }); diff --git a/extensions/anthropic/provider-policy-api.ts b/extensions/anthropic/provider-policy-api.ts index 912ad48810c..1655bcf20af 100644 --- a/extensions/anthropic/provider-policy-api.ts +++ b/extensions/anthropic/provider-policy-api.ts @@ -1,3 +1,4 @@ +import { resolveClaudeThinkingProfile } from "openclaw/plugin-sdk/provider-model-shared"; import type { ModelProviderConfig } from "openclaw/plugin-sdk/provider-model-types"; import { applyAnthropicConfigDefaults, @@ -11,3 +12,13 @@ export function normalizeConfig(params: { provider: string; providerConfig: Mode export function applyConfigDefaults(params: Parameters[0]) { return applyAnthropicConfigDefaults(params); } + +export function resolveThinkingProfile(params: { provider: string; modelId: string }) { + switch (params.provider.trim().toLowerCase()) { + case "anthropic": + case "claude-cli": + return resolveClaudeThinkingProfile(params.modelId); + default: + return null; + } +}