1"""Model pricing constants for token cost estimation.

2

3 Prices are in USD per million tokens ($/Mtok).

4 Source: Anthropic pricing page (as of June 2026).

5"""

6

7 from __future__ import annotations

8

9# Per-model pricing: {model_id: {token_type: usd_per_million}}

10 MODEL_PRICING: dict[str, dict[str, float]] = {

11 # Claude 4.x

12 "claude-opus-4-7": {

13 "input": 15.0,

14 "output": 75.0,

15 "cache_read": 1.50,

16 "cache_creation": 18.75,

17 },

18 "claude-opus-4-6": {

19 "input": 15.0,

20 "output": 75.0,

21 "cache_read": 1.50,

22 "cache_creation": 18.75,

23 },

24 "claude-sonnet-4-6": {

25 "input": 3.0,

26 "output": 15.0,

27 "cache_read": 0.30,

28 "cache_creation": 3.75,

29 },

30 "claude-haiku-4-5-20251001": {

31 "input": 0.80,

32 "output": 4.0,

33 "cache_read": 0.08,

34 "cache_creation": 1.0,

35 },

36 # Claude 3.x (legacy, may still appear in logs)

37 "claude-opus-4-5": {

38 "input": 15.0,

39 "output": 75.0,

40 "cache_read": 1.50,

41 "cache_creation": 18.75,

42 },

43 "claude-sonnet-3-7": {

44 "input": 3.0,

45 "output": 15.0,

46 "cache_read": 0.30,

47 "cache_creation": 3.75,

48 },

49 "claude-haiku-3-5": {

50 "input": 0.80,

51 "output": 4.0,

52 "cache_read": 0.08,

53 "cache_creation": 1.0,

54 },

55}

56

57

58 def estimate_cost_usd(

59 model: str,

60 input_tokens: int,

61 output_tokens: int,

62 cache_read_tokens: int = 0,

63 cache_creation_tokens: int = 0,

64) -> float | None:

65 """Estimate cost in USD for a token usage event.

66

67 Returns None if the model is not in MODEL_PRICING.

68 """

69 pricing = MODEL_PRICING.get(model)

70 if pricing is None:

71 return None

72 per_m = 1_000_000.0

73 return (

74 input_tokens * pricing["input"] / per_m

75 + output_tokens * pricing["output"] / per_m

76 + cache_read_tokens * pricing["cache_read"] / per_m

77 + cache_creation_tokens * pricing["cache_creation"] / per_m

78 )