1package provider
2
3import (
4 "context"
5 "fmt"
6 "net/http"
7 "net/http/httptest"
8 "slices"
9 "testing"
10)
11
12func TestDiscoverYoloAutoListsKeyModels(t *testing.T) {
13 const body = `{"object":"list","data":[
14 {"id":"yolo","object":"model","context_length":262144,"max_model_len":262144,
15 "thinking":["minimal","low","medium","high","xhigh"]},
16 {"id":"yolo-small","object":"model","context_length":262144,"max_model_len":262144,
17 "thinking":null},
18 {"id":"text-embedding-3-small","object":"model"}
19 ]}`
20 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
21 if r.URL.Path != "/models" {
22 t.Fatalf("request path = %q", r.URL.Path)
23 }
24 if got := r.Header.Get("authorization"); got != "Bearer yolo_test" {
25 t.Fatalf("authorization = %q", got)
26 }
27 w.Header().Set("content-type", "application/json")
28 fmt.Fprint(w, body)
29 }))
30 defer srv.Close()
31
32 models, err := DiscoverYoloAuto(context.Background(), "yolo_test", srv.URL+"/")
33 if err != nil {
34 t.Fatal(err)
35 }
36 if len(models) != 2 {
37 t.Fatalf("models = %+v", models)
38 }
39
40 yolo := models[0]
41 if yolo.Provider != "yolo-auto" || yolo.ID != "yolo" || yolo.DisplayName != "yolo" ||
42 yolo.ContextWindow != 262144 || yolo.MaxOutput != yoloAutoMaxOutput || !yolo.Reasoning ||
43 yolo.BaseURL != srv.URL || yolo.Source != "live" {
44 t.Fatalf("yolo model = %+v", yolo)
45 }
46
47 small := models[1]
48 if small.ID != "yolo-small" || small.ContextWindow != 262144 || small.Reasoning {
49 t.Fatalf("second model = %+v", small)
50 }
51}
52
53func TestDiscoverYoloAutoFallsBackToDocumentedLimits(t *testing.T) {
54 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
55 w.Header().Set("content-type", "application/json")
56 fmt.Fprint(w, `{"data":[{"id":"yolo"}]}`)
57 }))
58 defer srv.Close()
59
60 models, err := DiscoverYoloAuto(context.Background(), "yolo_test", srv.URL)
61 if err != nil {
62 t.Fatal(err)
63 }
64 if len(models) != 1 || models[0].ContextWindow != yoloAutoContextWindow {
65 t.Fatalf("models = %+v", models)
66 }
67}
68
69func TestYoloAutoDiscoveryReachesActiveCatalogAndWire(t *testing.T) {
70 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
71 fmt.Fprint(w, `{"data":[
72 {"id":"yolo","context_length":262144,"thinking":["minimal","low","medium","high","xhigh"]},
73 {"id":"qwen3.8-flash","context_length":65536,"thinking":["high"]},
74 {"id":"yolo-small","max_model_len":65536,"thinking":null}
75 ]}`)
76 }))
77 defer srv.Close()
78 models, err := DiscoverYoloAuto(context.Background(), "test", srv.URL)
79 if err != nil {
80 t.Fatal(err)
81 }
82 SetLiveModels(models)
83 t.Cleanup(func() { SetLiveModels(nil) })
84 for _, discovered := range models {
85 active, err := FindModel("yolo-auto", discovered.ID)
86 if err != nil {
87 t.Fatal(err)
88 }
89 if active.ContextWindow != discovered.ContextWindow || active.Reasoning != discovered.Reasoning || active.BaseURL != srv.URL {
90 t.Errorf("active metadata does not match discovery: %+v", active)
91 }
92 if active.ID == "yolo" && !slices.Equal(AvailableReasoningLevels(active), []string{"", "minimum", "low", "medium", "high", "xhigh"}) {
93 t.Errorf("available levels = %q", AvailableReasoningLevels(active))
94 }
95 }
96 client := NewYoloAuto("test", srv.URL).(*openaiClient)
97 for _, tc := range []struct{ model, level, want string }{
98 {"yolo", "minimum", "minimal"},
99 {"yolo", "xhigh", "xhigh"},
100 {"yolo", "max", "xhigh"},
101 {"yolo", "off", ""},
102 {"qwen3.8-flash", "low", "high"},
103 {"yolo-small", "high", ""},
104 } {
105 wire, err := client.buildRequest(Request{Model: tc.model, Reasoning: tc.level})
106 if err != nil {
107 t.Fatal(err)
108 }
109 if wire.ReasoningEffort != tc.want {
110 t.Errorf("%s/%s effort = %q, want %q", tc.model, tc.level, wire.ReasoningEffort, tc.want)
111 }
112 }
113}
114
115func TestDiscoverYoloAutoReportsHTTPError(t *testing.T) {
116 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
117 http.Error(w, "unauthorized", http.StatusUnauthorized)
118 }))
119 defer srv.Close()
120
121 _, err := DiscoverYoloAuto(context.Background(), "yolo_test", srv.URL)
122 if err == nil {
123 t.Fatal("expected discovery error")
124 }
125}