mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 20:20:42 +00:00
fix: gate max thinking by model support
This commit is contained in:
@@ -160,7 +160,7 @@ function buildThinkingOptions(
|
||||
);
|
||||
};
|
||||
|
||||
for (const label of listThinkingLevelLabels(provider)) {
|
||||
for (const label of listThinkingLevelLabels(provider, model)) {
|
||||
const normalized = normalizeThinkLevel(label) ?? normalizeLowercaseStringOrEmpty(label);
|
||||
addOption(normalized);
|
||||
}
|
||||
|
||||
@@ -520,7 +520,7 @@ describe("executeSlashCommand directives", () => {
|
||||
);
|
||||
|
||||
expect(result.content).toBe(
|
||||
"Current thinking level: low.\nOptions: off, minimal, low, medium, high, adaptive.",
|
||||
"Current thinking level: low.\nOptions: off, minimal, low, medium, high.",
|
||||
);
|
||||
expect(request).toHaveBeenNthCalledWith(1, "sessions.list", {});
|
||||
expect(request).toHaveBeenNthCalledWith(2, "models.list", {});
|
||||
|
||||
@@ -258,7 +258,7 @@ async function executeThink(
|
||||
return {
|
||||
content: formatDirectiveOptions(
|
||||
`Current thinking level: ${resolveCurrentThinkingLevel(session, models)}.`,
|
||||
formatThinkingLevels(session?.modelProvider),
|
||||
formatThinkingLevels(session?.modelProvider, session?.model),
|
||||
),
|
||||
};
|
||||
} catch (err) {
|
||||
@@ -271,7 +271,7 @@ async function executeThink(
|
||||
try {
|
||||
const session = await loadCurrentSession(client, sessionKey);
|
||||
return {
|
||||
content: `Unrecognized thinking level "${rawLevel}". Valid levels: ${formatThinkingLevels(session?.modelProvider)}.`,
|
||||
content: `Unrecognized thinking level "${rawLevel}". Valid levels: ${formatThinkingLevels(session?.modelProvider, session?.model)}.`,
|
||||
};
|
||||
} catch (err) {
|
||||
return { content: `Failed to validate thinking level: ${String(err)}` };
|
||||
|
||||
@@ -6,10 +6,13 @@ export type ThinkingCatalogEntry = {
|
||||
reasoning?: boolean;
|
||||
};
|
||||
|
||||
const BASE_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "adaptive"] as const;
|
||||
const BASE_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high"] as const;
|
||||
const BINARY_THINKING_LEVELS = ["off", "on"] as const;
|
||||
const ANTHROPIC_CLAUDE_46_MODEL_RE = /^claude-(?:opus|sonnet)-4(?:\.|-)6(?:$|[-.])/i;
|
||||
const ANTHROPIC_OPUS_47_MODEL_RE = /^claude-opus-4(?:\.|-)7(?:$|[-.])/i;
|
||||
const AMAZON_BEDROCK_CLAUDE_46_MODEL_RE = /claude-(?:opus|sonnet)-4(?:\.|-)6(?:$|[-.])/i;
|
||||
const OPENAI_XHIGH_MODEL_RE =
|
||||
/^(?:gpt-5\.[2-9](?:\.\d+)?|gpt-5\.[2-9](?:\.\d+)?-pro|gpt-5\.\d+-codex|gpt-5\.\d+-codex-spark|gpt-5\.1-codex|gpt-5\.2-codex)(?:$|-)/i;
|
||||
|
||||
export function normalizeThinkingProviderId(provider?: string | null): string {
|
||||
if (!provider) {
|
||||
@@ -38,6 +41,9 @@ export function normalizeThinkLevel(raw?: string | null): string | undefined {
|
||||
if (collapsed === "adaptive" || collapsed === "auto") {
|
||||
return "adaptive";
|
||||
}
|
||||
if (collapsed === "max") {
|
||||
return "max";
|
||||
}
|
||||
if (collapsed === "xhigh" || collapsed === "extrahigh") {
|
||||
return "xhigh";
|
||||
}
|
||||
@@ -56,9 +62,7 @@ export function normalizeThinkLevel(raw?: string | null): string | undefined {
|
||||
if (["mid", "med", "medium", "thinkharder", "think-harder", "harder"].includes(key)) {
|
||||
return "medium";
|
||||
}
|
||||
if (
|
||||
["high", "ultra", "ultrathink", "think-hard", "thinkhardest", "highest", "max"].includes(key)
|
||||
) {
|
||||
if (["high", "ultra", "ultrathink", "think-hard", "thinkhardest", "highest"].includes(key)) {
|
||||
return "high";
|
||||
}
|
||||
if (key === "think") {
|
||||
@@ -67,12 +71,53 @@ export function normalizeThinkLevel(raw?: string | null): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function listThinkingLevelLabels(provider?: string | null): readonly string[] {
|
||||
return isBinaryThinkingProvider(provider) ? BINARY_THINKING_LEVELS : BASE_THINKING_LEVELS;
|
||||
function supportsAdaptiveThinking(provider?: string | null, model?: string | null): boolean {
|
||||
const normalizedProvider = normalizeThinkingProviderId(provider);
|
||||
const modelId = model?.trim() ?? "";
|
||||
if (normalizedProvider === "anthropic") {
|
||||
return ANTHROPIC_CLAUDE_46_MODEL_RE.test(modelId) || ANTHROPIC_OPUS_47_MODEL_RE.test(modelId);
|
||||
}
|
||||
if (normalizedProvider === "amazon-bedrock") {
|
||||
return AMAZON_BEDROCK_CLAUDE_46_MODEL_RE.test(modelId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function formatThinkingLevels(provider?: string | null): string {
|
||||
return listThinkingLevelLabels(provider).join(", ");
|
||||
function supportsXHighThinking(provider?: string | null, model?: string | null): boolean {
|
||||
const normalizedProvider = normalizeThinkingProviderId(provider);
|
||||
const modelId = model?.trim() ?? "";
|
||||
if (normalizedProvider === "anthropic") {
|
||||
return ANTHROPIC_OPUS_47_MODEL_RE.test(modelId);
|
||||
}
|
||||
if (["openai", "openai-codex", "github-copilot", "codex"].includes(normalizedProvider)) {
|
||||
return OPENAI_XHIGH_MODEL_RE.test(modelId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function supportsMaxThinking(provider?: string | null, model?: string | null): boolean {
|
||||
return normalizeThinkingProviderId(provider) === "anthropic"
|
||||
? ANTHROPIC_OPUS_47_MODEL_RE.test(model?.trim() ?? "")
|
||||
: false;
|
||||
}
|
||||
|
||||
export function listThinkingLevelLabels(
|
||||
provider?: string | null,
|
||||
model?: string | null,
|
||||
): readonly string[] {
|
||||
if (isBinaryThinkingProvider(provider)) {
|
||||
return BINARY_THINKING_LEVELS;
|
||||
}
|
||||
return [
|
||||
...BASE_THINKING_LEVELS,
|
||||
...(supportsXHighThinking(provider, model) ? ["xhigh"] : []),
|
||||
...(supportsAdaptiveThinking(provider, model) ? ["adaptive"] : []),
|
||||
...(supportsMaxThinking(provider, model) ? ["max"] : []),
|
||||
];
|
||||
}
|
||||
|
||||
export function formatThinkingLevels(provider?: string | null, model?: string | null): string {
|
||||
return listThinkingLevelLabels(provider, model).join(", ");
|
||||
}
|
||||
|
||||
export function resolveThinkingDefaultForModel(params: {
|
||||
|
||||
Reference in New Issue
Block a user