1package provider
2
3import (
4 "math"
5 "slices"
6 "testing"
7)
8
9func TestAstraReleasedMetadata(t *testing.T) {
10 for _, name := range []string{"openai", "openai-codex"} {
11 t.Run(name, func(t *testing.T) {
12 m, err := FindModel(name, "gpt-6-astra")
13 if err != nil {
14 t.Fatal(err)
15 }
16 if m.ContextWindow != 500000 || m.MaxOutput != 128000 || m.Speculative {
17 t.Fatalf("released model must retain the intentional 500k budget: %+v", m)
18 }
19 if name == "openai" && m.API != APIResponses {
20 t.Fatalf("API = %q, want Responses", m.API)
21 }
22 if !slices.Contains(AvailableReasoningLevels(m), "max") || ClampReasoningForModel(m, "max") != "max" {
23 t.Fatalf("native max unavailable: %v", AvailableReasoningLevels(m))
24 }
25 if m.PriceTierInputTokens != 272000 || m.PriceInputAbove != 20 || m.PriceOutputAbove != 75 || m.PriceCacheReadAbove != 2 || m.PriceCacheWriteAbove != 25 {
26 t.Fatalf("long-context rates: %+v", m)
27 }
28 for _, tc := range []struct {
29 name string
30 usage Usage
31 want float64
32 }{
33 {"at_threshold", Usage{InputTokens: 100000, CacheReadTokens: 100000, CacheWriteTokens: 72000, OutputTokens: 1000}, 4.075},
34 {"above_threshold", Usage{InputTokens: 100000, CacheReadTokens: 100001, CacheWriteTokens: 72000, OutputTokens: 1000}, 4.075002},
35 } {
36 t.Run(tc.name, func(t *testing.T) {
37 if got := ComputeCost(m, tc.usage); math.Abs(got-tc.want) > 1e-9 {
38 t.Fatalf("cost = %.9f, want %.9f", got, tc.want)
39 }
40 })
41 }
42 })
43 }
44}
45
46func TestAstraResponsesCapabilities(t *testing.T) {
47 public := NewOpenAIResponsesNamed("synthetic-token", "", "openai").(*renamedClient).inner.(*responsesWebSocketClient).http
48 custom := NewOpenAIResponsesNamed("synthetic-token", "https://example.com/v1/responses", "openai").(*renamedClient).inner.(*codexClient)
49 for _, tc := range []struct {
50 name string
51 client *codexClient
52 breakpoint bool
53 }{
54 {"public", public, true},
55 {"subscription", newOpenAICodexClient("synthetic-token", "synthetic-account", ""), false},
56 {"custom", custom, false},
57 } {
58 t.Run(tc.name, func(t *testing.T) {
59 wire, err := tc.client.buildRequest(Request{Model: "gpt-6-astra", Reasoning: "max", Messages: []Message{{Role: RoleUser, Content: []Content{TextBlock{Text: "hello"}}}}})
60 if err != nil {
61 t.Fatal(err)
62 }
63 if wire.Reasoning == nil || wire.Reasoning.Effort != "max" {
64 t.Fatalf("reasoning = %+v, want max", wire.Reasoning)
65 }
66 if !tc.breakpoint {
67 if wire.PromptCacheOptions != nil || len(wire.Input) != 1 {
68 t.Fatalf("undeclared endpoint received explicit caching: %+v", wire)
69 }
70 return
71 }
72 if wire.PromptCacheOptions == nil || wire.PromptCacheOptions.Mode != "implicit" || len(wire.Input) != 2 {
73 t.Fatalf("missing stable boundary with implicit history caching: %+v", wire)
74 }
75 boundary, ok := wire.Input[0].(codexInputMessage)
76 if !ok || boundary.Role != "developer" || len(boundary.Content) != 1 {
77 t.Fatalf("boundary = %#v", wire.Input[0])
78 }
79 text, ok := boundary.Content[0].(codexInputText)
80 if !ok || text.PromptCacheBreakpoint == nil || text.PromptCacheBreakpoint.Mode != "explicit" {
81 t.Fatalf("breakpoint = %#v", boundary.Content[0])
82 }
83 })
84 }
85}