mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 21:30:44 +00:00
fix: hide adaptive think option for GPT models
This commit is contained in:
@@ -811,7 +811,7 @@ describe("handleDirectiveOnly model persist behavior (fixes #1435)", () => {
|
||||
);
|
||||
|
||||
expect(result?.text).toContain("Current thinking level: low");
|
||||
expect(result?.text).toContain("Options: off, minimal, low, medium, high, adaptive.");
|
||||
expect(result?.text).toContain("Options: off, minimal, low, medium, high.");
|
||||
});
|
||||
|
||||
it("persists verbose on and off directives", async () => {
|
||||
|
||||
@@ -20,7 +20,7 @@ export type ThinkingCatalogEntry = {
|
||||
reasoning?: boolean;
|
||||
};
|
||||
|
||||
const BASE_THINKING_LEVELS: ThinkLevel[] = ["off", "minimal", "low", "medium", "high", "adaptive"];
|
||||
const BASE_THINKING_LEVELS: ThinkLevel[] = ["off", "minimal", "low", "medium", "high"];
|
||||
const NO_THINKING_LEVELS: ThinkLevel[] = [...BASE_THINKING_LEVELS];
|
||||
|
||||
export function isBinaryThinkingProvider(provider?: string | null): boolean {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const providerRuntimeMocks = vi.hoisted(() => ({
|
||||
resolveProviderAdaptiveThinking: vi.fn(),
|
||||
resolveProviderBinaryThinking: vi.fn(),
|
||||
resolveProviderDefaultThinkingLevel: vi.fn(),
|
||||
resolveProviderXHighThinking: vi.fn(),
|
||||
@@ -15,6 +16,7 @@ let resolveThinkingDefaultForModel: typeof import("./thinking.js").resolveThinki
|
||||
async function loadFreshThinkingModuleForTest() {
|
||||
vi.resetModules();
|
||||
vi.doMock("../plugins/provider-thinking.js", () => ({
|
||||
resolveProviderAdaptiveThinking: providerRuntimeMocks.resolveProviderAdaptiveThinking,
|
||||
resolveProviderBinaryThinking: providerRuntimeMocks.resolveProviderBinaryThinking,
|
||||
resolveProviderDefaultThinkingLevel: providerRuntimeMocks.resolveProviderDefaultThinkingLevel,
|
||||
resolveProviderXHighThinking: providerRuntimeMocks.resolveProviderXHighThinking,
|
||||
@@ -23,6 +25,8 @@ async function loadFreshThinkingModuleForTest() {
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
providerRuntimeMocks.resolveProviderAdaptiveThinking.mockReset();
|
||||
providerRuntimeMocks.resolveProviderAdaptiveThinking.mockReturnValue(undefined);
|
||||
providerRuntimeMocks.resolveProviderBinaryThinking.mockReset();
|
||||
providerRuntimeMocks.resolveProviderBinaryThinking.mockReturnValue(undefined);
|
||||
providerRuntimeMocks.resolveProviderDefaultThinkingLevel.mockReset();
|
||||
@@ -113,8 +117,23 @@ describe("listThinkingLevels", () => {
|
||||
expect(listThinkingLevels(undefined, "gpt-4.1-mini")).not.toContain("xhigh");
|
||||
});
|
||||
|
||||
it("always includes adaptive", () => {
|
||||
expect(listThinkingLevels(undefined, "gpt-4.1-mini")).toContain("adaptive");
|
||||
it("uses provider runtime hooks for adaptive support", () => {
|
||||
providerRuntimeMocks.resolveProviderAdaptiveThinking.mockReturnValue(true);
|
||||
|
||||
expect(listThinkingLevels("demo", "demo-model")).toContain("adaptive");
|
||||
});
|
||||
|
||||
it("does not include adaptive without provider support", () => {
|
||||
expect(listThinkingLevels(undefined, "gpt-4.1-mini")).not.toContain("adaptive");
|
||||
expect(listThinkingLevels("openai", "gpt-5.4")).not.toContain("adaptive");
|
||||
});
|
||||
|
||||
it("includes adaptive for provider-advertised models", () => {
|
||||
providerRuntimeMocks.resolveProviderAdaptiveThinking.mockImplementation(
|
||||
({ provider, context }) =>
|
||||
provider === "anthropic" && context.modelId === "claude-opus-4-6" ? true : undefined,
|
||||
);
|
||||
|
||||
expect(listThinkingLevels("anthropic", "claude-opus-4-6")).toContain("adaptive");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { normalizeProviderId } from "../agents/provider-id.js";
|
||||
import {
|
||||
formatThinkingLevels as formatThinkingLevelsFallback,
|
||||
listThinkingLevelLabels as listThinkingLevelLabelsFallback,
|
||||
listThinkingLevels as listThinkingLevelsFallback,
|
||||
resolveThinkingDefaultForModel as resolveThinkingDefaultForModelFallback,
|
||||
} from "./thinking.shared.js";
|
||||
@@ -31,6 +29,7 @@ export type {
|
||||
VerboseLevel,
|
||||
} from "./thinking.shared.js";
|
||||
import {
|
||||
resolveProviderAdaptiveThinking,
|
||||
resolveProviderBinaryThinking,
|
||||
resolveProviderDefaultThinkingLevel,
|
||||
resolveProviderXHighThinking,
|
||||
@@ -82,10 +81,33 @@ export function supportsXHighThinking(provider?: string | null, model?: string |
|
||||
return false;
|
||||
}
|
||||
|
||||
export function supportsAdaptiveThinking(provider?: string | null, model?: string | null): boolean {
|
||||
const modelKey = normalizeOptionalLowercaseString(model);
|
||||
if (!modelKey) {
|
||||
return false;
|
||||
}
|
||||
const providerRaw = normalizeOptionalString(provider);
|
||||
const providerKey = providerRaw ? normalizeProviderId(providerRaw) : "";
|
||||
if (!providerKey) {
|
||||
return false;
|
||||
}
|
||||
const pluginDecision = resolveProviderAdaptiveThinking({
|
||||
provider: providerKey,
|
||||
context: {
|
||||
provider: providerKey,
|
||||
modelId: modelKey,
|
||||
},
|
||||
});
|
||||
return pluginDecision === true;
|
||||
}
|
||||
|
||||
export function listThinkingLevels(provider?: string | null, model?: string | null): ThinkLevel[] {
|
||||
const levels = listThinkingLevelsFallback(provider, model);
|
||||
if (supportsXHighThinking(provider, model)) {
|
||||
levels.splice(levels.length - 1, 0, "xhigh");
|
||||
levels.push("xhigh");
|
||||
}
|
||||
if (supportsAdaptiveThinking(provider, model)) {
|
||||
levels.push("adaptive");
|
||||
}
|
||||
return levels;
|
||||
}
|
||||
@@ -94,10 +116,7 @@ export function listThinkingLevelLabels(provider?: string | null, model?: string
|
||||
if (isBinaryThinkingProvider(provider, model)) {
|
||||
return ["off", "on"];
|
||||
}
|
||||
if (supportsXHighThinking(provider, model)) {
|
||||
return listThinkingLevels(provider, model);
|
||||
}
|
||||
return listThinkingLevelLabelsFallback(provider, model);
|
||||
return listThinkingLevels(provider, model);
|
||||
}
|
||||
|
||||
export function formatThinkingLevels(
|
||||
@@ -105,9 +124,7 @@ export function formatThinkingLevels(
|
||||
model?: string | null,
|
||||
separator = ", ",
|
||||
): string {
|
||||
return supportsXHighThinking(provider, model)
|
||||
? listThinkingLevelLabels(provider, model).join(separator)
|
||||
: formatThinkingLevelsFallback(provider, model, separator);
|
||||
return listThinkingLevelLabels(provider, model).join(separator);
|
||||
}
|
||||
|
||||
export function resolveThinkingDefaultForModel(params: {
|
||||
|
||||
@@ -640,6 +640,16 @@ export function resolveProviderXHighThinking(params: {
|
||||
return resolveProviderRuntimePlugin(params)?.supportsXHighThinking?.(params.context);
|
||||
}
|
||||
|
||||
export function resolveProviderAdaptiveThinking(params: {
|
||||
provider: string;
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
context: ProviderThinkingPolicyContext;
|
||||
}) {
|
||||
return resolveProviderRuntimePlugin(params)?.supportsAdaptiveThinking?.(params.context);
|
||||
}
|
||||
|
||||
export function resolveProviderDefaultThinkingLevel(params: {
|
||||
provider: string;
|
||||
config?: OpenClawConfig;
|
||||
|
||||
@@ -8,6 +8,7 @@ type ThinkingProviderPlugin = {
|
||||
id: string;
|
||||
aliases?: string[];
|
||||
isBinaryThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
|
||||
supportsAdaptiveThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
|
||||
supportsXHighThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
|
||||
resolveDefaultThinkingLevel?: (
|
||||
ctx: ProviderDefaultThinkingPolicyContext,
|
||||
@@ -61,6 +62,12 @@ export function resolveProviderXHighThinking(
|
||||
return resolveActiveThinkingProvider(params.provider)?.supportsXHighThinking?.(params.context);
|
||||
}
|
||||
|
||||
export function resolveProviderAdaptiveThinking(
|
||||
params: ThinkingHookParams<ProviderThinkingPolicyContext>,
|
||||
) {
|
||||
return resolveActiveThinkingProvider(params.provider)?.supportsAdaptiveThinking?.(params.context);
|
||||
}
|
||||
|
||||
export function resolveProviderDefaultThinkingLevel(
|
||||
params: ThinkingHookParams<ProviderDefaultThinkingPolicyContext>,
|
||||
) {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
* Provider-owned thinking policy input.
|
||||
*
|
||||
* Used by shared `/think`, ACP controls, and directive parsing to ask a
|
||||
* provider whether a model supports special reasoning UX such as xhigh or a
|
||||
* binary on/off toggle.
|
||||
* provider whether a model supports special reasoning UX such as adaptive,
|
||||
* xhigh, or a binary on/off toggle.
|
||||
*/
|
||||
export type ProviderThinkingPolicyContext = {
|
||||
provider: string;
|
||||
|
||||
@@ -1407,6 +1407,12 @@ export type ProviderPlugin = {
|
||||
* Return true only for models that should expose the `xhigh` thinking level.
|
||||
*/
|
||||
supportsXHighThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
|
||||
/**
|
||||
* Provider-owned adaptive thinking support.
|
||||
*
|
||||
* Return true only for models that should expose the `adaptive` thinking level.
|
||||
*/
|
||||
supportsAdaptiveThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
|
||||
/**
|
||||
* Provider-owned default thinking level.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user