From 21d8164c568a2244ec9bbd630a3f0704a238928c Mon Sep 17 00:00:00 2001 From: Luis Pater Date: Sun, 28 Jun 2026 17:54:49 +0800 Subject: [PATCH] feat(handlers): add `disable-cooling` support in OpenAI compatibility configuration - Introduced `disable-cooling` field in OpenAI compatibility configurations. - Updated `PatchOpenAICompat` to handle `disable-cooling` updates. - Refined response structure in compatibility handlers to include `disable-cooling`. - Added unit test to validate `disable-cooling` propagation in API responses. Closes: #4023 --- .../handlers/management/config_auth_index.go | 36 ++++++------ .../api/handlers/management/config_lists.go | 18 +++--- .../management/config_openai_compat_test.go | 55 +++++++++++++++++++ 3 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 internal/api/handlers/management/config_openai_compat_test.go diff --git a/internal/api/handlers/management/config_auth_index.go b/internal/api/handlers/management/config_auth_index.go index f2bbc2ff..e7c7a2b4 100644 --- a/internal/api/handlers/management/config_auth_index.go +++ b/internal/api/handlers/management/config_auth_index.go @@ -34,15 +34,16 @@ type openAICompatibilityAPIKeyWithAuthIndex struct { } type openAICompatibilityWithAuthIndex struct { - Name string `json:"name"` - Priority int `json:"priority,omitempty"` - Disabled bool `json:"disabled"` - Prefix string `json:"prefix,omitempty"` - BaseURL string `json:"base-url"` - APIKeyEntries []openAICompatibilityAPIKeyWithAuthIndex `json:"api-key-entries,omitempty"` - Models []config.OpenAICompatibilityModel `json:"models,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - AuthIndex string `json:"auth-index,omitempty"` + Name string `json:"name"` + Priority int `json:"priority,omitempty"` + Disabled bool `json:"disabled"` + Prefix string `json:"prefix,omitempty"` + BaseURL string `json:"base-url"` + APIKeyEntries []openAICompatibilityAPIKeyWithAuthIndex `json:"api-key-entries,omitempty"` + Models []config.OpenAICompatibilityModel `json:"models,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + DisableCooling bool `json:"disable-cooling,omitempty"` + AuthIndex string `json:"auth-index,omitempty"` } func (h *Handler) liveAuthIndexByID() map[string]string { @@ -214,14 +215,15 @@ func (h *Handler) openAICompatibilityWithAuthIndex() []openAICompatibilityWithAu idKind := fmt.Sprintf("openai-compatibility:%s", providerName) response := openAICompatibilityWithAuthIndex{ - Name: entry.Name, - Priority: entry.Priority, - Disabled: entry.Disabled, - Prefix: entry.Prefix, - BaseURL: entry.BaseURL, - Models: entry.Models, - Headers: entry.Headers, - AuthIndex: "", + Name: entry.Name, + Priority: entry.Priority, + Disabled: entry.Disabled, + Prefix: entry.Prefix, + BaseURL: entry.BaseURL, + Models: entry.Models, + Headers: entry.Headers, + DisableCooling: entry.DisableCooling, + AuthIndex: "", } if len(entry.APIKeyEntries) == 0 { id, _ := idGen.Next(idKind, entry.BaseURL) diff --git a/internal/api/handlers/management/config_lists.go b/internal/api/handlers/management/config_lists.go index fb4c67d2..5456e7ce 100644 --- a/internal/api/handlers/management/config_lists.go +++ b/internal/api/handlers/management/config_lists.go @@ -466,13 +466,14 @@ func (h *Handler) PutOpenAICompat(c *gin.Context) { } func (h *Handler) PatchOpenAICompat(c *gin.Context) { type openAICompatPatch struct { - Name *string `json:"name"` - Prefix *string `json:"prefix"` - Disabled *bool `json:"disabled"` - BaseURL *string `json:"base-url"` - APIKeyEntries *[]config.OpenAICompatibilityAPIKey `json:"api-key-entries"` - Models *[]config.OpenAICompatibilityModel `json:"models"` - Headers *map[string]string `json:"headers"` + Name *string `json:"name"` + Prefix *string `json:"prefix"` + Disabled *bool `json:"disabled"` + DisableCooling *bool `json:"disable-cooling"` + BaseURL *string `json:"base-url"` + APIKeyEntries *[]config.OpenAICompatibilityAPIKey `json:"api-key-entries"` + Models *[]config.OpenAICompatibilityModel `json:"models"` + Headers *map[string]string `json:"headers"` } var body struct { Name *string `json:"name"` @@ -514,6 +515,9 @@ func (h *Handler) PatchOpenAICompat(c *gin.Context) { if body.Value.Disabled != nil { entry.Disabled = *body.Value.Disabled } + if body.Value.DisableCooling != nil { + entry.DisableCooling = *body.Value.DisableCooling + } if body.Value.BaseURL != nil { trimmed := strings.TrimSpace(*body.Value.BaseURL) if trimmed == "" { diff --git a/internal/api/handlers/management/config_openai_compat_test.go b/internal/api/handlers/management/config_openai_compat_test.go new file mode 100644 index 00000000..88f3c90d --- /dev/null +++ b/internal/api/handlers/management/config_openai_compat_test.go @@ -0,0 +1,55 @@ +package management + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "github.com/router-for-me/CLIProxyAPI/v7/internal/config" +) + +func TestGetOpenAICompatIncludesDisableCooling(t *testing.T) { + t.Setenv("MANAGEMENT_PASSWORD", "") + + h := NewHandlerWithoutConfigFilePath(&config.Config{ + OpenAICompatibility: []config.OpenAICompatibility{ + { + Name: "Mimo CN", + BaseURL: "https://token-plan-cn.xiaomimimo.com/v1", + APIKeyEntries: []config.OpenAICompatibilityAPIKey{ + {APIKey: "test-key"}, + }, + Models: []config.OpenAICompatibilityModel{ + {Name: "mimo-v2.5", Alias: ""}, + }, + DisableCooling: true, + }, + }, + }, nil) + + rec := httptest.NewRecorder() + ctx, _ := gin.CreateTestContext(rec) + ctx.Request = httptest.NewRequest(http.MethodGet, "/v0/management/openai-compatibility", nil) + h.GetOpenAICompat(ctx) + + if rec.Code != http.StatusOK { + t.Fatalf("expected status %d, got %d with body %s", http.StatusOK, rec.Code, rec.Body.String()) + } + + var body struct { + OpenAICompatibility []struct { + DisableCooling *bool `json:"disable-cooling"` + } `json:"openai-compatibility"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatalf("failed to decode response: %v", err) + } + if len(body.OpenAICompatibility) != 1 { + t.Fatalf("expected 1 openai-compatibility entry, got %d", len(body.OpenAICompatibility)) + } + if body.OpenAICompatibility[0].DisableCooling == nil || !*body.OpenAICompatibility[0].DisableCooling { + t.Fatalf("expected disable-cooling to be present and true, got %#v", body.OpenAICompatibility[0].DisableCooling) + } +} -- 2.51.2