Skip to content

feat: align context usage metrics - #411

Merged
Astro-Han merged 5 commits into
devfrom
codex/i403-context-usage
May 4, 2026
Merged

feat: align context usage metrics#411
Astro-Han merged 5 commits into
devfrom
codex/i403-context-usage

Conversation

@Astro-Han

@Astro-Han Astro-Han commented May 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add a shared @opencode-ai/util/context-usage helper for context usage, compact threshold, and used-token math.
  • Update runtime overflow and app context metrics to use the same helper and reserve source.
  • Update the context usage indicator, tooltip, Context tab labels, and ring warning/danger tones.

Why

Issue #403 needs the UI to show real usable input context instead of the theoretical context window, while keeping runtime compaction and UI display on the same calculation.

Related Issue

Closes #403

Human Review Status

Pending. A human should make the final merge decision after reviewing the final diff and verification evidence.

Review Focus

  • Shared helper API in @opencode-ai/util/context-usage.
  • Parity between packages/opencode/src/session/overflow.ts and app context metrics.
  • Token accounting around tokens.total, cache tokens, reasoning tokens, unknown limits, and custom compaction.reserved.
  • UI copy and 70% / 90% ring tone thresholds.

Risk Notes

  • Behavior risk: runtime overflow now routes through the shared helper, so compact threshold behavior is intentionally tied to the same math the UI displays. The default reserve source is the model output limit, not the request-level ProviderTransform.maxOutputTokens cap; this keeps the displayed threshold stable across runtime output-token cap experiments.
  • UI risk: visible context usage copy and ring color changed, but no new visual threshold marker was added.
  • Migration risk: no Effect Service was introduced; the helper is pure and can be wrapped by future Effect Schema / Effect Service migration work.

How To Verify

util context usage tests: 11 pass, 0 fail
util typecheck: tsc --noEmit passed
opencode compaction tests: 44 pass, 0 fail
opencode typecheck: tsgo --noEmit passed
app focused tests: 11 pass, 0 fail
app typecheck: tsgo -b passed
app production build: vite build passed, with existing chunk-size/dynamic-import warnings only
root typecheck: bun turbo typecheck --force passed
diff check: no whitespace errors
reviewer pass: addressed P2 reserve-source mismatch before opening PR

Screenshots or Recordings

Not included. I attempted a local render check at 127.0.0.1:54544; the page returned 200, but the backend at localhost:4096 was not running, so the screenshot only showed the empty app shell and was not useful evidence for the context indicator.

Checklist

  • Human review status is stated above as pending, approved, or not required
  • I linked the related issue, or stated why there is no issue
  • This PR has type, scope, and priority labels, or I requested maintainer labeling
  • I described the review focus and any meaningful risks
  • I listed the relevant verification steps and the key result for each
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for desktop, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
  • I reviewed the final diff for unrelated changes and suspicious dependency changes
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

Summary by CodeRabbit

  • New Features

    • Context-usage ring now maps usage into tones (normal/warning/danger), clamps percent display, and shows a localized "used tokens" tooltip with optional effective input limit and compacting status.
  • Improvements

    • Metrics UI now displays context window, effective input limit, compact threshold, and context used; usage, thresholds and overflow detection are derived consistently from model/provider data.
  • Tests

    • Added extensive tests for usage derivation, clamping, thresholds, and overflow paths.
  • Internationalization

    • Updated English and Chinese labels for context usage and statistics.

@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR derives effective input limits, compaction thresholds, and usage from model tokens/config, exposes helpers for tone and clamped ring percent, integrates those into session metrics, UI, overflow detection, tests, and i18n. (≤50 words)

Changes

Context usage derivation & UI/overflow integration

