fix(cli): trigger auto-compaction at the configured context threshold - #13340
fix(cli): trigger auto-compaction at the configured context threshold#13340rakshith1928 wants to merge 10 commits into
Conversation
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (1 files)
Previous Review Summaries (6 snapshots, latest commit 030412e)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 030412e)Status: No Issues Found | Recommendation: Merge Files Reviewed (3 files)
Previous review (commit e28ec56)Status: No Issues Found | Recommendation: Merge Files Reviewed (5 files)
Previous review (commit 54d7675)Status: No Issues Found | Recommendation: Merge Files Reviewed (4 files)
Previous review (commit f607bf0)Status: No Issues Found | Recommendation: Merge Files Reviewed (4 files)
Previous review (commit c5180fc)Status: No Issues Found | Recommendation: Merge Files Reviewed (1 files)
Previous review (commit c1689db)Status: No Issues Found | Recommendation: Merge Files Reviewed (4 files)
Reviewed by grok-4.6 · Input: 66.4K · Output: 3.7K · Cached: 170.4K Review guidance: REVIEW.md from base branch |
|
Thanks for digging into this. The input-vs-context mismatch is real, but I do not think we should merge this approach yet. It fixes the repeated- The main issue is The provider-reported value also cannot replace the current outgoing estimate with The provider baseline and local estimate are not measurements of the same thing once opaque media and encrypted reasoning are normalized out. We need to account for content added since the provider report, not only take the larger number. There is also a product-semantics mismatch in the PR description. For a 400k context / 272k input model, Can we revise this so that we:
I locally combined current |
The preflight threshold was applied to model.limit.input while the UI displays usage against limit.context, and it compared an inflated chars/4 x 1.3 estimate instead of provider-reported tokens. On models with input < context (GPT-5 family), 80% effectively fired at ~40% displayed usage. Apply threshold_percent to the context window and anchor shouldCompact to the reported token count from the last finished turn, keeping the deflated estimate as a floor for huge pastes. Fixes Kilo-Org#13335
…ontent Address review on the first iteration: dividing the estimate by its safety factor under-counted dense CJK/code payloads ~3x, and taking max(reported, estimate) ignored content added since the provider report once encrypted reasoning is normalized out of local estimates. The preflight now projects the next request as the last finished turn's provider-reported count plus the inflated estimate of messages added after it, falling back to the whole-payload estimate when no baseline exists (first turn, post-compaction, zero-usage reports). threshold_percent applies to limit.context, matching the UI. The 1.3 factor stays everywhere; conservative accounting preserved. On models whose input limit sits below their context window, the reserved input ceiling still triggers before a high configured percentage.
c5180fc to
f607bf0
Compare
RevisionPushed revision [
|
|
Thanks @rakshith1928 , can you have another look at those comments? Interrupted responses hide uncounted tool output. New system content and tool schemas bypass the threshold. Output-only usage is treated as complete context usage. Thanks in advance |
A cancelled or errored assistant trails the last finished one without a finish marker. The payload then replays tool output and partial text that the provider report never covered, and the tail estimate starts after the last serialized assistant so it cannot count them either. The stale baseline plus tail-only projection under-counted and skipped compaction past the threshold. When the last assistant is not the finished one, reportedContextTokens is now undefined and the full conservative estimate decides alone.
The provider-reported baseline covered only the previous request's messages, so new system prompts and grown tool schemas bypassed the threshold. The projection now adds the current system + tool estimate on top, and a report without prompt-side usage (e.g. completion tokens only) no longer anchors the baseline.
|
All three are addressed on the branch:
|

Issue
Fixes #13335
Context
Auto-compaction was firing on message send long before the configured context threshold — with
threshold_percent: 80, compaction hit around 40% of the context bar, inconsistently. Two compounding causes in the preflight check:threshold_percenttomodel.limit.input || model.limit.context. For models with a separate input limit (GPT-5 family: 272k input of a 400k window), "80%" was really 54% of the displayed bar.chars/4 × 1.3+ tool schemas), whose overshoot varies with content type — hence the randomness. Since the check defers during tool loops, it landed on the next user message: the reported "triggers on send" pattern.Implementation
packages/opencode/src/kilocode/session/overflow.tslimit()now appliesthreshold_percenttomodel.limit.context— the denominator the UI uses.Math.min(usable, cap)is unchanged, so the usable input limit remains the hard ceiling.measure()additionally returnstail: the 1.3×-inflated estimate of messages added after the last assistant reply, i.e. the content the provider has not counted yet. Tool schemas stay out oftailsince the baseline already includes them.shouldCompact()projects the next request asreported + tail, wherereportedis the provider-reported count from the last finished turn. Without a baseline (first turn, post-compaction summary, zero-usage report) the full outgoing estimate decides alone. The safety factor stays everywhere — dense CJK/code still over-count rather than under-count, which matters since fix(cli): preserve output budget for encrypted reasoning #13349 normalizes encrypted reasoning out of local estimates, so neither the raw estimate nor the stale baseline alone sees reality.On models whose input limit sits below their context window (GPT-5: 272k of 400k), the reserved input ceiling fires before a high threshold — 80% triggers around 63% of the displayed bar. That's the model's physical wall, not policy; lower thresholds stay predictable.
packages/opencode/src/session/llm.tsPasses
reported: input.reportedContextTokensandtail: usage.tailinto the preflight decision — both values already existed onStreamInput/measure(), no new plumbing.Tests (
test/kilocode/session-overflow.test.ts) cover the false-negative regressions and the effective ceiling below.Screenshots / Video
Config:
How to Test
Manual/local verification
bun test ./test/kilocode/session-overflow.test.tsfrompackages/opencode/: 36 pass, including new regressions for dense CJK payloads, a large new message on top of a high reported baseline with encrypted reasoning history, the input-limited effective ceiling, and zero-usage reports falling back to the estimate path. The false-negative cases were written failing before the fix .Reviewer test steps
compaction.threshold_percent: 80; use a model with an input limit below its context window (e.g. GPT-5).Blocked checks and substitute verification
Checklist
Get in Touch
@TRAVIX26 discord