Skip to content

Port upstream 0.70.0: price Mistral usage by event type, API zone and service tier - #718

Open
Finesssee wants to merge 1 commit into
port/micro-0.68.0-mistral-plan-detailfrom
port/micro-0.70.0-mistral-price-dimensions
Open

Finesssee wants to merge 1 commit into
port/micro-0.68.0-mistral-plan-detailfrom
port/micro-0.70.0-mistral-price-dimensions

Conversation

@Finesssee

Copy link
Copy Markdown
Collaborator

Summary

Ports upstream v0.70.0 steipete#4076: Mistral API spend now prices each billed usage row by its event type, API zone and service tier, not by billing metric and group alone.

  • The bug: the billing price table lists one metric several times, once per API zone and service tier and again under other event types. Keyed by metric::group, the last row won. In upstream's real September 2026 sample, mistral-medium-3-5 input was priced at the per-second audio rate, which is 100x the token rate, and cached and output tokens took the EU priority rates.
  • The fix: usage rows and prices now decode event_type, api_zone and service_tier. A row takes the price with the same event type, metric, group, zone and tier.
  • Legacy tables: a price row that omits both zone and tier is the only fallback, for rows with the same event type, metric and group. A price that names only one of them, or a different zone or tier, never prices the row, so no zone or tier is guessed. Tables and rows that omit every dimension still match as before.
  • The lookup lives in a new providers/mistral/pricing.rs submodule, which keeps mod.rs at 853 lines.

Token totals are unchanged: they already count consumed units per category.

Stacked on #657 (port/micro-0.68.0-mistral-plan-detail), like #717. This PR and #717 change different parts of providers/mistral/mod.rs.

Upstream reference

  • fix(mistral): price billing usage by event type, zone, and tier steipete/CodexBar#4076, upstream b468e0dbf3 (v0.70.0 release notes: "Mistral: price billing usage by event type, API zone, and service tier").
  • Tag-pinned v0.70.0 sources: MistralModels.swift (apiZone and serviceTier on MistralUsageEntry and MistralPrice), MistralUsageFetcher.swift (PriceKey, the exact key then the zoneless key, a later duplicate wins), Tests/CodexBarTests/MistralUsageParserTests.swift and docs/mistral.md.

Ported / Deferred

Change Status
event_type, api_zone and service_tier on usage rows and prices Ported
Exact price key, then the unqualified legacy row; unmatched rows cost 0 Ported
Upstream tests: price by event type, zone and tier in both table orders; legacy prices without guessing a zone or tier Ported (pricing.rs tests)
Category table refactor in MistralUsageFetcher (library tokens count only in daily buckets) Not needed. It is a pure refactor upstream; Windows already aggregates the same categories and has no Mistral daily buckets.
Daily bucket and 30-day history cost Not applicable. The Windows Mistral provider reports the monthly cost only.
docs/mistral.md paragraph Not applicable. There is no Windows Mistral doc page; the rule is documented in the pricing.rs module comment.

Validation

Run in the worker worktree on Rust 1.98.0 at 12c366e7:

Command Result
cargo +1.98.0 fmt --all --check pass
cargo +1.98.0 clippy --workspace --all-targets -- -D warnings pass
cargo +1.98.0 test -p codexbar providers::mistral 23 passed
cargo +1.98.0 test -p codexbar 2175 passed, 0 failed, 1 ignored
cargo +1.98.0 test -p codexbar-desktop-tauri -- --skip bootstrap_payload_exposes_every_provider_variant 463 passed, 0 failed

The skipped desktop test is the non-hermetic #684 test, which is not on this stacked base. #711 fixes it. The frontend is unchanged.

New tests in providers/mistral/pricing.rs:

  • prices_entries_by_event_type_zone_and_tier_instead_of_the_last_matching_metric: upstream's September 2026 sample, in both table orders. The old metric::group key fails the original order.
  • legacy_prices_match_qualified_usage_without_guessing_a_zone_or_tier: the unqualified price costs 40 billed units x 0.25 = 10. The EU-standard and global-priority prices cost 0, where the old key charged 10.
  • exact_dimensions_win_over_the_unqualified_legacy_row, a_partly_qualified_price_is_not_a_fallback, event_type_must_match_even_for_the_legacy_row and rows_without_a_metric_or_group_have_no_price.

Affected areas

  • rust/src/providers/mistral/pricing.rs (new): MistralPrice, PriceIndex and tests.
  • rust/src/providers/mistral/mod.rs: usage-row fields and the price lookup.

UI proof

Not applicable: backend only. The change alters the Mistral spend amount, not any UI surface, and the tests above cover it.

Upstream steipete#4076 (b468e0d). The billing price table lists one metric
once per API zone and service tier and again under other event types, so
keying prices by metric and group let the last row win: a per-second
audio price or a priority-tier price could price ordinary token rows.

Usage rows and prices now carry event_type, api_zone and service_tier.
A row takes the price with the same event type, metric, group, zone and
tier. Only a legacy price row that omits both zone and tier is a
fallback, for rows with the same event type, metric and group; a zone or
tier is never guessed. The lookup lives in a new pricing submodule.
@coderabbitai

coderabbitai Bot commented Sep 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: d832b022-455a-4b32-8c68-71947674c20a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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