feat(provider): expand GPT-5.6 context windows
- commit
- c7695e636dc9d085ef8752ae013a88b8e1ae2bce
- author
- brice · · 2026-08-18 20:43 UTC
- committer
- brice · · 2026-08-18 20:51 UTC
- parent
- e791659
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
4 files · +30 -19
M packages/provider/discover.go +7 -2
| @@ -295,8 +295,13 @@ func DiscoverOpenAICodex(ctx context.Context, token, accountID, baseURL string) | |||
| 295 | 295 | if m.ContextWindow != nil { | |
| 296 | 296 | contextWindow = *m.ContextWindow | |
| 297 | 297 | } | |
| 298 | - | if contextWindow == 0 && m.MaxContext != nil { | |
| 299 | - | contextWindow = *m.MaxContext | |
| 298 | + | if m.MaxContext != nil { | |
| 299 | + | switch { | |
| 300 | + | case contextWindow == 0: | |
| 301 | + | contextWindow = *m.MaxContext | |
| 302 | + | case *m.MaxContext >= openAIContextWindowTarget && contextWindow < openAIContextWindowTarget: | |
| 303 | + | contextWindow = openAIContextWindowTarget | |
| 304 | + | } | |
| 300 | 305 | } | |
| 301 | 306 | displayName := m.DisplayName | |
| 302 | 307 | if displayName == "" { | |
| @@ -295,8 +295,13 @@ func DiscoverOpenAICodex(ctx context.Context, token, accountID, baseURL string) | |||||
| 295 | if m.ContextWindow != nil { | 295 | if m.ContextWindow != nil { | ||
| 296 | contextWindow = *m.ContextWindow | 296 | contextWindow = *m.ContextWindow | ||
| 297 | } | 297 | } | ||
| 298 | - | if contextWindow == 0 && m.MaxContext != nil { | 298 | + | if m.MaxContext != nil { |
| 299 | - | contextWindow = *m.MaxContext | 299 | + | switch { |
| 300 | + | case contextWindow == 0: | |||
| 301 | + | contextWindow = *m.MaxContext | |||
| 302 | + | case *m.MaxContext >= openAIContextWindowTarget && contextWindow < openAIContextWindowTarget: | |||
| 303 | + | contextWindow = openAIContextWindowTarget | |||
| 304 | + | } | |||
| 300 | } | 305 | } | ||
| 301 | displayName := m.DisplayName | 306 | displayName := m.DisplayName | ||
| 302 | if displayName == "" { | 307 | if displayName == "" { | ||
M packages/provider/discover_test.go +9 -5
| @@ -26,9 +26,10 @@ func TestDiscoverOpenAICodex(t *testing.T) { | |||
| 26 | 26 | t.Errorf("originator = %q", got) | |
| 27 | 27 | } | |
| 28 | 28 | _, _ = io.WriteString(w, `{"models":[ | |
| 29 | - | {"slug":"gpt-5.6-luna","display_name":"GPT-5.6 Luna","supported_in_api":true,"context_window":272000,"max_context_window":400000,"supported_reasoning_levels":["low","medium","high"]}, | |
| 29 | + | {"slug":"gpt-5.6-luna","display_name":"GPT-5.6 Luna","supported_in_api":true,"context_window":272000,"max_context_window":872000,"supported_reasoning_levels":["low","medium","high"]}, | |
| 30 | 30 | {"slug":"gpt-hidden","display_name":"Hidden","supported_in_api":true,"visibility":"hide"}, | |
| 31 | 31 | {"slug":"gpt-unsupported","display_name":"Unsupported","supported_in_api":false}, | |
| 32 | + | {"slug":"gpt-limited","supported_in_api":true,"context_window":272000,"max_context_window":400000}, | |
| 32 | 33 | {"slug":"gpt-custom","supported_in_api":true,"max_context_window":100000} | |
| 33 | 34 | ]}`) | |
| 34 | 35 | })) | |
| @@ -38,15 +39,18 @@ func TestDiscoverOpenAICodex(t *testing.T) { | |||
| 38 | 39 | if err != nil { | |
| 39 | 40 | t.Fatal(err) | |
| 40 | 41 | } | |
| 41 | - | if len(got) != 2 { | |
| 42 | - | t.Fatalf("models = %+v, want 2 models", got) | |
| 42 | + | if len(got) != 3 { | |
| 43 | + | t.Fatalf("models = %+v, want 3 models", got) | |
| 43 | 44 | } | |
| 44 | - | if got[0].Provider != "openai-codex" || got[0].ID != "gpt-5.6-luna" || got[0].DisplayName != "GPT-5.6 Luna" || got[0].ContextWindow != 272000 || !got[0].Reasoning || got[0].Source != "live" { | |
| 45 | + | if got[0].Provider != "openai-codex" || got[0].ID != "gpt-5.6-luna" || got[0].DisplayName != "GPT-5.6 Luna" || got[0].ContextWindow != 500000 || !got[0].Reasoning || got[0].Source != "live" { | |
| 45 | 46 | t.Errorf("first model = %+v", got[0]) | |
| 46 | 47 | } | |
| 47 | - | if got[1].ID != "gpt-custom" || got[1].DisplayName != "gpt-custom" || got[1].ContextWindow != 100000 { | |
| 48 | + | if got[1].ID != "gpt-limited" || got[1].ContextWindow != 272000 { | |
| 48 | 49 | t.Errorf("second model = %+v", got[1]) | |
| 49 | 50 | } | |
| 51 | + | if got[2].ID != "gpt-custom" || got[2].DisplayName != "gpt-custom" || got[2].ContextWindow != 100000 { | |
| 52 | + | t.Errorf("third model = %+v", got[2]) | |
| 53 | + | } | |
| 50 | 54 | } | |
| 51 | 55 | ||
| 52 | 56 | func TestDiscoverOpenAICodexRejectsHTTPError(t *testing.T) { | |
| @@ -26,9 +26,10 @@ func TestDiscoverOpenAICodex(t *testing.T) { | |||||
| 26 | t.Errorf("originator = %q", got) | 26 | t.Errorf("originator = %q", got) | ||
| 27 | } | 27 | } | ||
| 28 | _, _ = io.WriteString(w, `{"models":[ | 28 | _, _ = io.WriteString(w, `{"models":[ | ||
| 29 | - | {"slug":"gpt-5.6-luna","display_name":"GPT-5.6 Luna","supported_in_api":true,"context_window":272000,"max_context_window":400000,"supported_reasoning_levels":["low","medium","high"]}, | 29 | + | {"slug":"gpt-5.6-luna","display_name":"GPT-5.6 Luna","supported_in_api":true,"context_window":272000,"max_context_window":872000,"supported_reasoning_levels":["low","medium","high"]}, |
| 30 | {"slug":"gpt-hidden","display_name":"Hidden","supported_in_api":true,"visibility":"hide"}, | 30 | {"slug":"gpt-hidden","display_name":"Hidden","supported_in_api":true,"visibility":"hide"}, | ||
| 31 | {"slug":"gpt-unsupported","display_name":"Unsupported","supported_in_api":false}, | 31 | {"slug":"gpt-unsupported","display_name":"Unsupported","supported_in_api":false}, | ||
| 32 | + | {"slug":"gpt-limited","supported_in_api":true,"context_window":272000,"max_context_window":400000}, | |||
| 32 | {"slug":"gpt-custom","supported_in_api":true,"max_context_window":100000} | 33 | {"slug":"gpt-custom","supported_in_api":true,"max_context_window":100000} | ||
| 33 | ]}`) | 34 | ]}`) | ||
| 34 | })) | 35 | })) | ||
| @@ -38,15 +39,18 @@ func TestDiscoverOpenAICodex(t *testing.T) { | |||||
| 38 | if err != nil { | 39 | if err != nil { | ||
| 39 | t.Fatal(err) | 40 | t.Fatal(err) | ||
| 40 | } | 41 | } | ||
| 41 | - | if len(got) != 2 { | 42 | + | if len(got) != 3 { |
| 42 | - | t.Fatalf("models = %+v, want 2 models", got) | 43 | + | t.Fatalf("models = %+v, want 3 models", got) |
| 43 | } | 44 | } | ||
| 44 | - | if got[0].Provider != "openai-codex" || got[0].ID != "gpt-5.6-luna" || got[0].DisplayName != "GPT-5.6 Luna" || got[0].ContextWindow != 272000 || !got[0].Reasoning || got[0].Source != "live" { | 45 | + | if got[0].Provider != "openai-codex" || got[0].ID != "gpt-5.6-luna" || got[0].DisplayName != "GPT-5.6 Luna" || got[0].ContextWindow != 500000 || !got[0].Reasoning || got[0].Source != "live" { |
| 45 | t.Errorf("first model = %+v", got[0]) | 46 | t.Errorf("first model = %+v", got[0]) | ||
| 46 | } | 47 | } | ||
| 47 | - | if got[1].ID != "gpt-custom" || got[1].DisplayName != "gpt-custom" || got[1].ContextWindow != 100000 { | 48 | + | if got[1].ID != "gpt-limited" || got[1].ContextWindow != 272000 { |
| 48 | t.Errorf("second model = %+v", got[1]) | 49 | t.Errorf("second model = %+v", got[1]) | ||
| 49 | } | 50 | } | ||
| 51 | + | if got[2].ID != "gpt-custom" || got[2].DisplayName != "gpt-custom" || got[2].ContextWindow != 100000 { | |||
| 52 | + | t.Errorf("third model = %+v", got[2]) | |||
| 53 | + | } | |||
| 50 | } | 54 | } | ||
| 51 | 55 | ||||
| 52 | func TestDiscoverOpenAICodexRejectsHTTPError(t *testing.T) { | 56 | func TestDiscoverOpenAICodexRejectsHTTPError(t *testing.T) { | ||
M packages/provider/models.go +8 -6
| @@ -6,6 +6,8 @@ import ( | |||
| 6 | 6 | "sync" | |
| 7 | 7 | ) | |
| 8 | 8 | ||
| 9 | + | const openAIContextWindowTarget = 500_000 | |
| 10 | + | ||
| 9 | 11 | // Model describes a single LLM we know about. | |
| 10 | 12 | type Model struct { | |
| 11 | 13 | Provider string // "anthropic" | "openai" | |
| @@ -337,19 +339,19 @@ var Catalog = []Model{ | |||
| 337 | 339 | }, | |
| 338 | 340 | { | |
| 339 | 341 | Provider: "openai", ID: "gpt-5.6-luna", DisplayName: "GPT-5.6 Luna", API: APIResponses, | |
| 340 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | |
| 342 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, | |
| 341 | 343 | PriceInput: 1, PriceOutput: 6, PriceCacheRead: 0.1, PriceCacheWrite: 1.25, | |
| 342 | 344 | Speculative: true, | |
| 343 | 345 | }, | |
| 344 | 346 | { | |
| 345 | 347 | Provider: "openai", ID: "gpt-5.6-sol", DisplayName: "GPT-5.6 Sol", API: APIResponses, | |
| 346 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | |
| 348 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, | |
| 347 | 349 | PriceInput: 5, PriceOutput: 30, PriceCacheRead: 0.5, PriceCacheWrite: 6.25, | |
| 348 | 350 | Speculative: true, | |
| 349 | 351 | }, | |
| 350 | 352 | { | |
| 351 | 353 | Provider: "openai", ID: "gpt-5.6-terra", DisplayName: "GPT-5.6 Terra", API: APIResponses, | |
| 352 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | |
| 354 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, | |
| 353 | 355 | PriceInput: 2.5, PriceOutput: 15, PriceCacheRead: 0.25, PriceCacheWrite: 3.125, | |
| 354 | 356 | Speculative: true, | |
| 355 | 357 | }, | |
| @@ -382,17 +384,17 @@ var Catalog = []Model{ | |||
| 382 | 384 | }, | |
| 383 | 385 | { | |
| 384 | 386 | Provider: "openai-codex", ID: "gpt-5.6-luna", DisplayName: "GPT-5.6 Luna", | |
| 385 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | |
| 387 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, | |
| 386 | 388 | PriceInput: 1, PriceOutput: 6, PriceCacheRead: 0.1, PriceCacheWrite: 1.25, | |
| 387 | 389 | }, | |
| 388 | 390 | { | |
| 389 | 391 | Provider: "openai-codex", ID: "gpt-5.6-sol", DisplayName: "GPT-5.6 Sol", | |
| 390 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | |
| 392 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, | |
| 391 | 393 | PriceInput: 5, PriceOutput: 30, PriceCacheRead: 0.5, PriceCacheWrite: 6.25, | |
| 392 | 394 | }, | |
| 393 | 395 | { | |
| 394 | 396 | Provider: "openai-codex", ID: "gpt-5.6-terra", DisplayName: "GPT-5.6 Terra", | |
| 395 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | |
| 397 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, | |
| 396 | 398 | PriceInput: 2.5, PriceOutput: 15, PriceCacheRead: 0.25, PriceCacheWrite: 3.125, | |
| 397 | 399 | }, | |
| 398 | 400 | } | |
| @@ -6,6 +6,8 @@ import ( | |||||
| 6 | "sync" | 6 | "sync" | ||
| 7 | ) | 7 | ) | ||
| 8 | 8 | ||||
| 9 | + | const openAIContextWindowTarget = 500_000 | |||
| 10 | + | ||||
| 9 | // Model describes a single LLM we know about. | 11 | // Model describes a single LLM we know about. | ||
| 10 | type Model struct { | 12 | type Model struct { | ||
| 11 | Provider string // "anthropic" | "openai" | 13 | Provider string // "anthropic" | "openai" | ||
| @@ -337,19 +339,19 @@ var Catalog = []Model{ | |||||
| 337 | }, | 339 | }, | ||
| 338 | { | 340 | { | ||
| 339 | Provider: "openai", ID: "gpt-5.6-luna", DisplayName: "GPT-5.6 Luna", API: APIResponses, | 341 | Provider: "openai", ID: "gpt-5.6-luna", DisplayName: "GPT-5.6 Luna", API: APIResponses, | ||
| 340 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | 342 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, |
| 341 | PriceInput: 1, PriceOutput: 6, PriceCacheRead: 0.1, PriceCacheWrite: 1.25, | 343 | PriceInput: 1, PriceOutput: 6, PriceCacheRead: 0.1, PriceCacheWrite: 1.25, | ||
| 342 | Speculative: true, | 344 | Speculative: true, | ||
| 343 | }, | 345 | }, | ||
| 344 | { | 346 | { | ||
| 345 | Provider: "openai", ID: "gpt-5.6-sol", DisplayName: "GPT-5.6 Sol", API: APIResponses, | 347 | Provider: "openai", ID: "gpt-5.6-sol", DisplayName: "GPT-5.6 Sol", API: APIResponses, | ||
| 346 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | 348 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, |
| 347 | PriceInput: 5, PriceOutput: 30, PriceCacheRead: 0.5, PriceCacheWrite: 6.25, | 349 | PriceInput: 5, PriceOutput: 30, PriceCacheRead: 0.5, PriceCacheWrite: 6.25, | ||
| 348 | Speculative: true, | 350 | Speculative: true, | ||
| 349 | }, | 351 | }, | ||
| 350 | { | 352 | { | ||
| 351 | Provider: "openai", ID: "gpt-5.6-terra", DisplayName: "GPT-5.6 Terra", API: APIResponses, | 353 | Provider: "openai", ID: "gpt-5.6-terra", DisplayName: "GPT-5.6 Terra", API: APIResponses, | ||
| 352 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | 354 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, |
| 353 | PriceInput: 2.5, PriceOutput: 15, PriceCacheRead: 0.25, PriceCacheWrite: 3.125, | 355 | PriceInput: 2.5, PriceOutput: 15, PriceCacheRead: 0.25, PriceCacheWrite: 3.125, | ||
| 354 | Speculative: true, | 356 | Speculative: true, | ||
| 355 | }, | 357 | }, | ||
| @@ -382,17 +384,17 @@ var Catalog = []Model{ | |||||
| 382 | }, | 384 | }, | ||
| 383 | { | 385 | { | ||
| 384 | Provider: "openai-codex", ID: "gpt-5.6-luna", DisplayName: "GPT-5.6 Luna", | 386 | Provider: "openai-codex", ID: "gpt-5.6-luna", DisplayName: "GPT-5.6 Luna", | ||
| 385 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | 387 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, |
| 386 | PriceInput: 1, PriceOutput: 6, PriceCacheRead: 0.1, PriceCacheWrite: 1.25, | 388 | PriceInput: 1, PriceOutput: 6, PriceCacheRead: 0.1, PriceCacheWrite: 1.25, | ||
| 387 | }, | 389 | }, | ||
| 388 | { | 390 | { | ||
| 389 | Provider: "openai-codex", ID: "gpt-5.6-sol", DisplayName: "GPT-5.6 Sol", | 391 | Provider: "openai-codex", ID: "gpt-5.6-sol", DisplayName: "GPT-5.6 Sol", | ||
| 390 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | 392 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, |
| 391 | PriceInput: 5, PriceOutput: 30, PriceCacheRead: 0.5, PriceCacheWrite: 6.25, | 393 | PriceInput: 5, PriceOutput: 30, PriceCacheRead: 0.5, PriceCacheWrite: 6.25, | ||
| 392 | }, | 394 | }, | ||
| 393 | { | 395 | { | ||
| 394 | Provider: "openai-codex", ID: "gpt-5.6-terra", DisplayName: "GPT-5.6 Terra", | 396 | Provider: "openai-codex", ID: "gpt-5.6-terra", DisplayName: "GPT-5.6 Terra", | ||
| 395 | - | ContextWindow: 272000, MaxOutput: 128000, Reasoning: true, | 397 | + | ContextWindow: openAIContextWindowTarget, MaxOutput: 128000, Reasoning: true, |
| 396 | PriceInput: 2.5, PriceOutput: 15, PriceCacheRead: 0.25, PriceCacheWrite: 3.125, | 398 | PriceInput: 2.5, PriceOutput: 15, PriceCacheRead: 0.25, PriceCacheWrite: 3.125, | ||
| 397 | }, | 399 | }, | ||
| 398 | } | 400 | } | ||
M packages/provider/provider_test.go +6 -6
| @@ -655,12 +655,12 @@ func TestGPT56CatalogEntries(t *testing.T) { | |||
| 655 | 655 | cacheRead float64 | |
| 656 | 656 | cacheWrite float64 | |
| 657 | 657 | }{ | |
| 658 | - | {"openai", "gpt-5.6-luna", 272000, 1, 6, 0.1, 1.25}, | |
| 659 | - | {"openai", "gpt-5.6-sol", 272000, 5, 30, 0.5, 6.25}, | |
| 660 | - | {"openai", "gpt-5.6-terra", 272000, 2.5, 15, 0.25, 3.125}, | |
| 661 | - | {"openai-codex", "gpt-5.6-luna", 272000, 1, 6, 0.1, 1.25}, | |
| 662 | - | {"openai-codex", "gpt-5.6-sol", 272000, 5, 30, 0.5, 6.25}, | |
| 663 | - | {"openai-codex", "gpt-5.6-terra", 272000, 2.5, 15, 0.25, 3.125}, | |
| 658 | + | {"openai", "gpt-5.6-luna", 500000, 1, 6, 0.1, 1.25}, | |
| 659 | + | {"openai", "gpt-5.6-sol", 500000, 5, 30, 0.5, 6.25}, | |
| 660 | + | {"openai", "gpt-5.6-terra", 500000, 2.5, 15, 0.25, 3.125}, | |
| 661 | + | {"openai-codex", "gpt-5.6-luna", 500000, 1, 6, 0.1, 1.25}, | |
| 662 | + | {"openai-codex", "gpt-5.6-sol", 500000, 5, 30, 0.5, 6.25}, | |
| 663 | + | {"openai-codex", "gpt-5.6-terra", 500000, 2.5, 15, 0.25, 3.125}, | |
| 664 | 664 | {"azure-openai-responses", "gpt-5.6-luna", 1050000, 1, 6, 0.1, 1.25}, | |
| 665 | 665 | {"azure-openai-responses", "gpt-5.6-sol", 1050000, 5, 30, 0.5, 6.25}, | |
| 666 | 666 | {"azure-openai-responses", "gpt-5.6-terra", 1050000, 2.5, 15, 0.25, 3.125}, | |
| @@ -655,12 +655,12 @@ func TestGPT56CatalogEntries(t *testing.T) { | |||||
| 655 | cacheRead float64 | 655 | cacheRead float64 | ||
| 656 | cacheWrite float64 | 656 | cacheWrite float64 | ||
| 657 | }{ | 657 | }{ | ||
| 658 | - | {"openai", "gpt-5.6-luna", 272000, 1, 6, 0.1, 1.25}, | 658 | + | {"openai", "gpt-5.6-luna", 500000, 1, 6, 0.1, 1.25}, |
| 659 | - | {"openai", "gpt-5.6-sol", 272000, 5, 30, 0.5, 6.25}, | 659 | + | {"openai", "gpt-5.6-sol", 500000, 5, 30, 0.5, 6.25}, |
| 660 | - | {"openai", "gpt-5.6-terra", 272000, 2.5, 15, 0.25, 3.125}, | 660 | + | {"openai", "gpt-5.6-terra", 500000, 2.5, 15, 0.25, 3.125}, |
| 661 | - | {"openai-codex", "gpt-5.6-luna", 272000, 1, 6, 0.1, 1.25}, | 661 | + | {"openai-codex", "gpt-5.6-luna", 500000, 1, 6, 0.1, 1.25}, |
| 662 | - | {"openai-codex", "gpt-5.6-sol", 272000, 5, 30, 0.5, 6.25}, | 662 | + | {"openai-codex", "gpt-5.6-sol", 500000, 5, 30, 0.5, 6.25}, |
| 663 | - | {"openai-codex", "gpt-5.6-terra", 272000, 2.5, 15, 0.25, 3.125}, | 663 | + | {"openai-codex", "gpt-5.6-terra", 500000, 2.5, 15, 0.25, 3.125}, |
| 664 | {"azure-openai-responses", "gpt-5.6-luna", 1050000, 1, 6, 0.1, 1.25}, | 664 | {"azure-openai-responses", "gpt-5.6-luna", 1050000, 1, 6, 0.1, 1.25}, | ||
| 665 | {"azure-openai-responses", "gpt-5.6-sol", 1050000, 5, 30, 0.5, 6.25}, | 665 | {"azure-openai-responses", "gpt-5.6-sol", 1050000, 5, 30, 0.5, 6.25}, | ||
| 666 | {"azure-openai-responses", "gpt-5.6-terra", 1050000, 2.5, 15, 0.25, 3.125}, | 666 | {"azure-openai-responses", "gpt-5.6-terra", 1050000, 2.5, 15, 0.25, 3.125}, | ||