Skip to content

Add token usage tracking and punch stats command (Phase 4a)#21

Merged
humancto merged 1 commit into
mainfrom
feat/token-usage-tracking
Mar 26, 2026
Merged

Add token usage tracking and punch stats command (Phase 4a)#21
humancto merged 1 commit into
mainfrom
feat/token-usage-tracking

Conversation

@humancto
Copy link
Copy Markdown
Owner

Summary

  • Adds per-model and per-fighter usage breakdown queries to the memory substrate (SQLite)
  • Extends the MeteringEngine with period-based breakdown methods (hour/day/month)
  • Adds GET /api/stats and GET /api/stats/fighters/:id API endpoints returning token counts, costs, and per-model/per-fighter breakdowns
  • Adds punch stats CLI command with --period (hour/day/month) and --fighter (name or ID) flags
  • Formatted table output with human-readable token counts (1.5K, 2.3M) and cost display

Example output

  Token Usage Stats (period: day)
  ============================================================

  Total:  160.2K in / 20.1K out  |  180.3K tokens  |  $0.51  |  20 requests

  MODEL                                INPUT      OUTPUT        COST    REQS
  ---------------------------------------------------------------------------
  claude-sonnet-4-20250514            120.0K      15.0K       $0.45      15
  gpt-4o-mini                          40.2K       5.1K       $0.06       5

  FIGHTER                              INPUT      OUTPUT        COST    REQS
  ----------------------------------------------------------------
  Punch                               160.2K      20.1K       $0.51      20

Test plan

  • cargo test --workspace passes (all tests pass, 0 failures)
  • cargo clippy --workspace -- -D warnings clean
  • cargo fmt --all -- --check clean
  • New unit tests for per-model breakdown, total model breakdown, fighter breakdown queries
  • Manual test: run daemon, send messages, verify punch stats shows correct data

Generated with Claude Code

- Add per-model and per-fighter usage breakdown queries to punch-memory
- Add MeteringEngine methods for period-based breakdown queries
- Add GET /api/stats and GET /api/stats/fighters/:id API endpoints
- Add `punch stats` CLI command with period and fighter filtering
- Formatted table output with token counts, costs, and request counts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d18288f3f4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return 1;
}

let base_url = match daemon_url(None) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor --config when resolving stats daemon URL

punch stats ignores the global config override because it hardcodes daemon_url(None), so the command always reads ~/.punch/config.toml even when the user passed --config <path>. In environments where the daemon is started from a non-default config (different api_listen), punch stats will incorrectly report that the daemon is not running or query the wrong instance.

Useful? React with 👍 / 👎.

Comment on lines +200 to +204
let fighter_name = fighters
.iter()
.find(|(fid, _, _)| *fid == fighter_id)
.map(|(_, m, _)| m.name.clone())
.unwrap_or_else(|| "unknown".to_string());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Return 404 when fighter stats target is unknown

The fighter stats handler silently substitutes "unknown" when the fighter ID is not present in the ring and still returns 200, which makes invalid IDs look like valid fighters with zero usage. This is especially misleading when --fighter is given as a UUID (it bypasses name resolution and hits this path directly), so callers cannot reliably distinguish typo/nonexistent IDs from real data.

Useful? React with 👍 / 👎.

@humancto humancto merged commit 25219ef into main Mar 26, 2026
5 checks passed
@humancto humancto deleted the feat/token-usage-tracking branch March 26, 2026 20:57
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