refactor(thinking): move provider thinking fallback out of core

This commit is contained in:
Peter Steinberger
2026-04-04 07:00:16 +01:00
parent b59ce0903c
commit fca80d2ee2
3 changed files with 16 additions and 73 deletions

View File

@@ -1,5 +1,3 @@
import { matchesExactOrPrefix } from "../plugins/provider-model-helpers.js";
export type ThinkLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive"; export type ThinkLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive";
export type VerboseLevel = "off" | "on" | "full"; export type VerboseLevel = "off" | "on" | "full";
export type NoticeLevel = "off" | "on" | "full"; export type NoticeLevel = "off" | "on" | "full";
@@ -14,59 +12,19 @@ export type ThinkingCatalogEntry = {
}; };
const BASE_THINKING_LEVELS: ThinkLevel[] = ["off", "minimal", "low", "medium", "high", "adaptive"]; const BASE_THINKING_LEVELS: ThinkLevel[] = ["off", "minimal", "low", "medium", "high", "adaptive"];
const ANTHROPIC_CLAUDE_46_MODEL_RE = /^claude-(?:opus|sonnet)-4(?:\.|-)6(?:$|[-.])/i; const NO_THINKING_LEVELS: ThinkLevel[] = [...BASE_THINKING_LEVELS];
const AMAZON_BEDROCK_CLAUDE_46_MODEL_RE = /claude-(?:opus|sonnet)-4(?:\.|-)6(?:$|[-.])/i;
const OPENAI_XHIGH_MODEL_IDS = [
"gpt-5.4",
"gpt-5.4-pro",
"gpt-5.4-mini",
"gpt-5.4-nano",
"gpt-5.2",
] as const;
const OPENAI_CODEX_XHIGH_MODEL_IDS = [
"gpt-5.4",
"gpt-5.3-codex-spark",
"gpt-5.2-codex",
"gpt-5.1-codex",
] as const;
const GITHUB_COPILOT_XHIGH_MODEL_IDS = ["gpt-5.2", "gpt-5.2-codex"] as const;
export function normalizeProviderId(provider?: string | null): string {
if (!provider) {
return "";
}
const normalized = provider.trim().toLowerCase();
if (normalized === "z.ai" || normalized === "z-ai") {
return "zai";
}
if (normalized === "bedrock" || normalized === "aws-bedrock") {
return "amazon-bedrock";
}
return normalized;
}
export function isBinaryThinkingProvider(provider?: string | null): boolean { export function isBinaryThinkingProvider(provider?: string | null): boolean {
return normalizeProviderId(provider) === "zai"; void provider;
return false;
} }
export function supportsBuiltInXHighThinking( export function supportsBuiltInXHighThinking(
provider?: string | null, provider?: string | null,
model?: string | null, model?: string | null,
): boolean { ): boolean {
const providerId = normalizeProviderId(provider); void provider;
const modelId = model?.trim().toLowerCase(); void model;
if (!providerId || !modelId) {
return false;
}
if (providerId === "openai") {
return matchesExactOrPrefix(modelId, OPENAI_XHIGH_MODEL_IDS);
}
if (providerId === "openai-codex") {
return matchesExactOrPrefix(modelId, OPENAI_CODEX_XHIGH_MODEL_IDS);
}
if (providerId === "github-copilot") {
return GITHUB_COPILOT_XHIGH_MODEL_IDS.includes(modelId as never);
}
return false; return false;
} }
@@ -113,7 +71,7 @@ export function listThinkingLevels(
_provider?: string | null, _provider?: string | null,
_model?: string | null, _model?: string | null,
): ThinkLevel[] { ): ThinkLevel[] {
return [...BASE_THINKING_LEVELS]; return [...NO_THINKING_LEVELS];
} }
export function listThinkingLevelLabels(provider?: string | null, model?: string | null): string[] { export function listThinkingLevelLabels(provider?: string | null, model?: string | null): string[] {
@@ -140,14 +98,6 @@ export function resolveThinkingDefaultForModel(params: {
model: string; model: string;
catalog?: ThinkingCatalogEntry[]; catalog?: ThinkingCatalogEntry[];
}): ThinkLevel { }): ThinkLevel {
const normalizedProvider = normalizeProviderId(params.provider);
const modelId = params.model.trim();
if (normalizedProvider === "anthropic" && ANTHROPIC_CLAUDE_46_MODEL_RE.test(modelId)) {
return "adaptive";
}
if (normalizedProvider === "amazon-bedrock" && AMAZON_BEDROCK_CLAUDE_46_MODEL_RE.test(modelId)) {
return "adaptive";
}
const candidate = params.catalog?.find( const candidate = params.catalog?.find(
(entry) => entry.provider === params.provider && entry.id === params.model, (entry) => entry.provider === params.provider && entry.id === params.model,
); );

View File

@@ -127,8 +127,9 @@ describe("listThinkingLevelLabels", () => {
expect(listThinkingLevelLabels("zai", "glm-4.7")).toEqual(["off", "on"]); expect(listThinkingLevelLabels("zai", "glm-4.7")).toEqual(["off", "on"]);
}); });
it("keeps built-in binary thinking fallback without provider runtime", () => { it("does not assume binary thinking without provider runtime", () => {
expect(listThinkingLevelLabels("zai", "glm-4.7")).toEqual(["off", "on"]); expect(listThinkingLevelLabels("zai", "glm-4.7")).toContain("low");
expect(listThinkingLevelLabels("zai", "glm-4.7")).not.toContain("on");
}); });
it("returns full levels for non-ZAI", () => { it("returns full levels for non-ZAI", () => {
@@ -170,13 +171,13 @@ describe("resolveThinkingDefaultForModel", () => {
).toBe("adaptive"); ).toBe("adaptive");
}); });
it("keeps built-in adaptive defaults without provider runtime", () => { it("does not assume adaptive defaults without provider runtime", () => {
expect( expect(
resolveThinkingDefaultForModel({ provider: "anthropic", model: "claude-opus-4-6" }), resolveThinkingDefaultForModel({ provider: "anthropic", model: "claude-opus-4-6" }),
).toBe("adaptive"); ).toBe("off");
expect( expect(
resolveThinkingDefaultForModel({ provider: "aws-bedrock", model: "claude-sonnet-4-6" }), resolveThinkingDefaultForModel({ provider: "aws-bedrock", model: "claude-sonnet-4-6" }),
).toBe("adaptive"); ).toBe("off");
}); });
it("defaults reasoning-capable catalog models to low", () => { it("defaults reasoning-capable catalog models to low", () => {

View File

@@ -1,11 +1,9 @@
import { normalizeProviderId } from "../agents/provider-id.js";
import { import {
formatThinkingLevels as formatThinkingLevelsFallback, formatThinkingLevels as formatThinkingLevelsFallback,
isBinaryThinkingProvider as isBinaryThinkingProviderFallback,
listThinkingLevelLabels as listThinkingLevelLabelsFallback, listThinkingLevelLabels as listThinkingLevelLabelsFallback,
listThinkingLevels as listThinkingLevelsFallback, listThinkingLevels as listThinkingLevelsFallback,
normalizeProviderId,
resolveThinkingDefaultForModel as resolveThinkingDefaultForModelFallback, resolveThinkingDefaultForModel as resolveThinkingDefaultForModelFallback,
supportsBuiltInXHighThinking,
} from "./thinking.shared.js"; } from "./thinking.shared.js";
import type { ThinkLevel, ThinkingCatalogEntry } from "./thinking.shared.js"; import type { ThinkLevel, ThinkingCatalogEntry } from "./thinking.shared.js";
export { export {
@@ -37,10 +35,7 @@ import {
} from "../plugins/provider-thinking.js"; } from "../plugins/provider-thinking.js";
export function isBinaryThinkingProvider(provider?: string | null, model?: string | null): boolean { export function isBinaryThinkingProvider(provider?: string | null, model?: string | null): boolean {
if (isBinaryThinkingProviderFallback(provider)) { const normalizedProvider = provider?.trim() ? normalizeProviderId(provider) : "";
return true;
}
const normalizedProvider = normalizeProviderId(provider);
if (!normalizedProvider) { if (!normalizedProvider) {
return false; return false;
} }
@@ -55,7 +50,7 @@ export function isBinaryThinkingProvider(provider?: string | null, model?: strin
if (typeof pluginDecision === "boolean") { if (typeof pluginDecision === "boolean") {
return pluginDecision; return pluginDecision;
} }
return isBinaryThinkingProviderFallback(provider); return false;
} }
export function supportsXHighThinking(provider?: string | null, model?: string | null): boolean { export function supportsXHighThinking(provider?: string | null, model?: string | null): boolean {
@@ -63,10 +58,7 @@ export function supportsXHighThinking(provider?: string | null, model?: string |
if (!modelKey) { if (!modelKey) {
return false; return false;
} }
if (supportsBuiltInXHighThinking(provider, modelKey)) { const providerKey = provider?.trim() ? normalizeProviderId(provider) : "";
return true;
}
const providerKey = normalizeProviderId(provider);
if (providerKey) { if (providerKey) {
const pluginDecision = resolveProviderXHighThinking({ const pluginDecision = resolveProviderXHighThinking({
provider: providerKey, provider: providerKey,