1package provider
2
3import (
4 "slices"
5 "testing"
6)
7
8func TestSonnet55CatalogAndThinking(t *testing.T) {
9 for _, tc := range []struct {
10 name string
11 client *anthropicClient
12 }{
13 {"api-key", NewAnthropic("synthetic-key", "").(*anthropicClient)},
14 {"oauth", NewAnthropicOAuth("synthetic-token", "").(*anthropicClient)},
15 } {
16 t.Run(tc.name, func(t *testing.T) {
17 const id = "claude-sonnet-5-5"
18 m, err := FindModel("anthropic", id)
19 if err != nil {
20 t.Fatal(err)
21 }
22 if m.ContextWindow != 1000000 || m.MaxOutput != 128000 || !m.Reasoning || !m.AdaptiveThinking || m.Speculative {
23 t.Fatalf("unexpected capabilities: %+v", m)
24 }
25 if m.PriceInput != 2 || m.PriceOutput != 10 || m.PriceCacheRead != 0.2 || m.PriceCacheWrite != 2.5 {
26 t.Fatalf("unexpected pricing: %+v", m)
27 }
28 want := []string{"low", "medium", "high", "xhigh", "max"}
29 if got := AvailableReasoningLevels(m); !slices.Equal(got, want) {
30 t.Fatalf("levels = %q, want %q", got, want)
31 }
32 for _, level := range []string{"", "off", "minimum", "low", "medium", "high", "xhigh", "max"} {
33 effort := level
34 if level == "" || level == "off" || level == "minimum" {
35 effort = "low"
36 }
37 if got := ClampReasoningForModel(m, level); got != effort {
38 t.Errorf("clamp(%q) = %q, want %q", level, got, effort)
39 }
40 temperature := float32(0.5)
41 wire, err := tc.client.buildRequest(Request{Model: id, Reasoning: level, Temperature: &temperature})
42 if err != nil {
43 t.Fatal(err)
44 }
45 if wire.Model != id || wire.MaxTokens != 128000 || wire.Temperature != nil {
46 t.Fatalf("unexpected request: %+v", wire)
47 }
48 if wire.Thinking == nil || wire.Thinking.Type != "adaptive" || wire.Thinking.BudgetTokens != 0 {
49 t.Fatalf("thinking = %+v", wire.Thinking)
50 }
51 if wire.OutputConfig == nil || wire.OutputConfig.Effort != effort {
52 t.Fatalf("output config = %+v, want effort %q", wire.OutputConfig, effort)
53 }
54 }
55 })
56 }
57}
58
59func TestSonnet55ReasoningOverrides(t *testing.T) {
60 m, err := FindModel("anthropic", "claude-sonnet-5-5")
61 if err != nil {
62 t.Fatal(err)
63 }
64 m.ReasoningLevelMap = map[string]string{"max": "xhigh"}
65 want := []string{"low", "medium", "high", "xhigh"}
66 if got := AvailableReasoningLevels(m); !slices.Equal(got, want) {
67 t.Fatalf("levels = %q, want %q", got, want)
68 }
69 if got := ClampReasoningForModel(m, "off"); got != "low" {
70 t.Fatalf("off clamped to %q, want low", got)
71 }
72}