1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! Single source of truth for SM per-call USD cost estimation (DOC-14 §5.5).
//!
//! Why: the three SM providers (Anthropic, Bedrock, OpenRouter) all bill the
//! same Anthropic model FAMILIES (Sonnet / Haiku / Opus) at the same public
//! per-million-token rates, plus a couple of common OpenAI ids routed through
//! OpenRouter. SM-2 review flagged that copy-pasting that pricing table into
//! every provider file means the numbers silently drift out of sync the moment
//! one vendor changes a price. Centralising the table in one dated module gives
//! a single place to audit and update, and keeps every provider's cost
//! telemetry consistent.
//! What: exposes [`cost_per_million`] (family-substring → `(input, output)` USD
//! per million tokens) and [`estimate_cost_usd`] (token counts → USD). Both use
//! the same substring matching the per-provider copies used before, so behaviour
//! is identical for every previously-priced model.
//! Test: `pricing_tests.rs` (substring matching, known/unknown estimates, the
//! OpenRouter-routed OpenAI ids); per-provider tests still assert that their
//! `complete` round-trips compute the expected cost via this module.
//
// ─────────────────────────────────────────────────────────────────────────────
// Pricing as of 2026-06 — update when Anthropic/AWS/OpenRouter publish changes.
// - Anthropic: https://www.anthropic.com/pricing
// - AWS Bedrock: https://aws.amazon.com/bedrock/pricing/
// - OpenRouter: https://openrouter.ai/models
// All rates are USD per 1,000,000 tokens, expressed as (input, output).
// ─────────────────────────────────────────────────────────────────────────────
/// Approximate `(input, output)` USD cost per million tokens for the model
/// families the SM routes through any of its three providers.
///
/// Why: the SM logs a per-call cost estimate in `LlmResponse` (§5.5); all three
/// providers need the SAME table so their telemetry agrees and updates land in
/// one place. Unknown ids fall back to `(0.0, 0.0)` — a missing estimate, not
/// an error.
/// What: matches on the model-family substring (so version suffixes such as
/// `-4-6` still price) for the Anthropic Sonnet/Haiku/Opus tiers, accepting both
/// the bare `sonnet`/`haiku`/`opus` ids (direct Anthropic + Bedrock) and the
/// `claude-sonnet`/… ids OpenRouter uses; plus a couple of common OpenAI ids
/// routed through OpenRouter.
/// Test: `pricing::tests::cost_per_million_*`.
/// Compute a USD cost estimate from token counts and the pricing table.
///
/// Why: lets the SM total session cost and rank tiers by cost (§5.5) using one
/// shared formula across every provider.
/// What: applies [`cost_per_million`]; returns `0.0` for unknown models.
/// Test: `pricing::tests::estimate_cost_usd_*`.