From 01101560182bcb7379cf8bbe875a77163b3e33b1 Mon Sep 17 00:00:00 2001 From: vikingowl Date: Sat, 25 Apr 2026 13:09:55 +0200 Subject: [PATCH] fix(ai): drop TunedModelInfo nil check in model filter SDK's modelFromMldev maps _self to tunedModelInfo for every model, making the nil check always true and silently dropping all results. Name-based filtering is the correct gate; tuned models are excluded by the gemini- prefix requirement. --- backend/internal/pkg/ai/gemini.go | 3 -- backend/internal/pkg/ai/gemini_test.go | 73 ++++++++++++-------------- 2 files changed, 34 insertions(+), 42 deletions(-) diff --git a/backend/internal/pkg/ai/gemini.go b/backend/internal/pkg/ai/gemini.go index d0a6f1b..f9c95e2 100644 --- a/backend/internal/pkg/ai/gemini.go +++ b/backend/internal/pkg/ai/gemini.go @@ -60,9 +60,6 @@ func filterCompatibleModels(items []*genai.Model) []ModelInfo { } out := make([]ModelInfo, 0, len(items)) for _, m := range items { - if m.TunedModelInfo != nil { - continue - } name := strings.TrimPrefix(m.Name, "models/") if !strings.HasPrefix(name, "gemini-") { continue diff --git a/backend/internal/pkg/ai/gemini_test.go b/backend/internal/pkg/ai/gemini_test.go index e83861b..067cd2a 100644 --- a/backend/internal/pkg/ai/gemini_test.go +++ b/backend/internal/pkg/ai/gemini_test.go @@ -7,28 +7,24 @@ import ( "google.golang.org/genai" ) -func makeModel(name string, tuned, thinking bool) *genai.Model { - m := &genai.Model{ +func makeModel(name string, thinking bool) *genai.Model { + return &genai.Model{ Name: "models/" + name, DisplayName: name, Thinking: thinking, InputTokenLimit: 32000, } - if tuned { - m.TunedModelInfo = &genai.TunedModelInfo{} - } - return m } func TestFilterCompatibleModels_KeepsGeminiTextFamilies(t *testing.T) { // SupportedActions intentionally nil — stable text models don't have it populated. kept := []*genai.Model{ - makeModel("gemini-2.5-pro", false, true), - makeModel("gemini-2.5-flash", false, false), - makeModel("gemini-2.5-flash-lite", false, false), - makeModel("gemini-3-flash-preview-04-2026", false, false), - makeModel("gemini-3.1-pro-preview-04-2026", false, true), - makeModel("gemini-3.1-flash-lite-preview-04-2026", false, false), + makeModel("gemini-2.5-pro", true), + makeModel("gemini-2.5-flash", false), + makeModel("gemini-2.5-flash-lite", false), + makeModel("gemini-3-flash-preview-04-2026", false), + makeModel("gemini-3.1-pro-preview-04-2026", true), + makeModel("gemini-3.1-flash-lite-preview-04-2026", false), } got := filterCompatibleModels(kept) if len(got) != len(kept) { @@ -44,25 +40,24 @@ func TestFilterCompatibleModels_DropsExcludedFamilies(t *testing.T) { name string model *genai.Model }{ - {"tts", makeModel("gemini-2.5-flash-preview-tts", false, false)}, - {"pro tts", makeModel("gemini-2.5-pro-preview-tts", false, false)}, - {"image", makeModel("gemini-2.5-flash-image", false, false)}, - {"native audio", makeModel("gemini-2.5-flash-native-audio-preview-12-2025", false, false)}, - {"live", makeModel("gemini-2.5-flash-live-preview", false, false)}, - {"computer use", makeModel("gemini-2.5-computer-use-preview-10-2025", false, false)}, - {"robotics", makeModel("gemini-robotics-er-1.6-preview", false, false)}, - {"embedding", makeModel("gemini-embedding-001", false, false)}, - {"gemma", makeModel("gemma-3-27b-it", false, false)}, - {"gemma nano", makeModel("gemma-3n-e4b-it", false, false)}, - {"deep research", makeModel("deep-research-preview-04-2026", false, false)}, - {"deep research max", makeModel("deep-research-max-preview-04-2026", false, false)}, - {"imagen", makeModel("imagen-3.0-generate-001", false, false)}, - {"veo", makeModel("veo-3.1-generate-preview", false, false)}, - {"lyria", makeModel("lyria-realtime-exp", false, false)}, - {"learnlm", makeModel("learnlm-2.0-flash-experimental", false, false)}, - {"gemini 2.0 flash eol", makeModel("gemini-2.0-flash", false, false)}, - {"gemini 2.0 flash lite eol", makeModel("gemini-2.0-flash-lite", false, false)}, - {"tuned model", makeModel("gemini-2.5-flash", true, false)}, + {"tts", makeModel("gemini-2.5-flash-preview-tts", false)}, + {"pro tts", makeModel("gemini-2.5-pro-preview-tts", false)}, + {"image", makeModel("gemini-2.5-flash-image", false)}, + {"native audio", makeModel("gemini-2.5-flash-native-audio-preview-12-2025", false)}, + {"live", makeModel("gemini-2.5-flash-live-preview", false)}, + {"computer use", makeModel("gemini-2.5-computer-use-preview-10-2025", false)}, + {"robotics", makeModel("gemini-robotics-er-1.6-preview", false)}, + {"embedding", makeModel("gemini-embedding-001", false)}, + {"gemma", makeModel("gemma-3-27b-it", false)}, + {"gemma nano", makeModel("gemma-3n-e4b-it", false)}, + {"deep research", makeModel("deep-research-preview-04-2026", false)}, + {"deep research max", makeModel("deep-research-max-preview-04-2026", false)}, + {"imagen", makeModel("imagen-3.0-generate-001", false)}, + {"veo", makeModel("veo-3.1-generate-preview", false)}, + {"lyria", makeModel("lyria-realtime-exp", false)}, + {"learnlm", makeModel("learnlm-2.0-flash-experimental", false)}, + {"gemini 2.0 flash eol", makeModel("gemini-2.0-flash", false)}, + {"gemini 2.0 flash lite eol", makeModel("gemini-2.0-flash-lite", false)}, } for _, tc := range cases { got := filterCompatibleModels([]*genai.Model{tc.model}) @@ -74,8 +69,8 @@ func TestFilterCompatibleModels_DropsExcludedFamilies(t *testing.T) { func TestFilterCompatibleModels_StableField(t *testing.T) { items := []*genai.Model{ - makeModel("gemini-2.5-flash", false, false), - makeModel("gemini-3-flash-preview-04-2026", false, false), + makeModel("gemini-2.5-flash", false), + makeModel("gemini-3-flash-preview-04-2026", false), } got := filterCompatibleModels(items) if len(got) != 2 { @@ -91,8 +86,8 @@ func TestFilterCompatibleModels_StableField(t *testing.T) { func TestFilterCompatibleModels_ThinkingField(t *testing.T) { items := []*genai.Model{ - makeModel("gemini-2.5-pro", false, true), - makeModel("gemini-2.5-flash", false, false), + makeModel("gemini-2.5-pro", true), + makeModel("gemini-2.5-flash", false), } got := filterCompatibleModels(items) if len(got) != 2 { @@ -111,10 +106,10 @@ func TestFilterCompatibleModels_ThinkingField(t *testing.T) { func TestFilterCompatibleModels_SortStableFirst(t *testing.T) { items := []*genai.Model{ - makeModel("gemini-3-flash-preview-04-2026", false, false), - makeModel("gemini-2.5-pro", false, true), - makeModel("gemini-3.1-pro-preview-04-2026", false, true), - makeModel("gemini-2.5-flash-lite", false, false), + makeModel("gemini-3-flash-preview-04-2026", false), + makeModel("gemini-2.5-pro", true), + makeModel("gemini-3.1-pro-preview-04-2026", true), + makeModel("gemini-2.5-flash-lite", false), } got := filterCompatibleModels(items) if len(got) != 4 {