Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 37 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -744,16 +744,17 @@ or applies today's `/fast` setting retroactively.
combination is unpriced and interrupts clean learning rather than silently
applying an invented multiplier. Benchmark comparisons continue to use Standard rates.

Tier pricing was reviewed on **12 October 2026**: **GPT-6.1 Sol, GPT-6 (Astra, Sol, Luna) and GPT-5.6
Tier pricing was reviewed on **27 October 2026**: **GPT-6.1 (Sol, Terra), GPT-6 (Astra, Sol, Luna) and GPT-5.6
(Sol, Terra, Luna)** use **2× applicable standard API prices** for `fast` / the
legacy `priority` alias. Astra and GPT-6.1 Sol **Ultrafast** use **6×** applicable standard API prices.
**Flex** uses **½×** on the maintained GPT-6/GPT-5.6 models, GPT-5.2 and GPT-5.5.
legacy `priority` alias. Astra and GPT-6.1 Sol **Ultrafast** use **6×** applicable standard API prices;
GPT-6.1 Terra has no maintained Ultrafast rate.
**Flex** uses **½×** on the maintained GPT-6.1/GPT-6/GPT-5.6 models, GPT-5.2 and GPT-5.5.
GPT-5.2 fallback pricing and published short-context Fast rates for GPT-5.2,
GPT-5.3 Codex, GPT-5.4/Mini and GPT-5.5 are also maintained; GPT-5.5 Fast is 2.5×.
Other explicit model/tier combinations and unpublished long-context Fast rates
remain unavailable. Adjustments follow per-response long-context and cache
calculations; reasoning output is not counted twice. See the official
[Astra pricing](https://developers.openai.com/api/docs/models/gpt-6-astra),
[API pricing table](https://developers.openai.com/api/docs/pricing),
[Codex speed guidance](https://learn.chatgpt.com/docs/agent-configuration/speed),
and [API Fast-mode guide](https://developers.openai.com/api/docs/guides/fast-mode).
The footer's standard-price retrieval date remains separate from this tier review.
Expand Down Expand Up @@ -868,7 +869,7 @@ hidden from Sessions; hiding presentation does not exclude their aggregate
subscription impact from Quota views.
The embedded rates come from the
[official OpenAI API pricing page](https://developers.openai.com/api/docs/pricing)
and were last reviewed on **2026-10-12**.
and were last reviewed on **2026-10-27**.
Every Quota presentation repeats that retrieval date and a terminal hyperlink
to the source in its footer when the terminal is wide enough, matching the
Benchmark view and making stale compiled pricing conspicuous wherever a priced
Expand Down Expand Up @@ -2525,24 +2526,44 @@ release was built. Codexometer does not inherit or guess such a price. Pricing
can change after a binary is released; consult the
[official OpenAI API pricing page](https://developers.openai.com/api/docs/pricing)
for current values. The compiled table was last updated from
that page on **2026-09-30**; every pricing-bearing Quota or Benchmark footer
that page on **2026-10-27**; every pricing-bearing Quota or Benchmark footer
Comment thread
merefield marked this conversation as resolved.
displays both the retrieval date and a terminal hyperlink to the source when
space permits, so stale embedded pricing is visible while interpreting results.
The maintained price table covers GPT-6.1 Sol, GPT-6 Astra, GPT-6 Sol, GPT-6 Luna, GPT-5.6 Sol, GPT-5.6 Terra,
GPT-5.6 Luna, GPT-5.5, GPT-5.4, GPT-5.4 Mini, and GPT-5.3 Codex.
The maintained table uses these standard USD rates per million tokens. All
entries were checked against the official pricing page on the date above.

The September additions use these standard USD rates per million tokens:

| Model | Input | Cached input | Cache writes | Output |
| Model | Input | Cached input | Cache writes (30 minutes) | Output |
| --- | ---: | ---: | ---: | ---: |
| GPT-6 Astra | $10.00 | $1.00 | $12.50 | $50.00 |
| [GPT-6.1 Sol](https://developers.openai.com/api/docs/models/gpt-6.1-sol) | $2.00 | $0.10 | $2.50 | $10.00 |
| [GPT-6.1 Terra](https://developers.openai.com/api/docs/models/gpt-6.1-terra) | $1.00 | $0.05 | $1.25 | $5.00 |
| [GPT-6 Sol](https://developers.openai.com/api/docs/models/gpt-6-sol) | $2.00 | $0.20 | $2.50 | $10.00 |
| [GPT-6 Luna](https://developers.openai.com/api/docs/models/gpt-6-luna) | $0.10 | $0.01 | $0.125 | $0.50 |

Above 272,000 input tokens per response, input and cache rates double and
output rates multiply by 1.5 for the entire response. Requested Fast/priority
pricing doubles the applicable rates in live estimates; benchmark API EQ
continues to use standard pricing. Existing model prices are retained.
| GPT-5.6 Sol | $4.00 | $0.40 | $5.00 | $20.00 |
| GPT-5.6 Terra | $2.00 | $0.20 | $2.50 | $12.00 |
| GPT-5.6 Luna | $0.20 | $0.02 | $0.25 | $1.20 |
| GPT-5.5 | $5.00 | $0.50 | Not published | $30.00 |
| GPT-5.4 | $2.50 | $0.25 | Not published | $15.00 |
| GPT-5.4 Mini | $0.75 | $0.075 | Not published | $4.50 |
| GPT-5.3 Codex | $1.75 | $0.175 | Not published | $14.00 |
| GPT-5.2 | $1.75 | $0.175 | Not published | $14.00 |

For GPT-6, GPT-6.1, GPT-5.6, GPT-5.5 and GPT-5.4 (not Mini), above 272,000
input tokens per response, input and cache rates double and output rates
multiply by 1.5 for the entire response. Models without maintained long-context
rates remain unpriced above that threshold. Requested Fast/priority pricing
doubles the applicable rates in live estimates, except GPT-5.5's 2.5× rate;
long-context Fast pricing for GPT-5.4 and GPT-5.5 remains unpriced. Published
Flex rates are half Standard; Ultrafast is 6× Standard for GPT-6 Astra and
GPT-6.1 Sol only. GPT-6.1 Terra has no maintained Ultrafast price, and the
unpublished ID `gpt-6-terra` is not treated as an alias. Benchmark API EQ
continues to use standard pricing.

Cache-write estimates use the published 30-minute rates. The observed token
breakdown does not identify retention duration; 12-hour cache writes cost more
and are not separately accounted for. Existing model prices are unchanged by
this update; GPT-5.6 Sol's promotional pricing is currently advertised through
at least 21 November 2026.

The figures are useful for comparing these particular observed trials, but
they have important limitations:
Expand Down
3 changes: 2 additions & 1 deletion internal/codex/benchmark.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const (
// the published rates compiled into this release. Keep both in sync whenever
// standardAPIPrices changes.
StandardAPIPricingSourceURL = "https://developers.openai.com/api/docs/pricing"
StandardAPIPricingRetrievedOn = "2026-10-12"
StandardAPIPricingRetrievedOn = "2026-10-27"
)

// BenchmarkUsage is the app-server token breakdown for one isolated turn.
Expand Down Expand Up @@ -1652,6 +1652,7 @@ type apiPrice struct {
var standardAPIPrices = map[string]apiPrice{
"gpt-5.2": {input: 1.75, cached: 0.175, output: 14.00},
"gpt-6.1-sol": {input: 2.00, cached: 0.10, cacheWrite: 2.50, cacheWriteKnown: true, output: 10.00, longInput: 4.00, longCached: 0.20, longCacheWrite: 5.00, longOutput: 15.00, longKnown: true},
"gpt-6.1-terra": {input: 1.00, cached: 0.05, cacheWrite: 1.25, cacheWriteKnown: true, output: 5.00, longInput: 2.00, longCached: 0.10, longCacheWrite: 2.50, longOutput: 7.50, longKnown: true},
"gpt-6-sol": {input: 2.00, cached: 0.20, cacheWrite: 2.50, cacheWriteKnown: true, output: 10.00, longInput: 4.00, longCached: 0.40, longCacheWrite: 5.00, longOutput: 15.00, longKnown: true},
"gpt-6-luna": {input: 0.10, cached: 0.01, cacheWrite: 0.125, cacheWriteKnown: true, output: 0.50, longInput: 0.20, longCached: 0.02, longCacheWrite: 0.25, longOutput: 0.75, longKnown: true},
"gpt-6-astra": {input: 10.00, cached: 1.00, cacheWrite: 12.50, cacheWriteKnown: true, output: 50.00, longInput: 20.00, longCached: 2.00, longCacheWrite: 25.00, longOutput: 75.00, longKnown: true},
Expand Down
12 changes: 7 additions & 5 deletions internal/codex/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,7 @@ func TestStandardAPIPricesMatchPublishedRates(t *testing.T) {
want := map[string]apiPrice{
"gpt-5.2": {input: 1.75, cached: 0.175, output: 14.00},
"gpt-6.1-sol": {input: 2.00, cached: 0.10, cacheWrite: 2.50, cacheWriteKnown: true, output: 10.00, longInput: 4.00, longCached: 0.20, longCacheWrite: 5.00, longOutput: 15.00, longKnown: true},
"gpt-6.1-terra": {input: 1.00, cached: 0.05, cacheWrite: 1.25, cacheWriteKnown: true, output: 5.00, longInput: 2.00, longCached: 0.10, longCacheWrite: 2.50, longOutput: 7.50, longKnown: true},
"gpt-6-sol": {input: 2.00, cached: 0.20, cacheWrite: 2.50, cacheWriteKnown: true, output: 10.00, longInput: 4.00, longCached: 0.40, longCacheWrite: 5.00, longOutput: 15.00, longKnown: true},
"gpt-6-luna": {input: 0.10, cached: 0.01, cacheWrite: 0.125, cacheWriteKnown: true, output: 0.50, longInput: 0.20, longCached: 0.02, longCacheWrite: 0.25, longOutput: 0.75, longKnown: true},
"gpt-6-astra": {input: 10.00, cached: 1.00, cacheWrite: 12.50, cacheWriteKnown: true, output: 50.00, longInput: 20.00, longCached: 2.00, longCacheWrite: 25.00, longOutput: 75.00, longKnown: true},
Expand Down Expand Up @@ -1237,13 +1238,14 @@ func TestStandardAPIPricesMatchPublishedRates(t *testing.T) {
}
}

func TestGPT6SolLunaPricingBoundaries(t *testing.T) {
func TestGPT6PricingBoundaries(t *testing.T) {
for _, tc := range []struct {
model string
input, cached, write, output float64
}{
{"gpt-6-sol", 2, 0.2, 2.5, 10},
{"gpt-6.1-sol", 2, 0.1, 2.5, 10},
{"gpt-6.1-terra", 1, 0.05, 1.25, 5},
{"gpt-6-luna", 0.1, 0.01, 0.125, 0.5},
} {
for _, input := range []int64{272000, 272001} {
Expand All @@ -1258,18 +1260,18 @@ func TestGPT6SolLunaPricingBoundaries(t *testing.T) {
if !known || issue != "" || math.Abs(got-want) > 1e-12 {
t.Fatalf("%s input %d: %g, %v, %s; want %g", model, input, got, known, issue, want)
}
for _, tier := range []string{"fast", "priority"} {
for tier, factor := range map[string]float64{"default": 1, "fast": 2, "priority": 2, "flex": 0.5} {
r := &LiveUsageReader{}
call := LiveModelCall{Model: model, RequestedServiceTier: tier}
r.finalizeCallPricing(&call, usage)
if !call.APIEqKnown || math.Abs(call.APIEqUSD+call.APIEqTierPremiumUSD-2*want) > 1e-12 {
t.Fatalf("%s %s input %d: incorrect Fast cost: %+v", model, tier, input, call)
if !call.APIEqKnown || math.Abs(call.APIEqUSD+call.APIEqTierPremiumUSD-factor*want) > 1e-12 {
t.Fatalf("%s %s input %d: incorrect tier cost: %+v", model, tier, input, call)
}
}
}
}
}
for _, model := range []string{"gpt-6-terra", "gpt-6-sol-preview", "gpt-6-luna-preview", "gpt-6.1-sol-preview", "gpt-6.1-astra", "gpt-6.1-luna"} {
for _, model := range []string{"gpt-6-terra", "gpt-6.1-terra-preview", "gpt-6.1-terra-2026-99-99", "gpt-6-sol-preview", "gpt-6-luna-preview", "gpt-6.1-sol-preview", "gpt-6.1-astra", "gpt-6.1-luna"} {
if _, known := priceForModel(model); known {
t.Fatalf("unpublished model %s was priced", model)
}
Expand Down
9 changes: 4 additions & 5 deletions internal/codex/service_tier.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import (
)

// FastAPIPricingRetrievedOn is separate from the standard-price review date.
// Sources: https://developers.openai.com/api/docs/pricing and
// https://learn.chatgpt.com/docs/agent-configuration/speed (GPT-5.6 API rates).
const FastAPIPricingRetrievedOn = "2026-10-12"
// Source: https://developers.openai.com/api/docs/pricing (Fast, Flex and Ultrafast).
const FastAPIPricingRetrievedOn = "2026-10-27"

// requestedTierPremium prices a single response's requested tier. It does not
// claim that the backend delivered/billed that tier. Empty means unavailable,
Expand All @@ -29,7 +28,7 @@ func requestedTierMultiplier(model, tier string) (float64, bool) {
return 1, true
case "fast", "priority":
switch name {
case "gpt-6-astra", "gpt-6.1-sol", "gpt-6-sol", "gpt-6-luna", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.2", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex":
case "gpt-6-astra", "gpt-6.1-sol", "gpt-6.1-terra", "gpt-6-sol", "gpt-6-luna", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.2", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex":
return 2, true
case "gpt-5.5":
return 2.5, true
Expand All @@ -40,7 +39,7 @@ func requestedTierMultiplier(model, tier string) (float64, bool) {
}
case "flex":
switch name {
case "gpt-6-astra", "gpt-6.1-sol", "gpt-6-sol", "gpt-6-luna", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.2", "gpt-5.5":
case "gpt-6-astra", "gpt-6.1-sol", "gpt-6.1-terra", "gpt-6-sol", "gpt-6-luna", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.2", "gpt-5.5":
return 0.5, true
}
}
Expand Down
37 changes: 37 additions & 0 deletions internal/codex/service_tier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ func TestRequestedTierPremium(t *testing.T) {
{"gpt-6-astra", "fast", 3, true},
{"gpt-6-sol", "fast", 3, true},
{"gpt-6.1-sol", "fast", 3, true},
{"gpt-6.1-terra", "fast", 3, true},
{" GPT-6.1-TERRA-2026-10-27 ", " PRIORITY ", 3, true},
{"gpt-6.1-terra", "flex", -1.5, true},
{"gpt-6.1-terra", "ultrafast", 0, false},
{"gpt-6.1-terra-preview", "fast", 0, false},
{"gpt-6-terra", "fast", 0, false},
{" GPT-6.1-SOL-2026-09-30 ", " PRIORITY ", 3, true},
{"gpt-6.1-sol-preview", "fast", 0, false},
{"gpt-6-luna", "priority", 3, true},
Expand All @@ -43,6 +49,37 @@ func TestRequestedTierPremium(t *testing.T) {
}
}

func TestMaintainedTierMultipliersMatchPublishedRates(t *testing.T) {
// Reviewed against the Standard, Fast, Flex and Ultrafast tables on
// https://developers.openai.com/api/docs/pricing, 2026-10-27.
for _, test := range []struct {
model string
fast, flex, ultrafast float64
}{
{"gpt-6-astra", 2, 0.5, 6},
{"gpt-6.1-sol", 2, 0.5, 6},
{"gpt-6.1-terra", 2, 0.5, 0},
{"gpt-6-sol", 2, 0.5, 0},
{"gpt-6-luna", 2, 0.5, 0},
{"gpt-5.6-sol", 2, 0.5, 0},
{"gpt-5.6-terra", 2, 0.5, 0},
{"gpt-5.6-luna", 2, 0.5, 0},
{"gpt-5.5", 2.5, 0.5, 0},
{"gpt-5.4", 2, 0, 0},
{"gpt-5.4-mini", 2, 0, 0},
{"gpt-5.3-codex", 2, 0, 0},
{"gpt-5.2", 2, 0.5, 0},
} {
for tier, want := range map[string]float64{"standard": 1, "fast": test.fast, "priority": test.fast, "flex": test.flex, "ultrafast": test.ultrafast} {
got, known := requestedTierMultiplier(test.model, tier)
// Zero denotes a deliberately unmaintained combination, not free usage.
if known != (want > 0) || known && got != want {
t.Errorf("%s %s = %g, known %v; want %g", test.model, tier, got, known, want)
}
}
}
}

func TestFastPricingPreservesTokenClassesAndLongContext(t *testing.T) {
for _, input := range []int64{272000, 272001} {
r := &LiveUsageReader{}
Expand Down
4 changes: 2 additions & 2 deletions internal/ui/english_snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func TestEnglishPresentationSnapshot(t *testing.T) {
// Baseline includes Pace graph controls, explicit panel/border
// backgrounds, Sessions Zero/Close All, the ACTIVE category and responsive
// summary filters; every theme, view and size
// remains covered. The displayed pricing review date is now 2026-10-12.
const want = "51ffe11ef44315386abd14364c7c64e2dd3c56ada230d21be539e2e29db88f48"
// remains covered. The displayed pricing review date is now 2026-10-27.
const want = "20af39ed4d2355a8cc183775b36d8d0ed4dc51a1284858a98c0011587a84a0ca"
if got != want {
t.Fatalf("English presentation changed: got %s, want %s", got, want)
}
Expand Down
Loading