Skip to content

Return cost components and decline disputed gateway amounts - #104

Merged
VasiliyRad merged 2 commits into
mainfrom
vasiliy/cost-components
Oct 6, 2026
Merged

VasiliyRad merged 2 commits into
mainfrom
vasiliy/cost-components

Conversation

@VasiliyRad

Copy link
Copy Markdown
Collaborator

What

Two additions the internal app's spend work needs, both on the pricing path and both additive.

Cost components. A priced CostResult carries components (input_usd, output_usd, cache_read_usd, cache_write_usd), computed inside _price_tokens from the same price row, rates, long-context tier and off-peak multiplier as the total. The total is rounded once, exactly as before; each part is rounded and the residue lands in the input part, so the four sum to cost_usd exactly and a consumer that stores them can rebuild the total. The result also names the publisher of the priced model.

Disputed gateways. The catalog gains a top-level disputes list: a gateway whose reported amount is not believed for one publisher's models from a date, with a one-line note and the source page. parse_disputes validates it like retrieval; LoadedCatalog.disputes exposes it. resolve_billing(..., disputes=, at=) declines a qualified gateway's amount for a disputed publisher: the catalog price is billed, the gateway's figure stays in reported_cost_usd as evidence, and gateway_disputed is recorded in the reasons. When the catalog cannot price the call the gateway's figure stands. The first entry is Portkey for DeepSeek from 2026-09-10: Portkey's table predates DeepSeek's price change and reports a quarter to a half of the list price.

Both parameters default to the old behaviour, so existing callers are unchanged. Version 0.2.54 is already on main from #102 and untagged, so this rides on it.

Evidence

  • core/tests: 848 passed. New: test_components_sum_to_the_cost_and_follow_the_rules, test_components_split_a_cache_inclusive_input_the_way_the_total_does, test_an_unpriced_result_carries_no_components, four billing tests for the decline (applies from its date, to its publisher and gateway only, and leaves an unpriced call on the gateway figure), four parse_disputes tests, and a check that the shipped catalog disputes Portkey for DeepSeek.

🤖 Generated with Claude Code

VasiliyRad and others added 2 commits October 6, 2026 14:44
A priced CostResult now carries `components`: the cost split into input,
output, cache reads and cache writes from the same arithmetic as the
total. Each part is rounded and the residue goes to input, so the four sum
to cost_usd exactly and a consumer can store them without a second
rounding. The result also names the publisher of the priced model.

The catalog gains a `disputes` list: a gateway whose reported amount is
not believed for one publisher's models from a date, with a note and the
page that shows the figure wrong. resolve_billing takes the disputes and
the call time; for a disputed pair it bills the catalog price, keeps the
gateway's figure as evidence and records `gateway_disputed`. The first
entry is Portkey for DeepSeek from 2026-09-10, whose table predates
DeepSeek's price change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A dispute runs from a date, so a caller that omits the call time keeps the
gateway amount rather than declining figures that may predate it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@VasiliyRad

Copy link
Copy Markdown
Collaborator Author

Applied: _disputed returns False without at, so a caller that omits the call time keeps the qualified gateway amount; test_without_the_call_time_nothing_is_disputed covers it.

@VasiliyRad
VasiliyRad merged commit e0d9203 into main Oct 6, 2026
5 checks passed
@VasiliyRad
VasiliyRad deleted the vasiliy/cost-components branch October 6, 2026 22:56
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