73 lines
2.8 KiB
TypeScript
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);
|
|
});
|