summaryrefslogtreecommitdiff
path: root/internal/provider/anthropic/pricing.go
blob: c5b5298549af74c4a2b63ac34697439f206a2993 (plain)
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
package anthropic

import "strings"

// modelPrice is USD cost per million tokens for one model (or model family
// prefix).
type modelPrice struct {
	InputPerMTok  float64
	OutputPerMTok float64
}

// pricingTable maps a model-name *prefix* to its per-million-token pricing.
// Keyed by prefix (rather than exact model string) so dated/versioned model
// IDs (e.g. "claude-3-5-sonnet-20241022") still resolve without needing an
// entry per snapshot. Edit this table as Anthropic's pricing or model
// lineup changes — it intentionally has no other logic attached.
//
// Prices below are cached from training/skill data as of mid-2026 and are
// not fetched live; verify against https://platform.claude.com/docs/en/pricing
// before relying on them for real billing decisions.
var pricingTable = map[string]modelPrice{
	// Claude Fable 5 / Mythos family (most capable, most expensive tier).
	"claude-fable-5":        {InputPerMTok: 10.00, OutputPerMTok: 50.00},
	"claude-mythos-5":       {InputPerMTok: 10.00, OutputPerMTok: 50.00},
	"claude-mythos-preview": {InputPerMTok: 10.00, OutputPerMTok: 50.00},

	// Opus tier.
	"claude-opus-4-8": {InputPerMTok: 5.00, OutputPerMTok: 25.00},
	"claude-opus-4-7": {InputPerMTok: 5.00, OutputPerMTok: 25.00},
	"claude-opus-4-6": {InputPerMTok: 5.00, OutputPerMTok: 25.00},
	"claude-opus-4-5": {InputPerMTok: 5.00, OutputPerMTok: 25.00},
	"claude-opus-4-1": {InputPerMTok: 5.00, OutputPerMTok: 25.00},
	"claude-opus-4-0": {InputPerMTok: 5.00, OutputPerMTok: 25.00},
	"claude-opus-4":   {InputPerMTok: 5.00, OutputPerMTok: 25.00},
	"claude-3-opus":   {InputPerMTok: 15.00, OutputPerMTok: 75.00},

	// Sonnet tier.
	"claude-sonnet-5":   {InputPerMTok: 3.00, OutputPerMTok: 15.00},
	"claude-sonnet-4-6": {InputPerMTok: 3.00, OutputPerMTok: 15.00},
	"claude-sonnet-4-5": {InputPerMTok: 3.00, OutputPerMTok: 15.00},
	"claude-sonnet-4-0": {InputPerMTok: 3.00, OutputPerMTok: 15.00},
	"claude-sonnet-4":   {InputPerMTok: 3.00, OutputPerMTok: 15.00},
	"claude-3-7-sonnet": {InputPerMTok: 3.00, OutputPerMTok: 15.00},
	"claude-3-5-sonnet": {InputPerMTok: 3.00, OutputPerMTok: 15.00},
	"claude-3-sonnet":   {InputPerMTok: 3.00, OutputPerMTok: 15.00},

	// Haiku tier.
	"claude-haiku-4-5": {InputPerMTok: 1.00, OutputPerMTok: 5.00},
	"claude-3-5-haiku": {InputPerMTok: 0.80, OutputPerMTok: 4.00},
	"claude-3-haiku":   {InputPerMTok: 0.25, OutputPerMTok: 1.25},
}

// defaultPricing is used for unrecognized models rather than erroring —
// Sonnet-tier pricing is a reasonable mid-point default.
var defaultPricing = modelPrice{InputPerMTok: 3.00, OutputPerMTok: 15.00}

// pricingFor returns the per-million-token input/output pricing for model,
// matching the longest pricingTable prefix that model starts with. Falls
// back to defaultPricing for unrecognized models.
func pricingFor(model string) (inputPerMTok, outputPerMTok float64) {
	price := defaultPricing
	bestLen := -1
	for prefix, p := range pricingTable {
		if len(prefix) > bestLen && strings.HasPrefix(model, prefix) {
			bestLen = len(prefix)
			price = p
		}
	}
	return price.InputPerMTok, price.OutputPerMTok
}