Layer / File(s) Summary
Data Shape / Types
packages/util/src/context-usage.ts
Adds types for model/tokens/compaction input and derived ContextUsage fields (effectiveInputLimit, compactThreshold, autoCompactEnabled, usedTokens, usagePercent).
Derivation Logic
packages/util/src/context-usage.ts
Implements contextUsageUsedTokens, contextUsageModelOutputLimit, and deriveContextUsage computing usedTokens, reserved, effectiveInputLimit, compactThreshold, and usagePercent (handles unknown/zero limits).
Derivation Tests
packages/util/test/context-usage.test.ts
Adds tests validating token-total precedence, limit selection, reserve/clamping, auto-compact flag, and edge cases (zero/unknown limits).
Session Metrics (core)
packages/app/src/components/session/session-context-metrics.ts, ...session-context-metrics.test.ts
build/getSessionContextMetrics now accept config, call deriveContextUsage, use contextUsageUsedTokens, and expose new context fields (effectiveInputLimit, contextWindow, compactThreshold, autoCompactEnabled, usedTokens, usagePercent, usage); tests updated/added.
UI: Usage helpers & tests
packages/app/src/components/session-context-usage-state.ts, ...usage.test.ts
Adds ContextUsageTone type, contextUsageTone(usage) mapping (normal/warning/danger), and contextUsageRingPercent(usage) that maps null→0 and clamps to 0–100; tests validate thresholds and clamping.
UI: Component & tooltip wiring
packages/app/src/components/session-context-usage.tsx
Uses getSessionContextMetrics(..., config), derives toneringColor, drives ProgressCircle via --progress-circle-progress, uses contextUsageRingPercent(context()?.usagePercent), and updates tooltip to show used tokens, optional effective input limit, and compacting status.
UI: Session Tab & i18n
packages/app/src/components/session/session-context-tab.tsx, packages/app/src/i18n/en.ts, packages/app/src/i18n/zh.ts
Metrics now include config; stats grid shows contextWindow, inputLimit (effectiveInputLimit), compactThreshold, and contextUsed; i18n keys replaced/added for new labels and unknown/auto-compact variants.
Overflow logic & tests
packages/opencode/src/session/overflow.ts, packages/opencode/test/session/compaction.test.ts
Refactors usable() and isOverflow() to use deriveContextUsage (with emptyTokens for usable) and contextUsageModelOutputLimit; tests added for cache.write inclusion and provider tokens.total usage.
Styling
packages/ui/src/components/progress-circle.css
Progress stroke now resolves from --progress-circle-progress with fallback to --border-active.
Tooling config
turbo.json
typecheck task now depends on ^typecheck.

Sequence Diagram

sequenceDiagram
    participant UI as SessionContextUsage (UI)
    participant Metrics as SessionContextMetrics
    participant Derive as deriveContextUsage
    participant Overflow as Overflow Logic
    participant Render as ProgressCircle/Tooltip

    UI->>Metrics: getSessionContextMetrics(messages, providers, config)
    Metrics->>Derive: deriveContextUsage({ model, tokens, compaction, defaultReserveTokens })
    Derive->>Derive: compute usedTokens, effectiveInputLimit, reserved, compactThreshold, usagePercent
    Derive-->>Metrics: context usage metrics
    Metrics-->>UI: context metrics
    UI->>Derive: contextUsageTone(usagePercent) & contextUsageRingPercent(usagePercent)
    Derive-->>UI: tone, percent
    UI->>Render: set --progress-circle-progress (ringColor), percent
    UI->>Overflow: isOverflow(...) uses deriveContextUsage
    Overflow-->>UI: overflow boolean
    Render-->>UI: rendered ring + tooltip
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

enhancement, P2, app, ui

Poem

🐰 I counted tokens by moonlit chart,
Trimmed the limits, made the thresholds smart.
Input caps now lead the show,
Warnings glow when numbers grow.
Hop, report — the ring turns bright, compacting comes in sight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: align context usage metrics' is concise and clearly summarizes the main change: aligning context usage calculations across the codebase and UI.
Linked Issues check ✅ Passed The PR fully addresses issue #403: implements effectiveInputLimit calculation [#403], exposes auto-compact threshold in UI [#403], updates context metrics and UI copy [#403], preserves fallback for models without limit.input [#403], and does not alter core compaction algorithm [#403].
Out of Scope Changes check ✅ Passed All changes are scoped to implementing issue #403 requirements: new shared context-usage helper, alignment of overflow and app metrics, UI updates for context display, and related test coverage. No unrelated refactors or unexpected dependencies detected.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering all required template sections including summary, why, related issue, human review status, review focus, risk notes, verification steps, and checklist completion.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/i403-context-usage

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request centralizes context usage and compaction logic into a shared utility package, ensuring consistent calculations across the UI and core session logic. It enhances the user interface to display more granular metrics, including context windows, input limits, and auto-compaction thresholds. A high-severity issue was identified in the new utility where reasoning tokens were omitted from the total token summation, which would lead to inaccurate usage reporting and overflow detection for models that report reasoning tokens separately.

