v0.4.10 5ac0009

discover_yolo_auto_test.go RawHistoryFolder

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}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close