fix(ai): send fixed low top-level effort with Anthropic per-message effort

Organizations can cap effort, and the previous fixed top-level high was
rejected even when the requested level was low or medium.

closes #10063
This commit is contained in:
David Brailovsky 2026-10-23 12:11:37 +02:00
parent 3141dfdcf4
commit e3bc05e871
3 changed files with 7 additions and 3 deletions

View file

@ -5,6 +5,7 @@
### Fixed
- Fixed Claude models that accept mid-conversation system messages rejecting a session with a 400 (`role 'system' must precede an 'assistant' message`) when a system update was followed by an assistant reply with nothing to send to Anthropic, such as an empty reply or another model's reasoning-only reply ([#11091](https://github.com/earendil-works/pi/issues/11091))
- Fixed Claude models with mid-conversation effort failing with `Invalid effort level` on accounts whose organization caps effort below `high`, even at `low` or `medium` thinking, by sending a fixed `low` top-level effort ([#10063](https://github.com/earendil-works/pi/issues/10063))
## [1.4.0] - 2026-10-21

View file

@ -1300,7 +1300,10 @@ function buildParams(
display: options?.thinkingDisplay ?? "summarized",
block_binding: { prefix_mismatch_behavior: "drop_block" },
};
params.output_config = { effort: "high" };
// Effort markers set the level for every reply. The top-level effort is part of the cached
// prompt, so it stays fixed. It is "low" because organizations can cap effort and reject
// requests containing any level above the cap.
params.output_config = { effort: "low" };
} else if (model.reasoning && options?.thinkingEnabled) {
// Default to "summarized" so Opus 4.7 and Mythos Preview behave like
// older Claude 4 models (whose API default is also "summarized").

View file

@ -108,8 +108,8 @@ describe("Anthropic mid-conversation effort", () => {
content: [],
output_config: { effort: "high" },
});
expect(first.payload.output_config).toEqual({ effort: "high" });
expect(second.payload.output_config).toEqual({ effort: "high" });
expect(first.payload.output_config).toEqual({ effort: "low" });
expect(second.payload.output_config).toEqual({ effort: "low" });
expect(second.payload.thinking).toEqual({
type: "adaptive",
display: "summarized",