fix: add budgetTokens fallback for Agent thinking compatibility#13575
Merged
fix: add budgetTokens fallback for Agent thinking compatibility#13575
Conversation
…nt compatibility
When `findTokenLimit()` cannot determine a model's token limit, `getThinkingBudget()`
returns `undefined`, causing `getAnthropicReasoningParams()` to emit
`{ thinking: { type: 'enabled' } }` without `budgetTokens`. The Claude Agent SDK
then silently converts this to `--thinking adaptive`, which non-Anthropic upstream
providers do not support (they only accept 'enabled'/'disabled'), resulting in a
400 error.
Add a fallback default of 8192 for `budgetTokens` in both affected code paths to
ensure `type: 'enabled'` always includes a valid budget.
Closes #13574
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Signed-off-by: icarus <[email protected]>
Extract shared budget computation into `computeBudgetTokens()` so both `getThinkingBudget()` and the new `getFallbackBudgetTokens()` share identical logic, preventing drift between the two code paths. Replace hardcoded 8192 fallback with `getFallbackBudgetTokens()` that uses a conservative token limit (min: 1024, max: 16384) scaled by EFFORT_RATIO, producing values proportional to the selected effort level. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> Signed-off-by: icarus <[email protected]>
5 tasks
DeJeune
approved these changes
Mar 18, 2026
Contributor
There was a problem hiding this comment.
This change fixes the compatibility issue cleanly by guaranteeing budgetTokens is always present when thinking is enabled, which prevents the Claude Agent SDK from silently switching into adaptive mode on non-Anthropic upstreams.
Pulling the shared math into computeBudgetTokens() is also a good refactor because it keeps the normal and fallback budget paths aligned and reduces the chance of future drift.
I did not find any blocking issues in the current patch. A follow-up test covering the unknown-token-limit path would still be valuable to make sure this regression does not come back later.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> Signed-off-by: icarus <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
Before this PR:
getAnthropicReasoningParams()could return{ thinking: { type: 'enabled' } }withoutbudgetTokenswhenfindTokenLimit()couldn't determine a model's token limit. The Claude Agent SDK then silently converted this to--thinking adaptive, which non-Anthropic upstream providers (e.g., cherryin proxy) do not support, resulting in a 400 error:"thinking type should be enabled or disabled".After this PR:
computeBudgetTokens(), used by bothgetThinkingBudget()and the newgetFallbackBudgetTokens()to prevent drift.getThinkingBudget()returnsundefined, fall back togetFallbackBudgetTokens()which uses a conservative token limit (min: 1024, max: 16384) scaled byEFFORT_RATIO, producing values proportional to the selected effort level.Fixes #13573
Why we need it and why it was done in this way
The following tradeoffs were made:
A conservative fallback max of
16384was chosen — small enough to work across most providers, large enough for meaningful reasoning at higher effort levels.The following alternatives were considered:
8192) — rejected because it ignores effort level and could be too large forlowor too small forhigh.getThinkingBudget()signature to never returnundefined— rejected to avoid changing the existing contract for other callers.enabledmode.Links to places where the discussion took place: #13573, #13574
Breaking changes
None.
Special notes for your reviewer
AnthropicProviderOptionswherebudgetTokensis optional) and the Claude Agent SDK (wherebudgetTokensis effectively required fortype: 'enabled').getAnthropicReasoningParamswas designed for the AI SDK but is reused in the Agent flow.src/renderer/src/aiCore/utils/reasoning.tsis modified.getThinkingBudget()signature and return type are unchanged.Checklist
/gh-pr-review,gh pr diff, or GitHub UI) before requesting review from othersRelease note