Skip to content

feat(tui): add /context command with a categorized context-window breakdown#3458

Merged
Sayt-0 merged 1 commit into
mainfrom
context-window-breakdown
Jul 3, 2026
Merged

feat(tui): add /context command with a categorized context-window breakdown#3458
Sayt-0 merged 1 commit into
mainfrom
context-window-breakdown

Conversation

@Sayt-0

@Sayt-0 Sayt-0 commented Jul 3, 2026

Copy link
Copy Markdown
Member

Closes #3432

Summary

Adds a /context slash command that opens a dialog (consistent with the existing /cost dialog) showing the estimated context-window composition, broken down by category, with a stacked usage bar, per-category rows, free space, and a copy-to-clipboard action.

╭─────────────────────────────────────────────────────────────╮
│                      Context Window                         │
│          openai/gpt-4o  •  limit: 128.0K tokens             │
│  ───────────────────────────────────────────────────────    │
│                                                             │
│  ███████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░    │
│  ~45.4K of 128.0K tokens (35%)                              │
│                                                             │
│  ■ System prompt       1.2K       <1%  (3 messages)         │
│  ■ Tool definitions    8.4K        7%  (23 tools)           │
│  ■ Prompt files        600        <1%  (1 file)             │
│  ■ Messages            6.1K        5%  (12 messages)        │
│  ■ Tool results        28.2K      22%  (18 results)         │
│  ■ Compaction summary  900        <1%  (1 summary)          │
│  ■ Free space          82.6K      65%                       │
│                                                             │
│  Token counts are estimates; the provider's tokenizer       │
│  may count differently.                                     │
│                                                             │
│                ↑↓ scroll  c copy  Esc close                 │
╰─────────────────────────────────────────────────────────────╯

Bar segments and row markers use per-category theme colors; the free space remainder is muted.

Issue expectations

Expectation Implementation
/context command pkg/tui/commands/commands.go (session.context): palette, slash parser, completion; compatible with --disable-commands
New message type messages.ShowContextDialogMsg in pkg/tui/messages/toggle.go, next to the sibling Show*DialogMsg types (the issue sketched session.go; toggle.go is where the existing dialog messages live)
New dialog pkg/tui/dialog/context.go, modeled on cost.go: scrollview, c copies a plain-text version, Esc/Enter/q closes
Breakdown computed in pkg/runtime from Session.GetMessages pkg/runtime/context_breakdown.go: ContextBreakdown/ContextCategory types, (*LocalRuntime).ContextBreakdown(ctx, sess)
Categories system prompt, tool definitions, prompt files, conversation messages, tool results, compaction summary
Estimates via compaction.EstimateMessageTokens, labeled as such usage-calibrated compaction.NewSliceEstimator (same estimator the proactive compaction trigger uses); explicit disclaimer line in the dialog
% of the resolved context limit resolved via contextLimitForAgentModel (same source as the sidebar gauge, including compaction-model capping); "context limit unknown" fallback for harness agents and uncatalogued models
Bar/grid rendering stacked color bar (cumulative rounding keeps it exactly content-width) plus aligned per-category rows with tokens, percent, and item counts
Reuse toolcommon/tokencount.go via the shared FormatTokenCount helper

Flow

/context → ShowContextDialogMsg → handleShowContextDialog (tea.Cmd goroutine)
  → App.ContextBreakdown → LocalRuntime.ContextBreakdown
      ├─ sess.GetMessages(agent) → categorize by role / exact summary match
      ├─ agent.Tools(ctx)        → tool schema (name+description+parameters) estimates
      └─ promptfiles lookup      → add_prompt_files content estimate
  → OpenDialogMsg{NewContextDialog(breakdown)}

Design decisions

  • Pull, not push: the issue said to "consider a ContextBreakdownEvent". An on-demand method was implemented instead: the data is fresh at dialog-open time and there is a single consumer today. feat(tui): per-sub-agent context accounting in the TUI #3438 can call LocalRuntime.ContextBreakdown directly; an event can be layered on later if feat(runtime): cross-agent compaction orchestration (explicit, user-triggered) #3439 needs one.
  • Optional capability interface in pkg/app (same pattern as agentConfigProvider): remote runtimes show an info toast ("Context breakdown is not supported with remote runtimes").
  • Async computation in a tea.Cmd goroutine (unlike /tools, which blocks the Update loop) because tool listing may lazily start MCP toolsets.
  • Exact summary matching: new session.SummaryMessageContent() and Session.LastSummary() helpers classify the summary message by exact content, so a user message that merely starts with "Session Summary: " stays in the conversation bucket (pinned by a test). The two former string literals in session.go now share the same helper.
  • Degraded modes: tool-listing failures and unreadable prompt files are logged and skipped instead of failing the dialog; a nil breakdown is guarded in the dialog constructor.

Testing

Area Coverage
pkg/runtime (8 tests) categorization and item counts, compaction summary bucket, summary look-alike guard, reported-usage precedence, unknown context limit, nil session, no prompt files, tool definition estimator
pkg/tui/dialog (9 tests) view rendering, unknown limit, empty breakdown, free-space clamping (never negative), percent labels, scale selection, bar width invariants across widths, ANSI-free plain-text copy
pkg/session LastSummary, SummaryMessageContent/GetMessages exact-content contract
pkg/tui/commands /context parse test

go build ./..., golangci-lint run ./... (0 issues), go run ./lint . (no offenses), full test suite green except pre-existing environment-dependent SSRF/network tests that also fail on a clean checkout of main.

…akdown

Add a /context slash command that opens a dialog (consistent with the
/cost dialog) showing the estimated composition of the context window,
broken down by category: system prompt, tool definitions, prompt files,
conversation messages, tool results, and compaction summary.

The breakdown is computed in pkg/runtime from Session.GetMessages output
using the usage-calibrated compaction estimator, plus tool schema and
add_prompt_files estimates. Percentages are relative to the resolved
context limit (same source as the sidebar gauge); the dialog renders a
stacked usage bar, per-category rows with item counts, free space, and
an explicit estimates disclaimer. Numbers can be copied as plain text.

The computation runs in a tea.Cmd goroutine so lazily-started toolsets
never block the UI, and remote runtimes report the feature as
unavailable via an optional capability interface.

Closes #3432
@Sayt-0
Sayt-0 requested a review from a team as a code owner July 3, 2026 20:20
@Sayt-0 Sayt-0 added area/tui For features/issues/fixes related to the TUI kind/feat PR adds a new feature (maps to feat:). Use on PRs only. area/runtime Runtime engine, agent loop execution, tool dispatch, loop detection labels Jul 3, 2026
@Sayt-0
Sayt-0 merged commit 6cad761 into main Jul 3, 2026
18 checks passed
@Sayt-0
Sayt-0 deleted the context-window-breakdown branch July 3, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/runtime Runtime engine, agent loop execution, tool dispatch, loop detection area/tui For features/issues/fixes related to the TUI kind/feat PR adds a new feature (maps to feat:). Use on PRs only.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(tui): add /context command with a categorized context-window breakdown

2 participants