Comment thread packages/util/src/context-usage.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/app/src/components/session/session-context-metrics.test.ts`:
- Around line 74-94: The test's message object in the "uses input limit and
custom compaction reserve for usage metrics" case creates a total token count
(238_000) while also setting non-zero component fields
(input/output/reasoning/read/write), which can cause a mismatch if
getSessionContextMetrics treats total as the sum of components; fix the test by
making the message components consistent with total—either set all component
fields to 0 so total is the sole source of usedTokens, or adjust total to equal
the sum of the component fields—so that getSessionContextMetrics returns
usedTokens matching the expected 238_000.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 041948e0-8ac0-4de5-8b9c-93330a01c392

📥 Commits

Reviewing files that changed from the base of the PR and between cd09536 and 37a3a3d.

📒 Files selected for processing (13)
  • packages/app/src/components/session-context-usage-state.ts
  • packages/app/src/components/session-context-usage.test.ts
  • packages/app/src/components/session-context-usage.tsx
  • packages/app/src/components/session/session-context-metrics.test.ts
  • packages/app/src/components/session/session-context-metrics.ts
  • packages/app/src/components/session/session-context-tab.tsx
  • packages/app/src/i18n/en.ts
  • packages/app/src/i18n/zh.ts
  • packages/opencode/src/session/overflow.ts
  • packages/opencode/test/session/compaction.test.ts
  • packages/ui/src/components/progress-circle.css
  • packages/util/src/context-usage.ts
  • packages/util/test/context-usage.test.ts

Comment thread packages/app/src/components/session/session-context-metrics.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/app/src/components/session/session-context-metrics.ts (1)

93-95: ⚡ Quick win

Drop the ambiguous limit alias.

limit now carries effectiveInputLimit, while contextWindow is also present beside it. That makes the API easy to misuse and reintroduces the exact “which limit is this?” ambiguity this PR is trying to remove.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app/src/components/session/session-context-metrics.ts` around lines
93 - 95, The object currently exposes a confusing alias `limit` that duplicates
`effectiveInputLimit`; remove the `limit` property so the object only exposes
`effectiveInputLimit` (from usage.effectiveInputLimit) and `contextWindow` (from
model?.limit.context), and update any consumers to reference
`effectiveInputLimit` directly instead of `limit`; ensure the symbols
`effectiveInputLimit`, `contextWindow`, and `usage.effectiveInputLimit` are
used/returned consistently in the `session-context-metrics` code paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/app/src/components/session/session-context-metrics.ts`:
- Around line 93-95: The object currently exposes a confusing alias `limit` that
duplicates `effectiveInputLimit`; remove the `limit` property so the object only
exposes `effectiveInputLimit` (from usage.effectiveInputLimit) and
`contextWindow` (from model?.limit.context), and update any consumers to
reference `effectiveInputLimit` directly instead of `limit`; ensure the symbols
`effectiveInputLimit`, `contextWindow`, and `usage.effectiveInputLimit` are
used/returned consistently in the `session-context-metrics` code paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ff27bd42-cd1e-49e6-b21d-5a6f99907e16

📥 Commits

Reviewing files that changed from the base of the PR and between 37a3a3d and 0bd323e.

📒 Files selected for processing (8)
  • packages/app/src/components/session-context-usage.tsx
  • packages/app/src/components/session/session-context-metrics.test.ts
  • packages/app/src/components/session/session-context-metrics.ts
  • packages/app/src/components/session/session-context-tab.tsx
  • packages/app/src/i18n/en.ts
  • packages/app/src/i18n/zh.ts
  • packages/util/src/context-usage.ts
  • packages/util/test/context-usage.test.ts
✅ Files skipped from review due to trivial changes (3)
  • packages/app/src/i18n/en.ts
  • packages/util/test/context-usage.test.ts
  • packages/app/src/i18n/zh.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/util/src/context-usage.ts
  • packages/app/src/components/session-context-usage.tsx
  • packages/app/src/components/session/session-context-metrics.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/util/src/context-usage.ts`:
