Skip to content

feat: cap completion tokens to remaining context window for chat-completions - #1131

Merged
wbxl2000 merged 5 commits into
mainfrom
feat/dynamic-completion-budget
Jun 26, 2026
Merged

feat: cap completion tokens to remaining context window for chat-completions#1131
wbxl2000 merged 5 commits into
mainfrom
feat/dynamic-completion-budget

Conversation

@wbxl2000

@wbxl2000 wbxl2000 commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

N/A — no prior issue; the problem is described below.

Problem

Chat-completions providers (Kimi and OpenAI-compatible third parties) reject requests where input + max_tokens exceeds the model context window, or where max_tokens exceeds a fixed ceiling (e.g. third-party endpoints that enforce [1, 131072]). The completion budget previously defaulted to the full context-window size, which triggered these errors once the context grew large.

What changed

  • withMaxCompletionTokens now accepts an optional { usedContextTokens, maxContextTokens }, so each provider can tighten the caller-supplied cap to its own transport constraints.
  • Kimi sizes the cap to max_context_size - usedContextTokens; OpenAI Legacy additionally clamps to 128k.
  • The main loop passes the API-reported token usage of the latest step, so the cap reflects the space actually left. Compaction is intentionally left uncapped so it can always produce a summary.
  • Anthropic, Google GenAI and OpenAI Responses are unaffected, since their max_tokens is not subject to the input+output window constraint.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Jun 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c3eff4c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@moonshot-ai/kosong Minor
@moonshot-ai/agent-core Patch
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jun 26, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@c3eff4c
npx https://pkg.pr.new/@moonshot-ai/kimi-code@c3eff4c

commit: c3eff4c

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b75c6451e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

reservedContextSize: this.agent.kimiConfig?.loopControl?.reservedContextSize,
}),
capability: this.agent.config.modelCapabilities,
usedContextTokens: this.agent.context.tokenCount,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Base compaction caps on compacted input

During auto/overflow compaction, messagesToCompact can be much smaller than the live history, but this passes the live context.tokenCount into the Kimi/OpenAI clamp. When compaction is started after the session has reached or exceeded max_context_size, the provider turns that into max_context_tokens - usedContextTokens (then 1), so the summary request is forced to a one-token completion and repeatedly fails as truncated instead of recovering the context. Compute the used tokens from the actual compaction request after messagesToCompact is chosen, or avoid this clamp for compaction.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c96440a — reverted the usedContextTokens passthrough for compaction so the summary request keeps an uncapped budget and can't be forced to a one-token completion. Compaction now matches its previous behavior.

capability: this.config.modelCapabilities,
generate: this.generate,
completionBudgetConfig,
usedContextTokens: () => this.context.tokenCount,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Count pending messages when clamping completions

context.tokenCount is only updated from the last sealed step.end; it does not include the just-appended user prompt, injected reminders, or tool results that buildMessages() sends on this request, and it is 0 on the first turn. For Kimi/OpenAI this means the remaining-window clamp can still set max_tokens too high whenever the current prompt/tool output is large, so the input+max_tokens overflow this change is meant to avoid still occurs. Pass a count for the current request instead.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional — we use the sealed API usage from the last step rather than an estimate, accepting a looser cap on the first turn or after large pending messages in exchange for no estimation error.

@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@wbxl2000
wbxl2000 force-pushed the feat/dynamic-completion-budget branch from c96440a to 496b298 Compare June 26, 2026 09:28
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 496b298d7a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

capability: this.config.modelCapabilities,
generate: this.generate,
completionBudgetConfig,
usedContextTokens: () => this.context.tokenCount,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Account for pending context in completion cap

Here usedContextTokens reads ContextMemory.tokenCount, but the current user prompt, hook injections, and tool results are appended before runStepLoop and are only reflected in tokenCountWithPending until step.end records provider usage. On a large new prompt/tool result after the last API call (and on the first turn, where tokenCount is still 0), Kimi/OpenAI providers still size max_completion_tokens to nearly the full window, so input + max_tokens can exceed max_context_size and the overflow this change is meant to prevent still happens.

Useful? React with 👍 / 👎.

@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3eff4cb1c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

capability: this.config.modelCapabilities,
generate: this.generate,
completionBudgetConfig,
usedContextTokens: () => this.context.tokenCount,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include pending messages in the cap calculation

When a new user prompt, steer message, injection, or tool result has been appended since the last sealed step, context.tokenCount still only reflects the API-reported usage from the previous completed step; those pending messages are nevertheless included in the next params.messages. For near-window inputs this undercounts the actual request size, so withMaxCompletionTokens can still send max_tokens/max_completion_tokens larger than the remaining context window and the chat-completions API rejects the request. Use tokenCountWithPending or an equivalent estimate for the in-flight prompt when sizing this cap.

Useful? React with 👍 / 👎.

@wbxl2000
wbxl2000 force-pushed the feat/dynamic-completion-budget branch from 51913c8 to c3eff4c Compare June 26, 2026 10:51
@wbxl2000
wbxl2000 merged commit 76c643b into main Jun 26, 2026
17 checks passed
@wbxl2000
wbxl2000 deleted the feat/dynamic-completion-budget branch June 26, 2026 11:12
@github-actions github-actions Bot mentioned this pull request Jun 26, 2026
7723qqq pushed a commit to 7723qqq/kimi-code that referenced this pull request Jul 11, 2026
…letions (MoonshotAI#1131)

* feat: cap completion tokens to remaining context window for chat-completions

* test: cover dynamic completion budget for kimi and openai-legacy

* fix: leave compaction budget uncapped to avoid one-token summaries

* fix: add hookCount to plugins-selector test mocks

(cherry picked from commit 76c643b)
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