Files
openclaw/src/auto-reply/thinking.test.ts
Sid c9f0d6ac8e feat(agents): support thinkingDefault: "adaptive" for Anthropic models (#31227)
* feat(agents): support `thinkingDefault: "adaptive"` for Anthropic models

Anthropic's Opus 4.6 and Sonnet 4.6 support adaptive thinking where the
model dynamically decides when and how much to think.  This is now
Anthropic's recommended mode and `budget_tokens` is deprecated on these
models.

Add "adaptive" as a valid thinking level:
- Config: `agents.defaults.thinkingDefault: "adaptive"`
- CLI: `/think adaptive` or `/think auto`
- Pi SDK mapping: "adaptive" → "medium" effort at the pi-agent-core
  layer, which the Anthropic provider translates to
  `thinking.type: "adaptive"` with `output_config.effort: "medium"`
- Provider fallbacks: OpenRouter and Google map "adaptive" to their
  respective "medium" equivalents

Closes #30880

Made-with: Cursor

* style(changelog): format changelog with oxfmt

* test(types): fix strict typing in runtime/plugin-context tests

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 03:52:02 +00:00

97 lines
3.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
listThinkingLevelLabels,
listThinkingLevels,
normalizeReasoningLevel,
normalizeThinkLevel,
} from "./thinking.js";
describe("normalizeThinkLevel", () => {
it("accepts mid as medium", () => {
expect(normalizeThinkLevel("mid")).toBe("medium");
});
it("accepts xhigh aliases", () => {
expect(normalizeThinkLevel("xhigh")).toBe("xhigh");
expect(normalizeThinkLevel("x-high")).toBe("xhigh");
expect(normalizeThinkLevel("x_high")).toBe("xhigh");
expect(normalizeThinkLevel("x high")).toBe("xhigh");
});
it("accepts extra-high aliases as xhigh", () => {
expect(normalizeThinkLevel("extra-high")).toBe("xhigh");
expect(normalizeThinkLevel("extra high")).toBe("xhigh");
expect(normalizeThinkLevel("extra_high")).toBe("xhigh");
expect(normalizeThinkLevel(" extra high ")).toBe("xhigh");
});
it("does not over-match nearby xhigh words", () => {
expect(normalizeThinkLevel("extra-highest")).toBeUndefined();
expect(normalizeThinkLevel("xhigher")).toBeUndefined();
});
it("accepts on as low", () => {
expect(normalizeThinkLevel("on")).toBe("low");
});
it("accepts adaptive and auto aliases", () => {
expect(normalizeThinkLevel("adaptive")).toBe("adaptive");
expect(normalizeThinkLevel("auto")).toBe("adaptive");
expect(normalizeThinkLevel("Adaptive")).toBe("adaptive");
});
});
describe("listThinkingLevels", () => {
it("includes xhigh for codex models", () => {
expect(listThinkingLevels(undefined, "gpt-5.2-codex")).toContain("xhigh");
expect(listThinkingLevels(undefined, "gpt-5.3-codex")).toContain("xhigh");
expect(listThinkingLevels(undefined, "gpt-5.3-codex-spark")).toContain("xhigh");
});
it("includes xhigh for openai gpt-5.2", () => {
expect(listThinkingLevels("openai", "gpt-5.2")).toContain("xhigh");
});
it("includes xhigh for github-copilot gpt-5.2 refs", () => {
expect(listThinkingLevels("github-copilot", "gpt-5.2")).toContain("xhigh");
expect(listThinkingLevels("github-copilot", "gpt-5.2-codex")).toContain("xhigh");
});
it("excludes xhigh for non-codex models", () => {
expect(listThinkingLevels(undefined, "gpt-4.1-mini")).not.toContain("xhigh");
});
it("always includes adaptive", () => {
expect(listThinkingLevels(undefined, "gpt-4.1-mini")).toContain("adaptive");
expect(listThinkingLevels("anthropic", "claude-opus-4-6")).toContain("adaptive");
});
});
describe("listThinkingLevelLabels", () => {
it("returns on/off for ZAI", () => {
expect(listThinkingLevelLabels("zai", "glm-4.7")).toEqual(["off", "on"]);
});
it("returns full levels for non-ZAI", () => {
expect(listThinkingLevelLabels("openai", "gpt-4.1-mini")).toContain("low");
expect(listThinkingLevelLabels("openai", "gpt-4.1-mini")).not.toContain("on");
});
});
describe("normalizeReasoningLevel", () => {
it("accepts on/off", () => {
expect(normalizeReasoningLevel("on")).toBe("on");
expect(normalizeReasoningLevel("off")).toBe("off");
});
it("accepts show/hide", () => {
expect(normalizeReasoningLevel("show")).toBe("on");
expect(normalizeReasoningLevel("hide")).toBe("off");
});
it("accepts stream", () => {
expect(normalizeReasoningLevel("stream")).toBe("stream");
expect(normalizeReasoningLevel("streaming")).toBe("stream");
});
});