feat: add model thinking level metadata

closes #3208
This commit is contained in:
Mario Zechner
2026-05-02 01:20:01 +02:00
parent 73b7b2c564
commit 80f06d3636
28 changed files with 527 additions and 243 deletions

View File

@@ -1,5 +1,5 @@
import { MODELS } from "./models.generated.js";
import type { Api, KnownProvider, Model, Usage } from "./types.js";
import type { Api, KnownProvider, Model, ModelThinkingLevel, Usage } from "./types.js";
const modelRegistry: Map<string, Map<string, Model<Api>>> = new Map();
@@ -45,36 +45,38 @@ export function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage
return usage.cost;
}
/**
* Check if a model supports xhigh thinking level.
*
* Supported today:
* - GPT-5.2 / GPT-5.3 / GPT-5.4 / GPT-5.5 model families
* - DeepSeek V4 Pro and Flash
* - Opus 4.6+ models (xhigh maps to adaptive effort "max" on Anthropic-compatible providers)
*/
export function supportsXhigh<TApi extends Api>(model: Model<TApi>): boolean {
if (
model.id.includes("gpt-5.2") ||
model.id.includes("gpt-5.3") ||
model.id.includes("gpt-5.4") ||
model.id.includes("gpt-5.5") ||
model.id.includes("deepseek-v4-pro") ||
model.id.includes("deepseek-v4-flash")
) {
return true;
}
const EXTENDED_THINKING_LEVELS: ModelThinkingLevel[] = ["off", "minimal", "low", "medium", "high", "xhigh"];
if (
model.id.includes("opus-4-6") ||
model.id.includes("opus-4.6") ||
model.id.includes("opus-4-7") ||
model.id.includes("opus-4.7")
) {
return true;
}
export function getSupportedThinkingLevels<TApi extends Api>(model: Model<TApi>): ModelThinkingLevel[] {
if (!model.reasoning) return ["off"];
return false;
return EXTENDED_THINKING_LEVELS.filter((level) => {
const mapped = model.thinkingLevelMap?.[level];
if (mapped === null) return false;
if (level === "xhigh") return mapped !== undefined;
return true;
});
}
export function clampThinkingLevel<TApi extends Api>(
model: Model<TApi>,
level: ModelThinkingLevel,
): ModelThinkingLevel {
const availableLevels = getSupportedThinkingLevels(model);
if (availableLevels.includes(level)) return level;
const requestedIndex = EXTENDED_THINKING_LEVELS.indexOf(level);
if (requestedIndex === -1) return availableLevels[0] ?? "off";
for (let i = requestedIndex; i < EXTENDED_THINKING_LEVELS.length; i++) {
const candidate = EXTENDED_THINKING_LEVELS[i];
if (availableLevels.includes(candidate)) return candidate;
}
for (let i = requestedIndex - 1; i >= 0; i--) {
const candidate = EXTENDED_THINKING_LEVELS[i];
if (availableLevels.includes(candidate)) return candidate;
}
return availableLevels[0] ?? "off";
}
/**