@@ -0,0 +1,90 @@
1+package discover
2+
3+import (
4+ "context"
5+ "encoding/json"
6+ "net/http"
7+ "net/http/httptest"
8+ "testing"
9+
10+ "charm.land/catwalk/pkg/catwalk"
11+ "github.com/stretchr/testify/require"
12+)
13+
14+func TestOmlxEnricher(t *testing.T) {
15+ t.Parallel()
16+
17+ t.Run("populates context window and max tokens from /v1/models/status", func(t *testing.T) {
18+ t.Parallel()
19+ srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
20+ require.Equal(t, "/v1/models/status", r.URL.Path)
21+ w.Header().Set("Content-Type", "application/json")
22+ json.NewEncoder(w).Encode(omlxModelsStatusResponse{
23+ Models: []omlxModelStatus{
24+ {ID: "qwen3:latest", MaxContextWindow: ptr(int64(32768)), MaxTokens: ptr(int64(16384))},
25+ {ID: "llama3:latest", MaxContextWindow: ptr(int64(8192)), MaxTokens: ptr(int64(4096))},
26+ },
27+ })
28+ }))
29+ defer srv.Close()
30+
31+ cfg := Config{ID: "test-omlx", BaseURL: srv.URL}
32+ models := []catwalk.Model{
33+ {ID: "qwen3:latest", Name: "qwen3:latest"},
34+ {ID: "llama3:latest", Name: "llama3:latest"},
35+ {ID: "unknown:latest", Name: "unknown:latest"},
36+ }
37+
38+ e := &omlxEnricher{}
39+ result, err := e.EnrichModels(context.Background(), cfg, &mockResolver{}, models)
40+ require.NoError(t, err)
41+ require.Len(t, result, 3)
42+ require.Equal(t, int64(32768), result[0].ContextWindow)
43+ require.Equal(t, int64(16384), result[0].DefaultMaxTokens)
44+ require.Equal(t, int64(8192), result[1].ContextWindow)
45+ require.Equal(t, int64(4096), result[1].DefaultMaxTokens)
46+ require.Equal(t, int64(0), result[2].ContextWindow)
47+ })
48+
49+ t.Run("preserves existing non-zero values", func(t *testing.T) {
50+ t.Parallel()
51+ srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
52+ w.Header().Set("Content-Type", "application/json")
53+ json.NewEncoder(w).Encode(omlxModelsStatusResponse{
54+ Models: []omlxModelStatus{
55+ {ID: "m1", MaxContextWindow: ptr(int64(32768)), MaxTokens: ptr(int64(16384))},
56+ },
57+ })
58+ }))
59+ defer srv.Close()
60+
61+ cfg := Config{ID: "test-omlx", BaseURL: srv.URL}
62+ models := []catwalk.Model{
63+ {ID: "m1", ContextWindow: 65536, DefaultMaxTokens: 8192},
64+ }
65+
66+ e := &omlxEnricher{}
67+ result, err := e.EnrichModels(context.Background(), cfg, &mockResolver{}, models)
68+ require.NoError(t, err)
69+ require.Equal(t, int64(65536), result[0].ContextWindow)
70+ require.Equal(t, int64(8192), result[0].DefaultMaxTokens)
71+ })
72+
73+ t.Run("returns models unchanged on HTTP error", func(t *testing.T) {
74+ t.Parallel()
75+ srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
76+ w.WriteHeader(http.StatusNotFound)
77+ }))
78+ defer srv.Close()
79+
80+ cfg := Config{ID: "test-omlx", BaseURL: srv.URL}
81+ models := []catwalk.Model{{ID: "m1"}}
82+
83+ e := &omlxEnricher{}
84+ result, err := e.EnrichModels(context.Background(), cfg, &mockResolver{}, models)
85+ require.NoError(t, err)
86+ require.Len(t, result, 1)
87+ })
88+}
89+
90+func ptr[T any](v T) *T { return &v }