diff --git a/routstr/payment/cost_calculation.py b/routstr/payment/cost_calculation.py index 27b04235..820bd174 100644 --- a/routstr/payment/cost_calculation.py +++ b/routstr/payment/cost_calculation.py @@ -418,10 +418,21 @@ def _calculate_from_tokens( }, ) + # Fold the cache-read/write cost into the visible ``input_msats`` so a + # dashboard that renders I / O / T sees ``input + output == total`` + # exactly. This mirrors ``_fold_cache_into_input_tokens`` (which rolls the + # cache token counts into the visible prompt total). The standalone + # ``cache_read_msats`` / ``cache_creation_msats`` fields stay populated for + # clients that want the breakdown; nothing sums the components to derive + # ``total_msats`` (it is computed independently above), so this is + # display-only and does not change what is billed. + visible_output_msats = int(calc_output_msats) + visible_input_msats = token_based_cost - visible_output_msats + return CostData( base_msats=0, - input_msats=int(calc_input_msats), - output_msats=int(calc_output_msats), + input_msats=visible_input_msats, + output_msats=visible_output_msats, total_msats=token_based_cost, total_usd=total_usd, input_tokens=input_tokens, diff --git a/tests/unit/test_cache_pricing.py b/tests/unit/test_cache_pricing.py index 14eb7965..c9af6e2d 100644 --- a/tests/unit/test_cache_pricing.py +++ b/tests/unit/test_cache_pricing.py @@ -181,10 +181,14 @@ async def test_deepseek_cache_hits_billed_at_cache_rate(model_pricing: Mock) -> result = await calculate_cost(response, max_cost=100000) assert isinstance(result, CostData) - # 1000 input @ 1 msat + 9000 cache reads @ 0.1 msat + 500 output @ 2 msat - assert result.input_msats == 1000 + # 1000 input @ 1 msat + 9000 cache reads @ 0.1 msat + 500 output @ 2 msat. + # input_msats folds the cache-read cost in (1000 + 900) so a dashboard + # rendering I/O/T sees input + output == total; the cache portion stays + # visible in cache_read_msats. assert result.cache_read_msats == 900 assert result.output_msats == 1000 + assert result.input_msats == 1900 + assert result.input_msats + result.output_msats == result.total_msats assert result.total_msats == 2900