Files
diegosouzapw--omniroute/tests/unit/claude-adaptive-sampling-params.test.ts
2026-07-13 13:39:12 +08:00

73 lines
2.8 KiB
TypeScript

/**
* Claude Opus 4.7+/Fable 5 sampling-param strip + adaptive-only flag.
*
* Anthropic's Opus 4.7+ generation rejects non-default `temperature`/`top_p`/`top_k` with a
* 400 (sampling is fixed; reasoning is steered by output_config.effort). These tests pin both
* the registry `unsupportedParams` that drive the strip at the chatCore dispatch point and
* the `isAdaptiveThinkingOnly` model flag — with regression guards that pre-4.7 models keep
* accepting sampling params and manual thinking.
*/
import test from "node:test";
import assert from "node:assert/strict";
import { getUnsupportedParams } from "../../open-sse/config/providerRegistry.ts";
import { isAdaptiveThinkingOnly } from "../../src/shared/constants/modelSpecs.ts";
const SAMPLING = ["temperature", "top_p", "top_k"];
test("claude registry strips temperature/top_p/top_k for Opus 4.7+/Fable 5", () => {
for (const model of ["claude-opus-4-8", "claude-opus-4-7", "claude-fable-5"]) {
const unsupported = getUnsupportedParams("claude", model);
for (const param of SAMPLING) {
assert.ok(
unsupported.includes(param),
`${model} must list ${param} as unsupported (400 on Anthropic otherwise)`
);
}
}
});
test("anthropic registry (dotted ids) strips sampling params for Opus 4.7", () => {
const unsupported = getUnsupportedParams("anthropic", "claude-opus-4.7");
for (const param of SAMPLING) {
assert.ok(unsupported.includes(param), `claude-opus-4.7 must list ${param} as unsupported`);
}
});
test("pre-4.7 Claude models still accept sampling params (regression guard)", () => {
for (const [provider, model] of [
["claude", "claude-opus-4-6"],
["claude", "claude-opus-4-5-20251101"],
["claude", "claude-sonnet-4-5-20250929"],
["claude", "claude-haiku-4-5-20251001"],
["anthropic", "claude-opus-4.6"],
] as const) {
const unsupported = getUnsupportedParams(provider, model);
for (const param of SAMPLING) {
assert.ok(
!unsupported.includes(param),
`${provider}/${model} must NOT strip ${param} — it still accepts sampling`
);
}
}
});
test("isAdaptiveThinkingOnly is true only for Opus 4.7+/Fable 5", () => {
for (const model of ["claude-opus-4-8", "claude-opus-4-7", "claude-fable-5"]) {
assert.equal(isAdaptiveThinkingOnly(model), true, `${model} is adaptive-only`);
}
for (const model of [
"claude-opus-4-6",
"claude-opus-4-5-20251101",
"claude-sonnet-4-6",
"claude-haiku-4-5-20251001",
]) {
assert.equal(isAdaptiveThinkingOnly(model), false, `${model} still supports manual thinking`);
}
assert.equal(isAdaptiveThinkingOnly(null), false);
assert.equal(isAdaptiveThinkingOnly(""), false);
});
test("isAdaptiveThinkingOnly resolves Bedrock/dated aliases", () => {
assert.equal(isAdaptiveThinkingOnly("anthropic.claude-opus-4-8"), true);
});