#1642

fix(cost): pair provider charges with their own response's estimate

Opensatoridev01wants to merge intofrom

Problem

Strix estimates the cost of every LLM response. Some providers, like OpenRouter, also report what they actually charged. Once a single response comes back with a real charge, the reported cost becomes the sum of the real charges only, and the estimates for every other response are dropped.

So if some responses never get a real charge (the provider doesn't price that model, or a stream ends before the usage arrives), their cost disappears from the total. The scan looks cheaper than it was, and --max-budget stops it later than it should.

Fix

Each real charge now replaces only the estimate of its own response, matched by response id. A response with no real charge keeps its estimate. If no id is available, the cost is added up the way it is today.

Finding the id takes some care, because the Agents SDK doesn't fill it in for Chat Completions. It's read from the provider's data on the response, or from the request log when that's missing. If the match would be a guess, nothing is paired.

Manually configured prices still win, as before.

Testing

  • New tests in tests/test_cost_response_pairing.py: a real charge replaces its estimate, in either arrival order; a response without a charge keeps its estimate, also after the run is reloaded; each agent's responses are paired separately.
  • More ledger tests in tests/test_pricing.py, and tests/test_cost_tracking.py updated for the new argument.
  • The full suite has the same 20 failures as an unmodified main on my machine (macOS, Python 3.13), and none new.
  • ruff format and mypy pass. ruff check only reports the warning that's already on add_vulnerability_report.

Activity

5
greptile-apps[bot]6d ago

Confidence Score: 4/5

[Medium impact] The change affects cost totals and budget decisions across LLM calls in a scan.

The PR appears safe to merge, with a non-blocking concern about repeated cost recounting.

Findings

  1.  Long scans recount old responses ▶
Fix with agent prompt
### Issue 1
strix/report/usage.py:170-176
`total_cost` now copies and scans every recorded response whenever it is read. `record_sdk_usage` saves after every completed call, and each save reads this property. Since the dictionaries retain their entries until reload, doubling the response count roughly quadruples the total counting work across a scan.

This is non-blocking, but makes budget checks and saves slower as scans grow. Keep running totals and adjust them when an estimate or charge changes instead.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Provider charges now replace the estimate for their own response.

  • Provider charges replace only the estimates for their own responses.

Intentional behavior: satoridev01 states that calls without matching IDs retain the existing fallback.

Reviews (1) · Last reviewed commit: "fix(cost): pair provider charges with th..." · Reviewed by Greptile

greptile-apps[bot]reviewed6d ago
satoridev01reviewed5d ago