Skip to content

feat: /cost per-turn breakdown dashboard#13

Merged
kienbui1995 merged 1 commit intomainfrom
feat/cost-dashboard
Apr 11, 2026
Merged

feat: /cost per-turn breakdown dashboard#13
kienbui1995 merged 1 commit intomainfrom
feat/cost-dashboard

Conversation

@kienbui1995
Copy link
Copy Markdown
Owner

@kienbui1995 kienbui1995 commented Apr 11, 2026

What

Enhanced /cost command with per-turn breakdown showing input/output tokens, cost, and model for each turn.

Example output

💰 Session cost: $0.0142 (3200 input + 450 output tokens)
─── Per-turn breakdown ───
  Turn 1: $0.0089  (2100↓ 280↑)  claude-sonnet-4-5
  Turn 2: $0.0053  (1100↓ 170↑)  claude-sonnet-4-5
──────────────────────────

Changes

  • mc-tui/src/app.rs: Add turn_costs field to App
  • mc-tui/src/commands.rs: Enhanced cmd_cost with per-turn breakdown
  • mc-cli/src/main.rs: Record per-turn cost on each Usage event

152 tests pass.

Summary by CodeRabbit

  • New Features
    • Enhanced /cost command now displays detailed per-turn cost breakdowns, including input/output token counts and model information for each conversation turn, alongside session totals.

Show per-turn token usage, cost, and model in /cost command.
Tracks each turn's input/output tokens and estimated cost.
/cost --total still shows all-time cumulative cost.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 11, 2026

📝 Walkthrough

Walkthrough

The changes add per-turn cost tracking to the CLI/TUI application. The App struct now maintains a turn_costs vector recording each turn's input tokens, output tokens, estimated cost, and model. The main CLI handler computes and stores per-turn costs, while the /cost command displays both session totals and per-turn breakdowns with enhanced formatting.

Changes

Cohort / File(s) Summary
Per-Turn Cost Data Structure
mc/crates/mc-tui/src/app.rs
Added public turn_costs: Vec<(u32, u32, u32, f64, String)> field to track per-turn metrics (turn number, input tokens, output tokens, cost, model); initialized as empty vector in App::new.
Per-Turn Cost Recording
mc/crates/mc-cli/src/main.rs
Implemented cost computation and recording logic when handling UiMessage::Usage; calculates per-turn cost, assigns turn number, and appends tuple to app.turn_costs while maintaining cumulative token aggregates.
Cost Display Enhancement
mc/crates/mc-tui/src/commands.rs
Updated /cost command output with 💰 emoji prefix on session total; added per-turn cost breakdown display with separator lines, turn index, formatted cost, token counts, and model name.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI Handler
    participant App as App State
    participant Cmd as Cost Command
    
    CLI->>CLI: Receive UiMessage::Usage
    CLI->>CLI: Compute per-turn cost
    CLI->>App: Push (turn_num, input, output, cost, model)
    CLI->>App: Update cumulative totals
    
    Cmd->>App: Request turn_costs vector
    App-->>Cmd: Return per-turn records
    Cmd->>Cmd: Format and display breakdown
    Cmd-->>Cmd: Show session total + per-turn details
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 Each turn now tracked with costs so clear,
Input, output, totals appear—
Per-turn breakdowns in a row,
The CLI hops with info flow! 💰

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a per-turn cost breakdown dashboard to the /cost command, which is the primary objective across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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 feat/cost-dashboard

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

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@mc/crates/mc-cli/src/main.rs`:
- Around line 349-351: Run rustfmt on the repository and commit the changes so
the file compiles under `cargo fmt --check`; specifically reformat the block
around the code that computes `turn_cost` and `turn_num` and the
`app.turn_costs.push(...)` call in `main.rs` (look for the `turn_cost`,
`turn_num`, and `app.turn_costs.push` symbols) by running `cargo fmt` locally
and committing the resulting formatting changes.
- Around line 349-351: The per-turn cost is recorded with the model used for
that turn (turn_cost and app.turn_costs push), but the session total is being
re-priced using the current model later, causing drift after /model switches;
fix by ensuring you persist the computed turn_cost (as already done when pushing
(turn_num, input, output, turn_cost, app.model.clone())) and change the session
total calculation to sum the stored per-turn cost values instead of re-calling
registry.estimate_cost with the current model — locate places that compute the
session total and replace re-estimation logic with summing the 4th tuple element
from app.turn_costs so totals remain consistent with the model used per turn.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: bf8ffce5-cf88-4ef1-bab8-5c3f1c243f27

📥 Commits

Reviewing files that changed from the base of the PR and between 64a0298 and 8e389c0.

📒 Files selected for processing (3)
  • mc/crates/mc-cli/src/main.rs
  • mc/crates/mc-tui/src/app.rs
  • mc/crates/mc-tui/src/commands.rs

Comment on lines +349 to +351
let turn_cost = registry.estimate_cost(&app.model, input, output);
let turn_num = app.turn_costs.len() as u32 + 1;
app.turn_costs.push((turn_num, input, output, turn_cost, app.model.clone()));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Rustfmt mismatch is currently failing CI.

The pipeline reports cargo fmt --check failure around this hunk (Line 348-350). Please run cargo fmt and commit the formatted output.

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

In `@mc/crates/mc-cli/src/main.rs` around lines 349 - 351, Run rustfmt on the
repository and commit the changes so the file compiles under `cargo fmt
--check`; specifically reformat the block around the code that computes
`turn_cost` and `turn_num` and the `app.turn_costs.push(...)` call in `main.rs`
(look for the `turn_cost`, `turn_num`, and `app.turn_costs.push` symbols) by
running `cargo fmt` locally and committing the resulting formatting changes.

⚠️ Potential issue | 🟠 Major

Fix session total cost drift after model switches.

Line 349+ stores per-turn cost with that turn’s model, but session total is still derived from cumulative tokens priced with the current model. After /model changes, /cost total can be wrong and inconsistent with the per-turn breakdown.

Proposed fix
-                    app.session_cost = registry.estimate_cost(
-                        &app.model,
-                        app.total_input_tokens,
-                        app.total_output_tokens,
-                    );
-                    let turn_cost = registry.estimate_cost(&app.model, input, output);
+                    let turn_cost = registry.estimate_cost(&app.model, input, output);
                     let turn_num = app.turn_costs.len() as u32 + 1;
-                    app.turn_costs.push((turn_num, input, output, turn_cost, app.model.clone()));
+                    app.turn_costs
+                        .push((turn_num, input, output, turn_cost, app.model.clone()));
+                    app.session_cost = app.turn_costs.iter().map(|(_, _, _, c, _)| c).sum();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mc/crates/mc-cli/src/main.rs` around lines 349 - 351, The per-turn cost is
recorded with the model used for that turn (turn_cost and app.turn_costs push),
but the session total is being re-priced using the current model later, causing
drift after /model switches; fix by ensuring you persist the computed turn_cost
(as already done when pushing (turn_num, input, output, turn_cost,
app.model.clone())) and change the session total calculation to sum the stored
per-turn cost values instead of re-calling registry.estimate_cost with the
current model — locate places that compute the session total and replace
re-estimation logic with summing the 4th tuple element from app.turn_costs so
totals remain consistent with the model used per turn.

@kienbui1995 kienbui1995 merged commit 7a31b57 into main Apr 11, 2026
6 of 7 checks passed
@kienbui1995 kienbui1995 deleted the feat/cost-dashboard branch April 11, 2026 09:25
@kienbui1995 kienbui1995 mentioned this pull request Apr 11, 2026
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