Skip to content

cost dialog: enrich with session stats, per-model percentages, and formatting fixes#2046

Open
dgageot wants to merge 1 commit intodocker:mainfrom
dgageot:board/what-could-we-improve-in-the-cost-dialog-a6143df6
Open

cost dialog: enrich with session stats, per-model percentages, and formatting fixes#2046
dgageot wants to merge 1 commit intodocker:mainfrom
dgageot:board/what-could-we-improve-in-the-cost-dialog-a6143df6

Conversation

@dgageot
Copy link
Member

@dgageot dgageot commented Mar 10, 2026

Summary

Enhance the /cost dialog with richer session insights and fix several edge-case bugs.

New features

  • Total token count (input + output combined) in the Total section
  • Session duration and message count in the header
  • Reasoning tokens displayed when the model reports them (e.g. o1)
  • Average cost per 1K tokens and average cost per message metrics
  • Cost percentage breakdown per model and per message
  • Cache hit rate and per-entry cached token counts
  • Model name included in plain-text clipboard copy output

Code quality improvements

  • Extract shared stat computation (totalStats, actualMessageCount, plainTextLine) to eliminate duplication between styled and plain-text renderers
  • Fix slice aliasing bug in applyScrolling (use slices.Clone)
  • Fix formatCost/formatCostPadded silently swallowing negative values
  • Fix formatDuration producing garbled output for negative durations

…rmatting fixes

Enhance the /cost dialog with richer session insights:

- Show total token count (input + output combined) in the Total section
- Display session duration and message count in the header
- Show reasoning tokens when the model reports them (e.g. o1)
- Add average cost per 1K tokens and average cost per message metrics
- Show cost percentage breakdown per model and per message
- Display cache hit rate and per-entry cached token counts
- Include model name in the plain-text clipboard copy output

Code quality improvements:

- Extract shared stat computation (totalStats, actualMessageCount,
  plainTextLine) to eliminate duplication between styled and plain-text
  renderers
- Fix slice aliasing bug in applyScrolling (use slices.Clone)
- Fix formatCost/formatCostPadded silently swallowing negative values
- Fix formatDuration producing garbled output for negative durations

Assisted-By: docker-agent
@dgageot dgageot requested a review from a team as a code owner March 10, 2026 17:45
Copy link

@docker-agent docker-agent bot left a comment

Choose a reason for hiding this comment

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

Review Summary

Assessment: 🟡 NEEDS ATTENTION

The PR successfully adds valuable session insights and formatting improvements to the cost dialog. However, 1 confirmed bug was found in the newly added cache hit rate calculation that will produce incorrect percentages when cache writes are present.

Findings

  • 1 MEDIUM severity issue requiring attention
  • 0 CRITICAL issues

Cache Hit Rate Formula

The cache hit rate calculation should exclude CacheWriteTokens from the denominator. Cache write tokens represent tokens written to cache for future use, not tokens that were candidates for cache hits. Including them artificially deflates the hit rate percentage.

For example:

  • With CachedInputTokens=700, InputTokens=300, CacheWriteTokens=200
  • Current formula: 700/(700+300+200) = 58.3%
  • Correct formula: 700/(700+300) = 70%

Consider changing line 185 from:

float64(d.total.CachedInputTokens)/float64(totalIn)*100

to:

float64(d.total.CachedInputTokens)/float64(d.total.CachedInputTokens + d.total.InputTokens)*100

stats = append(stats, stat{"avg cost/1K tokens:", formatCost(d.total.cost / float64(tok) * 1000)})
}
if totalIn := d.total.totalInput(); totalIn > 0 && d.total.CachedInputTokens > 0 {
stats = append(stats, stat{"cache hit rate:", fmt.Sprintf("%.0f%%", float64(d.total.CachedInputTokens)/float64(totalIn)*100)})
Copy link

Choose a reason for hiding this comment

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

MEDIUM: Cache hit rate calculation includes CacheWriteTokens in denominator

The denominator totalIn includes CacheWriteTokens, which artificially inflates the base and produces an incorrect (lower) percentage.

The semantically correct cache hit rate should be:

float64(d.total.CachedInputTokens) / float64(d.total.CachedInputTokens + d.total.InputTokens) * 100

CacheWriteTokens represent tokens written to the cache for future use, not tokens that were candidates for cache hits, so they shouldn't be included in the denominator.

Example:

  • CachedInputTokens=700, InputTokens=300, CacheWriteTokens=200
  • Current: 700/1200 = 58.3% ❌
  • Correct: 700/1000 = 70% ✅

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