Skip to content

feat(tui): show turn and session cost from odek limits - #23

Merged
jkyberneees merged 1 commit into
mainfrom
feat/limits-cost-ui
Aug 8, 2026
Merged

feat(tui): show turn and session cost from odek limits#23
jkyberneees merged 1 commit into
mainfrom
feat/limits-cost-ui

Conversation

@jkyberneees

Copy link
Copy Markdown
Contributor

What

Integrates with odek serve's new GET /api/limits endpoint and surfaces cost in the UI:

  • Header (left cluster): running session spend, e.g. sh.016
  • Turn footer: per-turn estimated cost next to the token counts
  • /stats: cost row with session rollup, plus · cap $X when max_cost_usd is configured

How

  • client.Limits() + Limits/ModelPrice types mirroring the odek contract, with ResolvePrices — an exact port of odek's per-model price-override semantics (per-field fallback to flat prices).
  • Limits fetched once at startup (batched with fetchModels); prices resolve against the active model at render time, so /models switches need no refetch.
  • Cost is computed client-side from the existing done event token counters (session fields are cumulative, so totals stay correct across reconnect/resume).
  • When odek has no token prices configured, the cost UI stays entirely hidden — odek never guesses provider prices, and neither does bodek.

Verification

  • make fmt / vet / lint — clean, 0 issues
  • make test — full race suite green
  • Coverage: all new paths at 100% (ResolvePrices, fetchLimits, handleLimitsMsg, formatUSD, lineCount); internal total 97.6% → 97.9%
  • Regression tests: header/footer/stats show cost with prices and hide it without; per-model override math; fetch error paths

Integrate with odek serve's GET /api/limits endpoint. The client learns
Limits() plus a ResolvePrices port of odek's per-model price overrides;
the TUI fetches limits at startup and renders:

- session spend in the header's left cluster,
- per-turn cost in the finalized turn footer,
- a cost row (with max_cost_usd cap when configured) in /stats.

Cost derives from the done event's cumulative session token counters, so
it stays correct across reconnect/resume. Prices resolve against the
active model at render time, so /models switches need no refetch. When
odek has no token prices configured the cost UI stays entirely hidden —
odek never guesses provider prices, and neither does bodek.

Coverage: new code paths at 100% (ResolvePrices, fetchLimits,
handleLimitsMsg, formatUSD, lineCount); internal total 97.6% -> 97.9%.
@jkyberneees
jkyberneees merged commit 916a8df into main Aug 8, 2026
5 checks passed
@jkyberneees
jkyberneees deleted the feat/limits-cost-ui branch August 8, 2026 19:21
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