- Around line 70-73: The code reads input.compaction?.reserved directly into
reserved and uses it to compute compactThreshold, which can produce NaN or
values > effectiveInputLimit if reserved is negative or non-finite;
clamp/normalize the value first by replacing input.compaction?.reserved with a
sanitizedReserved (e.g., Number.isFinite(...) ? Math.max(0, value) : 0) before
computing compactThreshold and usagePercent, ensuring reserved is a non-negative
finite number; update references to use sanitizedReserved in the Math.min(...)
and Math.max(...) expressions in this module (where reserved, compactThreshold,
usagePercent, and effectiveInputLimit are computed).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a0aeb12-fd22-465a-abca-f42121821e99

📥 Commits

Reviewing files that changed from the base of the PR and between 0bd323e and 99b0d93.

📒 Files selected for processing (6)
  • packages/app/src/components/session-context-usage.tsx
  • packages/app/src/components/session/session-context-metrics.test.ts
  • packages/app/src/components/session/session-context-metrics.ts
  • packages/opencode/src/session/overflow.ts
  • packages/util/src/context-usage.ts
  • packages/util/test/context-usage.test.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/app/src/components/session-context-usage.tsx
  • packages/util/test/context-usage.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/opencode/src/session/overflow.ts
  • packages/app/src/components/session/session-context-metrics.test.ts

Comment thread packages/util/src/context-usage.ts Outdated
@Astro-Han Astro-Han added enhancement New feature or request ui Design system and user interface harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority labels May 4, 2026
@Astro-Han
Astro-Han merged commit 00ea36a into dev May 4, 2026
23 checks passed
@Astro-Han

Copy link
Copy Markdown
Owner Author

Post-merge trace note for #411 / #403.

What merged

  • Shared @opencode-ai/util/context-usage now owns used-token, effective input limit, compact threshold, and usage percent math.
  • Runtime overflow and app context metrics now use the same helper, so UI and runtime calculate context usage the same way.
  • Context usage UI now shows real usable input context, with warning at 70% and danger at 90%.
  • turbo typecheck ordering now waits for dependency package typechecks, avoiding the clean-CI app declaration race seen in desktop-electron.

Key decisions

  • Cache read/write tokens count toward context usage.
  • Non-zero provider tokens.total wins; fallback excludes reasoning to avoid double counting providers that include reasoning inside output.
  • Default reserve source is the model output limit, not request-level ProviderTransform.maxOutputTokens, so displayed thresholds stay stable across output-token cap experiments.
  • Invalid compaction.reserved values are normalized before threshold math.
  • The shared helper stays pure and Effect Service-free, leaving room for later Effect Schema / Effect Service migration.

Verification before merge

  • bun test test/context-usage.test.ts: 11 pass.
  • opencode compaction tests: 44 pass.
  • app focused context tests: 11 pass.
  • package typechecks and bun turbo typecheck --force: pass.
  • app production build: pass, with existing warnings only.
  • GitHub checks: all pass, including typecheck, unit-app, unit-desktop, unit-opencode, CodeQL, CodeRabbit, smoke-macos-arm64, e2e-artifacts, lint, and analysis checks.

@Astro-Han
Astro-Han deleted the codex/i403-context-usage branch May 4, 2026 00:55
@Astro-Han Astro-Han added app Application behavior and product flows and removed app Application behavior and product flows labels May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Show effective input context and auto-compact threshold

1 participant