internal/registry/model_definitions_test.go
Rama main · réplica de lectura del repositorio original.
package registry
import (
"encoding/json"
"reflect"
"strings"
"testing"
)
func TestCodexConfigurationUpdateCapability(t *testing.T) {
// Counterexample: present in every tier without support_configuration_update.
const incapableModelID = "gpt-5.6-luna"
for _, tier := range []struct {
name string
models func() []*ModelInfo
capable []string
}{
{name: "free", models: GetCodexFreeModels, capable: []string{"gpt-6-luna"}},
{name: "team", models: GetCodexTeamModels, capable: []string{"gpt-6-astra", "gpt-6-sol", "gpt-6-luna"}},
{name: "plus", models: GetCodexPlusModels, capable: []string{"gpt-6-astra", "gpt-6-sol", "gpt-6-luna"}},
{name: "pro", models: GetCodexProModels, capable: []string{"gpt-6-astra", "gpt-6-sol", "gpt-6-luna"}},
} {
t.Run(tier.name, func(t *testing.T) {
byID := make(map[string]*ModelInfo)
for _, info := range tier.models() {
if info != nil {
byID[info.ID] = info
}
}
for _, id := range append([]string{incapableModelID}, tier.capable...) {
info := byID[id]
if info == nil {
t.Errorf("%s is missing", id)
continue
}
want := id != incapableModelID
if info.SupportConfigurationUpdate != want {
t.Errorf("%s configuration_update = %v, want %v", id, info.SupportConfigurationUpdate, want)
}
if cloned := cloneModelInfo(info); cloned.SupportConfigurationUpdate != want {
t.Errorf("%s clone configuration_update = %v, want %v", id, cloned.SupportConfigurationUpdate, want)
}
raw, errMarshal := json.Marshal(info)
if errMarshal != nil {
t.Fatal(errMarshal)
}
if strings.Contains(string(raw), "support_configuration_update") || strings.Contains(string(raw), "SupportConfigurationUpdate") {
t.Errorf("%s exposed configuration_update capability: %s", id, raw)
}
}
})
}
for _, tt := range []struct {
name string
raw string
want bool
}{
{name: "true", raw: `{"id":"test","support_configuration_update":true}`, want: true},
{name: "false", raw: `{"id":"test","support_configuration_update":false}`},
{name: "absent", raw: `{"id":"test"}`},
} {
t.Run(tt.name, func(t *testing.T) {
info := ModelInfo{SupportConfigurationUpdate: true}
if errUnmarshal := json.Unmarshal([]byte(tt.raw), &info); errUnmarshal != nil {
t.Fatal(errUnmarshal)
}
if info.SupportConfigurationUpdate != tt.want {
t.Errorf("capability = %v, want %v", info.SupportConfigurationUpdate, tt.want)
}
})
}
}
func TestGetStaticModelDefinitionsByChannelSupportsGeminiInteractions(t *testing.T) {
models := GetStaticModelDefinitionsByChannel("gemini-interactions")
if len(models) == 0 {
t.Fatal("GetStaticModelDefinitionsByChannel(gemini-interactions) returned no models")
}
}
func TestGetStaticModelDefinitionsByChannelSupportsKimiAndKimiAI(t *testing.T) {
for _, channel := range []string{"kimi", "kimi-ai", "kimi.ai", "kimi.com"} {
models := GetStaticModelDefinitionsByChannel(channel)
if len(models) == 0 {
t.Fatalf("GetStaticModelDefinitionsByChannel(%s) returned no models", channel)
}
}
}
func TestModelOverrideHeadersFromEmbeddedModels(t *testing.T) {
const wantUA = "codex-tui/0.154.0 (Mac OS 26.5.2; arm64) iTerm.app/3.6.11 (codex-tui; 0.154.0)"
got := ModelOverrideHeaders("gpt-5.6-luna")
if got == nil {
t.Fatal("ModelOverrideHeaders(gpt-5.6-luna) = nil, want headers")
}
if got["user-agent"] != wantUA {
t.Fatalf("user-agent = %q, want %q", got["user-agent"], wantUA)
}
if got := ModelOverrideHeaders("gpt-5.4"); got != nil {
t.Fatalf("ModelOverrideHeaders(gpt-5.4) = %#v, want nil", got)
}
}
func TestGeminiVertexModelsUseFlashLiteReleaseID(t *testing.T) {
const releaseID = "gemini-3.1-flash-lite"
const previewID = releaseID + "-preview"
for _, model := range GetGeminiVertexModels() {
if model == nil {
continue
}
if model.ID == previewID {
t.Fatalf("Vertex model ID = %q, want release ID %q", model.ID, releaseID)
}
if model.ID == releaseID {
return
}
}
t.Fatalf("Vertex models do not contain %q", releaseID)
}
func TestWithXAIBuiltinsIncludesImage20(t *testing.T) {
models := WithXAIBuiltins(nil)
for _, model := range models {
if model != nil && model.ID == xaiBuiltinImage20ModelID {
if model.Created != 1786060800 {
t.Fatalf("created = %d, want 1786060800 (2026-08-07)", model.Created)
}
return
}
}
t.Fatalf("expected xAI builtin model %s", xaiBuiltinImage20ModelID)
}
func TestWithXAIBuiltinsIncludesSpeechModels(t *testing.T) {
models := WithXAIBuiltins(nil)
found := map[string]*ModelInfo{}
for _, model := range models {
if model == nil {
continue
}
if model.ID == xaiBuiltinSpeechModelID || model.ID == xaiBuiltinSpeechVoiceModelID {
found[model.ID] = model
}
}
for _, id := range []string{xaiBuiltinSpeechModelID, xaiBuiltinSpeechVoiceModelID} {
model := found[id]
if model == nil {
t.Fatalf("expected xAI builtin model %s", id)
}
if model.OwnedBy != "xai" || model.Type != "xai" {
t.Fatalf("%s owned_by/type = %s/%s, want xai/xai", id, model.OwnedBy, model.Type)
}
}
}
func TestWithXAIBuiltinsIncludesVideo15GAAndPreviewAlias(t *testing.T) {
models := WithXAIBuiltins(nil)
foundGA := false
foundPreviewAlias := false
for _, model := range models {
if model == nil {
continue
}
if model.ID == xaiBuiltinVideo15ModelID {
foundGA = true
}
if model.ID == xaiBuiltinVideo15PreviewID {
foundPreviewAlias = true
}
}
if !foundGA {
t.Fatalf("expected xAI builtin model %s", xaiBuiltinVideo15ModelID)
}
if !foundPreviewAlias {
t.Fatalf("expected xAI builtin compatibility alias %s", xaiBuiltinVideo15PreviewID)
}
}
func TestGetXAIModelsPreservesVideo15LiteAfterCatalogRefresh(t *testing.T) {
const liteID = "grok-imagine-video-1.5-lite"
original := getModels()
t.Cleanup(func() {
modelsCatalogStore.mu.Lock()
modelsCatalogStore.data = original
modelsCatalogStore.mu.Unlock()
})
refreshed := *original
remoteModel := &ModelInfo{ID: "refreshed-xai-model", OwnedBy: "xai", Type: "xai", DisplayName: "Refreshed model"}
refreshed.XAI = []*ModelInfo{remoteModel}
payload, err := json.Marshal(&refreshed)
if err != nil {
t.Fatal(err)
}
if _, err := publishCatalogBytes(payload); err != nil {
t.Fatalf("publish catalog without Lite: %v", err)
}
models := GetXAIModels()
foundLite, foundRemote := false, false
for _, model := range models {
if model.ID == liteID {
foundLite = true
if model.OwnedBy != "xai" || model.Type != "xai" ||
!reflect.DeepEqual(model.SupportedInputModalities, []string{"text", "image"}) ||
!reflect.DeepEqual(model.SupportedOutputModalities, []string{"video"}) {
t.Fatalf("Lite lost xAI video capabilities after catalog refresh: %#v", model)
}
}
if model.ID == remoteModel.ID {
foundRemote = true
if !reflect.DeepEqual(model, remoteModel) {
t.Fatalf("refreshed model = %#v, want %#v", model, remoteModel)
}
}
}
if !foundLite || !foundRemote {
t.Fatalf("catalog lost Lite or refreshed model: Lite=%v, refreshed=%v", foundLite, foundRemote)
}
const clientID = "test-xai-lite-catalog-refresh"
registryRef := GetGlobalRegistry()
registryRef.RegisterClient(clientID, "xai", models)
t.Cleanup(func() { registryRef.UnregisterClient(clientID) })
if !registryRef.ClientSupportsModel(clientID, liteID) {
t.Fatal("xAI credential registration lost Lite support after catalog refresh")
}
if providers := registryRef.GetModelProviders(liteID); !reflect.DeepEqual(providers, []string{"xai"}) {
t.Fatalf("Lite providers = %v, want [xai]", providers)
}
}
func TestWithXAIBuiltinsReplacesVideo15LiteWithoutMutatingCatalog(t *testing.T) {
const liteID = "grok-imagine-video-1.5-lite"
stale := &ModelInfo{ID: liteID, DisplayName: "Stale Lite", SupportedInputModalities: []string{"text"}}
duplicate := &ModelInfo{ID: " GROK-IMAGINE-VIDEO-1.5-LITE ", DisplayName: "Duplicate Lite"}
custom := &ModelInfo{ID: "custom-xai-model", DisplayName: "Custom model"}
input := []*ModelInfo{stale, custom, duplicate}
for range 2 {
models := WithXAIBuiltins(input)
liteCount := 0
foundCustom := false
for _, model := range models {
if strings.EqualFold(strings.TrimSpace(model.ID), liteID) {
liteCount++
if model.ID != liteID || model.DisplayName != "Grok Imagine Video 1.5 Lite" ||
!reflect.DeepEqual(model.SupportedInputModalities, []string{"text", "image"}) {
t.Fatalf("Lite builtin did not replace stale metadata: %#v", model)
}
model.SupportedInputModalities[0] = "mutated"
}
if model.ID == custom.ID {
foundCustom = reflect.DeepEqual(model, custom)
}
}
if liteCount != 1 || !foundCustom {
t.Fatalf("Lite count = %d, custom preserved = %v, want 1 and true", liteCount, foundCustom)
}
}
if input[0] != stale || input[1] != custom || input[2] != duplicate ||
stale.DisplayName != "Stale Lite" || !reflect.DeepEqual(stale.SupportedInputModalities, []string{"text"}) ||
duplicate.ID != " GROK-IMAGINE-VIDEO-1.5-LITE " || duplicate.DisplayName != "Duplicate Lite" {
t.Fatal("builtin merge mutated the input catalog")
}
}
func TestAntigravityWebSearchModelForRequiresRequestedModelCapability(t *testing.T) {
registryRef := GetGlobalRegistry()
registryRef.RegisterClient("test-antigravity-websearch-route", "antigravity", []*ModelInfo{
{ID: "gemini-route-test"},
{ID: "gemini-web-search-test", SupportsWebSearch: true},
})
registryRef.RegisterClient("test-gemini-websearch-route", "gemini", []*ModelInfo{
{ID: "gemini-cross-provider-route"},
{ID: "gemini-cross-provider-search", SupportsWebSearch: true},
})
t.Cleanup(func() {
registryRef.UnregisterClient("test-antigravity-websearch-route")
registryRef.UnregisterClient("test-gemini-websearch-route")
})
if got := AntigravityWebSearchModelFor("gemini-route-test"); got != "" {
t.Fatalf("route model without web search support should not get fallback model, got %q", got)
}
if got := AntigravityWebSearchModelFor("gemini-route-test(high)"); got != "" {
t.Fatalf("suffix route model without web search support should not get fallback model, got %q", got)
}
if got := AntigravityWebSearchModelFor("gemini-web-search-test"); got != "gemini-web-search-test" {
t.Fatalf("AntigravityWebSearchModelFor capable model = %q, want itself", got)
}
if got := AntigravityWebSearchModelFor("gemini-cross-provider-route"); got != "" {
t.Fatalf("cross-provider model should not get Antigravity web search model, got %q", got)
}
if got := AntigravityWebSearchModelFor("unknown-model"); got != "" {
t.Fatalf("unknown model should not get Antigravity web search model, got %q", got)
}
}
func TestValidateModelsCatalog_Meta(t *testing.T) {
valid := &staticModelsJSON{
Meta: []*ModelInfo{
{ID: "muse-spark-1.3"},
},
}
if err := validateModelsCatalog(valid); err != nil {
t.Fatalf("expected valid Meta catalog to pass, got: %v", err)
}
withNull := &staticModelsJSON{
Meta: []*ModelInfo{nil},
}
if err := validateModelsCatalog(withNull); err == nil {
t.Fatal("expected error for Meta section with null model, got nil")
}
withEmptyID := &staticModelsJSON{
Meta: []*ModelInfo{{ID: " "}},
}
if err := validateModelsCatalog(withEmptyID); err == nil {
t.Fatal("expected error for Meta section with empty model id, got nil")
}
withDuplicate := &staticModelsJSON{
Meta: []*ModelInfo{
{ID: "muse-spark-1.3"},
{ID: "muse-spark-1.3"},
},
}
if err := validateModelsCatalog(withDuplicate); err == nil {
t.Fatal("expected error for Meta section with duplicate model id, got nil")
}
}
func TestWithCodexBuiltinsIncludesImage25And26Models(t *testing.T) {
models := WithCodexBuiltins(nil)
expectedModels := map[string]string{
"gpt-image-2.5-flare": "GPT Image 2.5 Flare",
"gpt-image-2.5-sunburst": "GPT Image 2.5 Sunburst",
"gpt-image-2.5": "GPT Image 2.5",
"gpt-image-2.6-flare": "GPT Image 2.6 Flare",
"gpt-image-2.6-sunburst": "GPT Image 2.6 Sunburst",
"gpt-image-2.6": "GPT Image 2.6",
}
found := make(map[string]*ModelInfo)
for _, model := range models {
if model != nil {
if _, ok := expectedModels[model.ID]; ok {
found[model.ID] = model
}
}
}
for id, wantDisplayName := range expectedModels {
model, ok := found[id]
if !ok {
t.Fatalf("expected builtin model %s in WithCodexBuiltins", id)
}
if model.DisplayName != wantDisplayName {
t.Errorf("model %s DisplayName = %q, want %q", id, model.DisplayName, wantDisplayName)
}
if model.Object != "model" {
t.Errorf("model %s Object = %q, want model", id, model.Object)
}
if model.OwnedBy != "openai" {
t.Errorf("model %s OwnedBy = %q, want openai", id, model.OwnedBy)
}
if model.Type != "openai" {
t.Errorf("model %s Type = %q, want openai", id, model.Type)
}
if model.Version != id {
t.Errorf("model %s Version = %q, want %q", id, model.Version, id)
}
if model.Created != 1704067200 {
t.Errorf("model %s Created = %d, want 1704067200", id, model.Created)
}
}
}
func TestGetDevinModelsFallback(t *testing.T) {
devinModels := GetDevinModels()
if len(devinModels) == 0 {
t.Fatal("GetDevinModels() returned empty list")
}
foundSWE2 := false
foundFable := false
foundGemini38 := false
foundGrok46 := false
foundDeepSeekV4Flash := false
foundDeepSeekV41Flash := false
for _, m := range devinModels {
if m != nil && m.ID == "devin/swe-2" {
foundSWE2 = true
if m.Type != "devin" {
t.Errorf("devin/swe-2 Type = %q, want devin", m.Type)
}
}
if m != nil && m.ID == "devin/claude-fable-5-1" {
foundFable = true
}
if m != nil && m.ID == "devin/gemini-3-8-flash" {
foundGemini38 = true
if m.OwnedBy != "google" {
t.Errorf("devin/gemini-3-8-flash OwnedBy = %q, want google", m.OwnedBy)
}
}
if m != nil && m.ID == "devin/grok-4-6" {
foundGrok46 = true
if m.OwnedBy != "xai" {
t.Errorf("devin/grok-4-6 OwnedBy = %q, want xai", m.OwnedBy)
}
}
if m != nil && m.ID == "devin/deepseek-v4-flash" {
foundDeepSeekV4Flash = true
if m.OwnedBy != "deepseek" {
t.Errorf("devin/deepseek-v4-flash OwnedBy = %q, want deepseek", m.OwnedBy)
}
}
if m != nil && m.ID == "devin/deepseek-v4-1-flash-1017" {
foundDeepSeekV41Flash = true
if m.OwnedBy != "deepseek" {
t.Errorf("devin/deepseek-v4-1-flash-1017 OwnedBy = %q, want deepseek", m.OwnedBy)
}
}
}
if !foundSWE2 {
t.Error("expected devin/swe-2 in GetDevinModels()")
}
if !foundFable {
t.Error("expected devin/claude-fable-5-1 in GetDevinModels()")
}
if !foundGemini38 {
t.Error("expected devin/gemini-3-8-flash in GetDevinModels()")
}
if !foundGrok46 {
t.Error("expected devin/grok-4-6 in GetDevinModels()")
}
if !foundDeepSeekV4Flash {
t.Error("expected devin/deepseek-v4-flash in GetDevinModels()")
}
if !foundDeepSeekV41Flash {
t.Error("expected devin/deepseek-v4-1-flash-1017 in GetDevinModels()")
}
byChannel := GetStaticModelDefinitionsByChannel("devin")
if len(byChannel) == 0 {
t.Fatal("GetStaticModelDefinitionsByChannel(\"devin\") returned empty list")
}
info := LookupStaticModelInfo("devin/swe-2")
if info == nil {
t.Fatal("LookupStaticModelInfo(\"devin/swe-2\") = nil, want valid model")
}
if info.DisplayName != "SWE-2" {
t.Errorf("info.DisplayName = %q, want SWE-2", info.DisplayName)
}
}