feat(config): add support for disabling OpenAI compatibility providers

- Introduced a `Disabled` flag to OpenAI compatibility configurations.
- Updated routing, auth selection, and API handling logic to respect the `Disabled` state.
- Extended relevant APIs, YAML configurations, and data structures to include the `Disabled` field.
- Adjusted all relevant loops and filters to skip disabled providers.

Closes: #3060 #3059 #2977
This commit is contained in:
Luis Pater
2026-04-26 21:49:36 +08:00
parent 0a7c6b0a4a
commit 38573050aa
13 changed files with 40 additions and 0 deletions

View File

@@ -766,6 +766,9 @@ func resolveOpenAICompatAPIKeyProxyURL(cfg *config.Config, auth *coreauth.Auth,
for i := range cfg.OpenAICompatibility {
compat := &cfg.OpenAICompatibility[i]
if compat.Disabled {
continue
}
for _, candidate := range candidates {
if candidate != "" && strings.EqualFold(strings.TrimSpace(candidate), compat.Name) {
for j := range compat.APIKeyEntries {

View File

@@ -36,6 +36,7 @@ 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"`
@@ -215,6 +216,7 @@ func (h *Handler) openAICompatibilityWithAuthIndex() []openAICompatibilityWithAu
response := openAICompatibilityWithAuthIndex{
Name: entry.Name,
Priority: entry.Priority,
Disabled: entry.Disabled,
Prefix: entry.Prefix,
BaseURL: entry.BaseURL,
Models: entry.Models,

View File

@@ -464,6 +464,7 @@ 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"`
@@ -506,6 +507,9 @@ func (h *Handler) PatchOpenAICompat(c *gin.Context) {
if body.Value.Prefix != nil {
entry.Prefix = strings.TrimSpace(*body.Value.Prefix)
}
if body.Value.Disabled != nil {
entry.Disabled = *body.Value.Disabled
}
if body.Value.BaseURL != nil {
trimmed := strings.TrimSpace(*body.Value.BaseURL)
if trimmed == "" {

View File

@@ -1100,6 +1100,9 @@ func (s *Server) UpdateClients(cfg *config.Config) {
openAICompatCount := 0
for i := range cfg.OpenAICompatibility {
entry := cfg.OpenAICompatibility[i]
if entry.Disabled {
continue
}
openAICompatCount += len(entry.APIKeyEntries)
}

View File

@@ -519,6 +519,9 @@ type OpenAICompatibility struct {
// Higher values are preferred; defaults to 0.
Priority int `yaml:"priority,omitempty" json:"priority,omitempty"`
// Disabled prevents this provider from being used for routing.
Disabled bool `yaml:"disabled,omitempty" json:"disabled,omitempty"`
// Prefix optionally namespaces model aliases for this provider (e.g., "teamA/kimi-k2").
Prefix string `yaml:"prefix,omitempty" json:"prefix,omitempty"`

View File

@@ -378,6 +378,9 @@ func (e *OpenAICompatExecutor) resolveCompatConfig(auth *cliproxyauth.Auth) *con
}
for i := range e.cfg.OpenAICompatibility {
compat := &e.cfg.OpenAICompatibility[i]
if compat.Disabled {
continue
}
for _, candidate := range candidates {
if candidate != "" && strings.EqualFold(strings.TrimSpace(candidate), compat.Name) {
return compat

View File

@@ -98,6 +98,9 @@ func IsOpenAICompatibilityAlias(modelName string, cfg *config.Config) bool {
}
for _, compat := range cfg.OpenAICompatibility {
if compat.Disabled {
continue
}
for _, model := range compat.Models {
if model.Alias == modelName {
return true
@@ -123,6 +126,9 @@ func GetOpenAICompatibilityConfig(alias string, cfg *config.Config) (*config.Ope
}
for _, compat := range cfg.OpenAICompatibility {
if compat.Disabled {
continue
}
for _, model := range compat.Models {
if model.Alias == alias {
return &compat, &model

View File

@@ -357,6 +357,9 @@ func BuildAPIKeyClients(cfg *config.Config) (int, int, int, int, int) {
}
if len(cfg.OpenAICompatibility) > 0 {
for _, compatConfig := range cfg.OpenAICompatibility {
if compatConfig.Disabled {
continue
}
openAICompatCount += len(compatConfig.APIKeyEntries)
}
}

View File

@@ -66,6 +66,9 @@ func describeOpenAICompatibilityUpdate(oldEntry, newEntry config.OpenAICompatibi
oldModelCount := countOpenAIModels(oldEntry.Models)
newModelCount := countOpenAIModels(newEntry.Models)
details := make([]string, 0, 3)
if oldEntry.Disabled != newEntry.Disabled {
details = append(details, fmt.Sprintf("disabled %t -> %t", oldEntry.Disabled, newEntry.Disabled))
}
if oldKeyCount != newKeyCount {
details = append(details, fmt.Sprintf("api-keys %d -> %d", oldKeyCount, newKeyCount))
}

View File

@@ -194,6 +194,9 @@ func (s *ConfigSynthesizer) synthesizeOpenAICompat(ctx *SynthesisContext) []*cor
out := make([]*coreauth.Auth, 0)
for i := range cfg.OpenAICompatibility {
compat := &cfg.OpenAICompatibility[i]
if compat.Disabled {
continue
}
prefix := strings.TrimSpace(compat.Prefix)
providerName := strings.ToLower(strings.TrimSpace(compat.Name))
if providerName == "" {