|
| 1 | +// Coverage for every cell of the model x thinking-shape matrix the live |
| 2 | +// Messages API enforces (verified 2026-04-29). The helper is the single |
| 3 | +// source of truth for SDK `query()` thinking options across chat, judge, |
| 4 | +// runtime, and reflection callsites. |
| 5 | + |
| 6 | +import { describe, expect, test } from "bun:test"; |
| 7 | +import { JUDGE_MODEL_HAIKU, JUDGE_MODEL_OPUS, JUDGE_MODEL_SONNET } from "../../evolution/judge-models.ts"; |
| 8 | +import { getThinkingConfig } from "../thinking-config.ts"; |
| 9 | + |
| 10 | +describe("getThinkingConfig", () => { |
| 11 | + test("Opus 4.7 returns adaptive (Opus 4.7 rejects manual enabled with 400)", () => { |
| 12 | + expect(getThinkingConfig(JUDGE_MODEL_OPUS)).toEqual({ type: "adaptive" }); |
| 13 | + expect(getThinkingConfig("claude-opus-4-7")).toEqual({ type: "adaptive" }); |
| 14 | + }); |
| 15 | + |
| 16 | + test("Opus 4.6 returns adaptive (recommended; manual is deprecated)", () => { |
| 17 | + expect(getThinkingConfig("claude-opus-4-6")).toEqual({ type: "adaptive" }); |
| 18 | + }); |
| 19 | + |
| 20 | + test("Sonnet 4.6 returns adaptive (recommended; manual still functional)", () => { |
| 21 | + expect(getThinkingConfig(JUDGE_MODEL_SONNET)).toEqual({ type: "adaptive" }); |
| 22 | + expect(getThinkingConfig("claude-sonnet-4-6")).toEqual({ type: "adaptive" }); |
| 23 | + }); |
| 24 | + |
| 25 | + test("Mythos preview returns adaptive", () => { |
| 26 | + expect(getThinkingConfig("claude-mythos-preview")).toEqual({ type: "adaptive" }); |
| 27 | + }); |
| 28 | + |
| 29 | + test("Haiku 4.5 returns enabled + budgetTokens (Haiku rejects adaptive with 400)", () => { |
| 30 | + const config = getThinkingConfig(JUDGE_MODEL_HAIKU); |
| 31 | + expect(config.type).toBe("enabled"); |
| 32 | + if (config.type === "enabled") { |
| 33 | + expect(config.budgetTokens).toBeGreaterThan(0); |
| 34 | + } |
| 35 | + }); |
| 36 | + |
| 37 | + test("older Haiku 3.x returns enabled + budgetTokens", () => { |
| 38 | + const config = getThinkingConfig("claude-haiku-3-5"); |
| 39 | + expect(config.type).toBe("enabled"); |
| 40 | + }); |
| 41 | + |
| 42 | + test("older Sonnet 3.x returns enabled + budgetTokens", () => { |
| 43 | + const config = getThinkingConfig("claude-sonnet-3-7"); |
| 44 | + expect(config.type).toBe("enabled"); |
| 45 | + }); |
| 46 | + |
| 47 | + test("legacy Opus 4.5 returns enabled + budgetTokens", () => { |
| 48 | + const config = getThinkingConfig("claude-opus-4-5"); |
| 49 | + expect(config.type).toBe("enabled"); |
| 50 | + }); |
| 51 | + |
| 52 | + test("undefined model defaults to adaptive (safe for all new models)", () => { |
| 53 | + expect(getThinkingConfig(undefined)).toEqual({ type: "adaptive" }); |
| 54 | + }); |
| 55 | + |
| 56 | + test("null model defaults to adaptive", () => { |
| 57 | + expect(getThinkingConfig(null)).toEqual({ type: "adaptive" }); |
| 58 | + }); |
| 59 | + |
| 60 | + test("empty string defaults to adaptive", () => { |
| 61 | + expect(getThinkingConfig("")).toEqual({ type: "adaptive" }); |
| 62 | + }); |
| 63 | + |
| 64 | + test("unknown future model defaults to adaptive", () => { |
| 65 | + // Every new model since Opus 4.7 has been adaptive-only, so when |
| 66 | + // we do not recognise the prefix we send adaptive. A wrong guess |
| 67 | + // returns a clear 400 with the required shape, which is preferable |
| 68 | + // to silent breakage in reflection. |
| 69 | + expect(getThinkingConfig("claude-future-model-2027")).toEqual({ type: "adaptive" }); |
| 70 | + }); |
| 71 | + |
| 72 | + test("provider-prefixed names still match by suffix-free comparison fail-safe", () => { |
| 73 | + // Some operators set `model: "anthropic/claude-haiku-4-5"` via |
| 74 | + // LiteLLM. The helper currently does prefix-match on the bare |
| 75 | + // Anthropic id. If a slash-prefix is used, we fall through to |
| 76 | + // adaptive default, which is the safer of the two failure modes |
| 77 | + // (adaptive will 400 with a clear error on Haiku rather than |
| 78 | + // silently downgrading thinking). |
| 79 | + expect(getThinkingConfig("anthropic/claude-haiku-4-5")).toEqual({ type: "adaptive" }); |
| 80 | + }); |
| 81 | + |
| 82 | + test("returned object is a fresh value (callers may spread it)", () => { |
| 83 | + const a = getThinkingConfig(JUDGE_MODEL_OPUS); |
| 84 | + const b = getThinkingConfig(JUDGE_MODEL_OPUS); |
| 85 | + expect(a).toEqual(b); |
| 86 | + }); |
| 87 | +}); |
0 commit comments