Skip to content

feat(core): fit output limits to the context window - #51021

Closed
rekram1-node wants to merge 1 commit into
v2from
max-output-tokens
Closed

rekram1-node wants to merge 1 commit into
v2from
max-output-tokens

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Issue for this PR

Closes #46595
Closes #47398

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Ready to merge. The fixes for thinking budgets that break once a limit is sent are merged: #51150, #51151, #51154, #51157, #51189 and #51190.

V2 only sent an output limit on Anthropic, a fixed 32k. Every other route got the provider default: 4,096 on Bedrock Claude, 2,000 on Bedrock Nova, and 4,096 on many OpenAI-compatible proxies. Long thinking turns were cut off and ended with no text.

Default limit. SessionModelRequest.prepare now sets an output limit for main steps and compaction summaries:

min(catalog output limit (32k if missing), cap, context − measured prompt − 1.15 × estimated prompt)
  • Cap: 256k for main steps, the largest real limit we've measured (DeepSeek allows 393,216), and 32k for compaction summaries.
  • Prompt size: the same one compaction uses. The part the provider reported at the latest response is exact. Text added since is estimated at 4 characters per token, which can run low on dense text, so that part counts 15% extra.
  • Hooks: the value is pre-filled into the hook options, so plugins can change or remove it.
  • OpenAI: the OpenAI plugin removes it, as in V1. The ChatGPT backend rejects it, and OpenAI counts it against rate limits.
  • Titles and generate: they send no limit and keep the provider default, because their reasoning is hard to budget.
  • Compaction trigger: unchanged.

There is no recovery when a provider rejects the limit. The cap and the fit keep requests within what providers accept. A wrong catalog value surfaces as the provider's error until models.dev or the user's config is fixed.

Overlaps with #47532, which sets the catalog limit.output but has no context fit.

Not in this PR: recovering when a response actually hits the limit, such as a thinking-only response or a cut-off tool call.

How did you verify your code works?

  • bun run check passes.
  • The packages/ai suite passes, and so do the affected packages/core session and plugin suites.
  • New tests cover:
    • the limit policy, the per-kind caps and the context fit;
    • hook override and removal;
    • the OpenAI opt-out.
  • Live check: I ran a server from this branch against every connected provider. A plugin logged the output-limit and thinking fields of each outgoing request.
    • Catalog sweep: one short prompt to each of 1,923 models across 42 providers. All 1,248 successful requests carried a limit: 808 above 64k, 369 above 128k, and 151 at the 256k cap.
    • End-to-end: a tool-using prompt, an automatic title and a manual compaction on one or more models per provider, including thinking variants. It passed on Anthropic, Bedrock Claude and Nova Pro, Copilot, Google and Vertex Gemini, Vercel, OpenRouter, xAI, DeepSeek, Moonshot, MiniMax, Mistral, Cerebras, Baseten, Fireworks, DeepInfra, Venice, Zen and Go.
    • Context fit: a Mistral step with a 262k context sent 253,504, then 251,154 once the provider had reported the real prompt size.

Screenshots / recordings

N/A

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@rekram1-node
rekram1-node force-pushed the max-output-tokens branch 6 times, most recently from 39f95b1 to a4155f1 Compare September 24, 2026 05:39
@rekram1-node
rekram1-node force-pushed the max-output-tokens branch 3 times, most recently from aab85ea to ea4a18b Compare September 24, 2026 15:10
@rekram1-node
rekram1-node force-pushed the max-output-tokens branch 4 times, most recently from a0dcc13 to db84fed Compare September 24, 2026 20:33
@rekram1-node

Copy link
Copy Markdown
Collaborator Author

Superseded by #51238, which now includes this change and its tests in the audited single PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant