Skip to content

fix: count reasoning tokens in context-usage display estimates (#371) - #374

Open
ranxianglei wants to merge 2 commits into
masterfrom
2026-09-08_reasoning-in-context-estimate
Open

fix: count reasoning tokens in context-usage display estimates (#371)#374
ranxianglei wants to merge 2 commits into
masterfrom
2026-09-08_reasoning-in-context-estimate

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Problem

The context-usage display estimators count only text + tool message parts and skip reasoning parts entirely, while the real usage formula includes reasoning (lib/token-utils.ts:44: input + cacheRead + cacheWrite + output + reasoning). Two duplicated code paths are affected:

  1. estimateContextComposition (lib/messages/inject/utils.ts:586) — powers the nudge Breakdown: line.
  2. collectVisibleMessages + renderOverview (lib/compress/status.ts:125/:185) — powers the acp_status overview (CONTEXT BREAKDOWN line). Note: acp_status does not call estimateContextComposition (the import at status.ts:9 is dead) — fixing only the issue's suggested location would not fix the acp_status display.

Result: displayed percentages systematically undercount real usage, and the largest residual component (reasoning — #368) is invisible in the display.

Not affected: /acp context command — its TOTAL comes from API-reported tokens and already includes reasoning. The decision path (when to nudge) also already uses the API formula; this is a display-only fix.

Solution

Count reasoning parts (len/4 heuristic, same as text parts) as their own visible category in both estimators:

  • ContextComposition gains reasoningTokens; total = system + tool + summary + message + reasoning. Reasoning feeds msgTotal (→ protectedTokens, largestRanges reflect full footprint) but not messageTokens (text/code classification stays clean).
  • Nudge breakdown line gains | N reasoning (Q%).
  • acp_status overview: VisibleMessageInfo gains a reasoning field (kept separate from tokens = text+tool to avoid double counting); inclusion gate widened to tokens > 0 || reasoning > 0 (reasoning-only messages now visible); overview total + CONTEXT BREAKDOWN line gain the reasoning category; per-message drilldown sort/totals/lines use full footprint (tokens + reasoning).
  • System prompt CONTEXT BREAKDOWN example + category list updated (example percentages now sum to 100%).

Display-only: no persisted-state, internal-tag, config, or decision-path changes.

Files

  • lib/messages/inject/utils.tsContextComposition + estimateContextComposition reasoning branch + total.
  • lib/messages/inject/inject.ts — nudge breakdown line.
  • lib/compress/status.tsVisibleMessageInfo, collectVisibleMessages, renderOverview, renderUncompressedDrilldown.
  • lib/prompts/system.ts — breakdown example + bullets.
  • tests/inject-utils-pure.test.ts (+4), tests/protection-aware-stats.test.ts (+1), tests/acp-status.test.ts (+3, plus 2 pre-existing vacuous tests fixed — their partial mocks were dropped by filterMessages so they passed with zero visible messages), tests/inject.test.ts (+1 rendered nudge-line test).
  • devlog/2026-09-08_reasoning-in-context-estimate/ — REQ / WORKLOG.

Testing

  • 1086/1086 tests pass (was 1077 on master; +9 new). Typecheck clean, build clean.
  • All 9 new tests verified to fail on the pre-fix code (empirically checked by the test reviewer against base 9b7adfd).
  • Dual-agent review (code §5.3 + tests §5.6): both APPROVE; all actionable findings addressed (rendered nudge-line test, vacuous pre-existing tests, exact-value assertion, example percentages).

Known interactions / documented non-goals

  • PR feat: strip reasoning from protected-exempt historical messages (gated) #370 (stripProtectedReasoning, open): its pass runs BEFORE injectCompressNudges in lib/hooks.ts, so post-merge the nudge-path estimator naturally matches sent content. acp_status reads raw DB messages and will still show request-time-stripped reasoning — feat: strip reasoning from protected-exempt historical messages (gated) #370-side concern, out of scope here.
  • Composition-vs-range divergence (new, minor): buildCompressibleRanges range tokens intentionally still exclude reasoning (ranges = compressible amounts; the pipeline's min-size check countMessageCharacters also excludes reasoning — adding it there risks phantom "Range too small" rejections, chore: bump version to 1.6.0 #37). Consequence: the nudge's "Effective compressible: ~X" and the overview total now include reasoning while per-range lines don't. Candidate follow-up issue.
  • Per-message dcp-message-id token annotation (countMessageCharacters) still excludes reasoning — pre-existing, out of scope, candidate follow-up.
  • countAllMessageTokens fallback (token-utils.ts) unchanged — first-turn only, no reasoning present at that point.

Fixes #371

ework-agent added 2 commits September 9, 2026 00:42
estimateContextComposition (nudge breakdown) and collectVisibleMessages
(acp_status overview) both skipped reasoning parts, so displayed
context-usage percentages systematically undercounted real usage
(token-utils.ts usage formula includes reasoning).

- ContextComposition gains reasoningTokens; total includes it
- nudge breakdown + acp_status CONTEXT BREAKDOWN gain a reasoning category
- per-message drilldown totals/sort/lines include reasoning footprint
- system prompt breakdown example + category list updated
- +8 tests (1085/1085 passing)

Fixes #371
- add nudge breakdown line test asserting rendered reasoning category
- fix 2 pre-existing vacuous acp_status tests (partial mocks dropped by
  filterMessages → passed with zero visible messages)
- tighten protected-reasoning assertion to exact value
- system prompt breakdown example percentages now sum to 100%

1086/1086 tests passing
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

📦 Built Plugin Artifact

Branch: 2026-09-08_reasoning-in-context-estimate (425a5d6)

Option A — Install from npm PR tag (recommended)

opencode plugin opencode-acp@pr-374 --global

Each push to this PR publishes a new version under the pr-374 npm tag.

Option B — Install from GitHub

opencode plugin "github:ranxianglei/opencode-acp#2026-09-08_reasoning-in-context-estimate" --global

Option C — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf opencode-acp-pr374.tgz
cp -r package/dist ~/.cache/opencode/packages/opencode-acp@latest/node_modules/opencode-acp/dist
  1. Restart opencode to pick up changes.

This comment is automatically updated on each push.

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.

Display/acp_status context-usage estimator excludes reasoning tokens (undercounts real usage)

1 participant