Skip to content

fix(dashboard): price session, project, and branch costs per turn model - #165

Open
blineadam wants to merge 2 commits into
phuryn:DEVfrom
blineadam:fix/160-subagent-session-cost
Open

fix(dashboard): price session, project, and branch costs per turn model#165
blineadam wants to merge 2 commits into
phuryn:DEVfrom
blineadam:fix/160-subagent-session-cost

Conversation

@blineadam

Copy link
Copy Markdown

Summary

Fixes #160.

The Recent Sessions, Cost by Project, and Cost by Project & Branch tables were pricing all of a session’s tokens using its primary model. That meant sub-agent turns on cheaper models were still being charged at the main model’s rate.

The top Est. Cost card already prices each turn using its actual model, which is why the totals did not match. In one real Fable session with 27 Fable turns and 46 Sonnet turns, the session table showed $8.72 instead of the correct $6.01. Most of that difference came from Sonnet cache reads being priced at Fable’s higher rate.

Implementation

/api/data now adds a by_model token breakdown to each session using the model already stored for every turn in the turns table.

A new sessionCost() helper in the dashboard JavaScript calculates the session total by pricing each model’s share separately. It replaces the existing primary-model calculation in:

  • Cost sorting
  • The Recent Sessions table
  • The project aggregation
  • The project and branch aggregation
  • Session CSV exports

If a session does not have a model breakdown, it falls back to the existing primary-model calculation. This keeps databases without turn-level records working as before.

Nothing in the database needs to change. Existing history will be repriced automatically as soon as the updated code runs, with no rescan required.

Verification

Added three regression tests in tests/test_dashboard.py covering multi-model sessions:

  • by_model includes each model used by the session
  • Per-model token totals match the inserted turns
  • The combined breakdown matches the session’s total tokens

The full test suite passes with 150 tests.

I also ran the extracted dashboard JavaScript in Node and confirmed that a mixed Fable and Sonnet session is priced as the sum of each model’s usage. The empty-breakdown fallback also produces the same value as the previous calculation.

Finally, I verified the fix against a real database. The session, project, and project-and-branch tables now match the top Est. Cost card.

…uryn#160)

/api/data now ships each session a per-model token breakdown (by_model,
grouped from turns), and a sessionCost() helper sums calcCost over it.
Recent Sessions, Cost by Project, and Cost by Project & Branch previously
billed a session's total tokens at its single primary model, so sub-agent
turns on cheaper models were charged at the main model's rate. Falls back
to primary-model pricing when the breakdown is empty (old DBs).
sessionCost() prices each model in a session's by_model breakdown
separately, so a session can be billable even when its primary model
isn't (e.g. a non-billable main model that dispatched a billable
sub-agent). The Recent Sessions table still gated its n/a display on
isBillable(s.model) alone, so that real cost was computed but hidden.
sessionIsBillable() checks the whole breakdown instead.
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