Skip to content

fix(claude-code): correct token counts, add per-call cost, and show inline activity#1015

Merged
zbigniewsobiecki merged 1 commit intodevfrom
fix/claude-code-token-counts-and-inline-activity
Mar 23, 2026
Merged

fix(claude-code): correct token counts, add per-call cost, and show inline activity#1015
zbigniewsobiecki merged 1 commit intodevfrom
fix/claude-code-token-counts-and-inline-activity

Conversation

@zbigniewsobiecki
Copy link
Copy Markdown
Member

Summary

  • Fix wrong token counts: logClaudeCodeLlmCall was recording only usage.input_tokens, which with Anthropic prompt caching is the uncached portion (typically 0–8 tokens). Now sums all three usage fields: input_tokens + cache_read_input_tokens + cache_creation_input_tokens
  • Fix missing cachedTokens: now set to cache_read_input_tokens so the Cached stat card in the LLM Calls tab reflects reality
  • Add per-call cost: new toPricingKey() helper converts raw Anthropic model IDs (claude-sonnet-4-5-20250929) to the anthropic:claude-sonnet-4-5 format expected by calculateCost()
  • Inline activity in list rows: the listLlmCalls API now returns toolCalls [{name, inputSummary}] instead of a flat toolNames [], so each row shows [Read] /path/to/file.ts or [Bash] git commit -m "..." without requiring expansion; thinking turns show thinking (N chars) in muted italic
  • Refactor processAssistantMessage: extracted processContentBlock helper to bring Biome cognitive complexity from 17 → under 15

Test plan

  • npm run typecheck — clean
  • cd web && npx tsc --noEmit — clean
  • npm run lint — no errors
  • npm test — 6625 tests pass including new claude-code-messageProcessing.test.ts
  • In dashboard: open a Claude Code run → token counts show realistic thousands, not single digits
  • In dashboard: cost column populated for Sonnet/Opus/Haiku runs
  • In dashboard: Activity column shows [Tool] param inline per row; thinking turns show thinking (N chars)

🤖 Generated with Claude Code

…ivity

Token counts in the LLM Calls tab were near-zero for Claude Code runs because
only usage.input_tokens (the uncached portion) was recorded. With Anthropic
prompt caching, the vast majority of tokens land in cache_read_input_tokens and
cache_creation_input_tokens instead.

Fix logClaudeCodeLlmCall:
- inputTokens = input_tokens + cache_read_input_tokens + cache_creation_input_tokens
- cachedTokens = cache_read_input_tokens (tokens served from cache)
- costUsd computed via calculateCost() using toPricingKey() which converts
  'claude-sonnet-4-5-20250929' → 'anthropic:claude-sonnet-4-5' for pricing lookup

Also refactor processAssistantMessage to extract processContentBlock helper,
reducing Biome cognitive complexity from 17 to under 15.

LLM Calls tab activity column improvements:
- listLlmCalls API now returns toolCalls [{name, inputSummary}] instead of flat
  toolNames [], surfacing the parsed input summary (file path, command, etc.) for
  each tool call without requiring row expansion
- thinkingChars added: total chars across all thinking blocks shown inline as
  "thinking (N chars)" in muted italic
- Each tool call rendered as [Badge] monospace-param inline in the list row

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@zbigniewsobiecki zbigniewsobiecki merged commit 27dfbf7 into dev Mar 23, 2026
8 checks passed
@zbigniewsobiecki zbigniewsobiecki deleted the fix/claude-code-token-counts-and-inline-activity branch March 23, 2026 20:53
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 95.55556% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/api/routers/runs.ts 91.66% 1 Missing ⚠️
src/backends/claude-code/messageProcessing.ts 96.96% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

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