mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-02 20:40:52 +08:00
refactor(config): remove deprecated legacy API key fields
This commit is contained in:
@@ -17,7 +17,6 @@ func (h *Handler) GetConfig(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
cfgCopy := *h.cfg
|
cfgCopy := *h.cfg
|
||||||
cfgCopy.GlAPIKey = geminiKeyStringsFromConfig(h.cfg)
|
|
||||||
c.JSON(200, &cfgCopy)
|
c.JSON(200, &cfgCopy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,6 @@ func (h *Handler) applyLegacyKeys(keys []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
h.cfg.GeminiKey = newList
|
h.cfg.GeminiKey = newList
|
||||||
h.cfg.GlAPIKey = sanitized
|
|
||||||
h.cfg.SanitizeGeminiKeys()
|
h.cfg.SanitizeGeminiKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,15 +408,14 @@ func (h *Handler) PutOpenAICompat(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
arr = obj.Items
|
arr = obj.Items
|
||||||
}
|
}
|
||||||
arr = migrateLegacyOpenAICompatibilityKeys(arr)
|
|
||||||
// Filter out providers with empty base-url -> remove provider entirely
|
|
||||||
filtered := make([]config.OpenAICompatibility, 0, len(arr))
|
filtered := make([]config.OpenAICompatibility, 0, len(arr))
|
||||||
for i := range arr {
|
for i := range arr {
|
||||||
|
normalizeOpenAICompatibilityEntry(&arr[i])
|
||||||
if strings.TrimSpace(arr[i].BaseURL) != "" {
|
if strings.TrimSpace(arr[i].BaseURL) != "" {
|
||||||
filtered = append(filtered, arr[i])
|
filtered = append(filtered, arr[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h.cfg.OpenAICompatibility = migrateLegacyOpenAICompatibilityKeys(filtered)
|
h.cfg.OpenAICompatibility = filtered
|
||||||
h.cfg.SanitizeOpenAICompatibility()
|
h.cfg.SanitizeOpenAICompatibility()
|
||||||
h.persist(c)
|
h.persist(c)
|
||||||
}
|
}
|
||||||
@@ -431,7 +429,6 @@ func (h *Handler) PatchOpenAICompat(c *gin.Context) {
|
|||||||
c.JSON(400, gin.H{"error": "invalid body"})
|
c.JSON(400, gin.H{"error": "invalid body"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.cfg.OpenAICompatibility = migrateLegacyOpenAICompatibilityKeys(h.cfg.OpenAICompatibility)
|
|
||||||
normalizeOpenAICompatibilityEntry(body.Value)
|
normalizeOpenAICompatibilityEntry(body.Value)
|
||||||
// If base-url becomes empty, delete the provider instead of updating
|
// If base-url becomes empty, delete the provider instead of updating
|
||||||
if strings.TrimSpace(body.Value.BaseURL) == "" {
|
if strings.TrimSpace(body.Value.BaseURL) == "" {
|
||||||
@@ -731,28 +728,6 @@ func normalizeOpenAICompatibilityEntry(entry *config.OpenAICompatibility) {
|
|||||||
existing[trimmed] = struct{}{}
|
existing[trimmed] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(entry.APIKeys) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, legacyKey := range entry.APIKeys {
|
|
||||||
trimmed := strings.TrimSpace(legacyKey)
|
|
||||||
if trimmed == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, ok := existing[trimmed]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
entry.APIKeyEntries = append(entry.APIKeyEntries, config.OpenAICompatibilityAPIKey{APIKey: trimmed})
|
|
||||||
existing[trimmed] = struct{}{}
|
|
||||||
}
|
|
||||||
entry.APIKeys = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func migrateLegacyOpenAICompatibilityKeys(entries []config.OpenAICompatibility) []config.OpenAICompatibility {
|
|
||||||
for i := range entries {
|
|
||||||
normalizeOpenAICompatibilityEntry(&entries[i])
|
|
||||||
}
|
|
||||||
return entries
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizedOpenAICompatibilityEntries(entries []config.OpenAICompatibility) []config.OpenAICompatibility {
|
func normalizedOpenAICompatibilityEntries(entries []config.OpenAICompatibility) []config.OpenAICompatibility {
|
||||||
@@ -765,9 +740,6 @@ func normalizedOpenAICompatibilityEntries(entries []config.OpenAICompatibility)
|
|||||||
if len(copyEntry.APIKeyEntries) > 0 {
|
if len(copyEntry.APIKeyEntries) > 0 {
|
||||||
copyEntry.APIKeyEntries = append([]config.OpenAICompatibilityAPIKey(nil), copyEntry.APIKeyEntries...)
|
copyEntry.APIKeyEntries = append([]config.OpenAICompatibilityAPIKey(nil), copyEntry.APIKeyEntries...)
|
||||||
}
|
}
|
||||||
if len(copyEntry.APIKeys) > 0 {
|
|
||||||
copyEntry.APIKeys = append([]string(nil), copyEntry.APIKeys...)
|
|
||||||
}
|
|
||||||
normalizeOpenAICompatibilityEntry(©Entry)
|
normalizeOpenAICompatibilityEntry(©Entry)
|
||||||
out[i] = copyEntry
|
out[i] = copyEntry
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -938,11 +938,7 @@ func (s *Server) UpdateClients(cfg *config.Config) {
|
|||||||
openAICompatCount := 0
|
openAICompatCount := 0
|
||||||
for i := range cfg.OpenAICompatibility {
|
for i := range cfg.OpenAICompatibility {
|
||||||
entry := cfg.OpenAICompatibility[i]
|
entry := cfg.OpenAICompatibility[i]
|
||||||
if len(entry.APIKeyEntries) > 0 {
|
openAICompatCount += len(entry.APIKeyEntries)
|
||||||
openAICompatCount += len(entry.APIKeyEntries)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
openAICompatCount += len(entry.APIKeys)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
total := authFiles + geminiAPIKeyCount + claudeAPIKeyCount + codexAPIKeyCount + vertexAICompatCount + openAICompatCount
|
total := authFiles + geminiAPIKeyCount + claudeAPIKeyCount + codexAPIKeyCount + vertexAICompatCount + openAICompatCount
|
||||||
|
|||||||
@@ -58,9 +58,6 @@ type Config struct {
|
|||||||
// GeminiKey defines Gemini API key configurations with optional routing overrides.
|
// GeminiKey defines Gemini API key configurations with optional routing overrides.
|
||||||
GeminiKey []GeminiKey `yaml:"gemini-api-key" json:"gemini-api-key"`
|
GeminiKey []GeminiKey `yaml:"gemini-api-key" json:"gemini-api-key"`
|
||||||
|
|
||||||
// GlAPIKey exposes the legacy generative language API key list for backward compatibility.
|
|
||||||
GlAPIKey []string `yaml:"generative-language-api-key" json:"generative-language-api-key"`
|
|
||||||
|
|
||||||
// Codex defines a list of Codex API key configurations as specified in the YAML configuration file.
|
// Codex defines a list of Codex API key configurations as specified in the YAML configuration file.
|
||||||
CodexKey []CodexKey `yaml:"codex-api-key" json:"codex-api-key"`
|
CodexKey []CodexKey `yaml:"codex-api-key" json:"codex-api-key"`
|
||||||
|
|
||||||
@@ -170,6 +167,17 @@ type PayloadModelRule struct {
|
|||||||
Protocol string `yaml:"protocol" json:"protocol"`
|
Protocol string `yaml:"protocol" json:"protocol"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type legacyConfigData struct {
|
||||||
|
LegacyGeminiKeys []string `yaml:"generative-language-api-key"`
|
||||||
|
OpenAICompat []legacyOpenAICompatibility `yaml:"openai-compatibility"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type legacyOpenAICompatibility struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
BaseURL string `yaml:"base-url"`
|
||||||
|
APIKeys []string `yaml:"api-keys"`
|
||||||
|
}
|
||||||
|
|
||||||
// ClaudeKey represents the configuration for a Claude API key,
|
// ClaudeKey represents the configuration for a Claude API key,
|
||||||
// including the API key itself and an optional base URL for the API endpoint.
|
// including the API key itself and an optional base URL for the API endpoint.
|
||||||
type ClaudeKey struct {
|
type ClaudeKey struct {
|
||||||
@@ -250,10 +258,6 @@ type OpenAICompatibility struct {
|
|||||||
// BaseURL is the base URL for the external OpenAI-compatible API endpoint.
|
// BaseURL is the base URL for the external OpenAI-compatible API endpoint.
|
||||||
BaseURL string `yaml:"base-url" json:"base-url"`
|
BaseURL string `yaml:"base-url" json:"base-url"`
|
||||||
|
|
||||||
// APIKeys are the authentication keys for accessing the external API services.
|
|
||||||
// Deprecated: Use APIKeyEntries instead to support per-key proxy configuration.
|
|
||||||
APIKeys []string `yaml:"api-keys,omitempty" json:"api-keys,omitempty"`
|
|
||||||
|
|
||||||
// APIKeyEntries defines API keys with optional per-key proxy configuration.
|
// APIKeyEntries defines API keys with optional per-key proxy configuration.
|
||||||
APIKeyEntries []OpenAICompatibilityAPIKey `yaml:"api-key-entries,omitempty" json:"api-key-entries,omitempty"`
|
APIKeyEntries []OpenAICompatibilityAPIKey `yaml:"api-key-entries,omitempty" json:"api-key-entries,omitempty"`
|
||||||
|
|
||||||
@@ -333,6 +337,12 @@ func LoadConfigOptional(configFile string, optional bool) (*Config, error) {
|
|||||||
return nil, fmt.Errorf("failed to parse config file: %w", err)
|
return nil, fmt.Errorf("failed to parse config file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var legacy legacyConfigData
|
||||||
|
if errLegacy := yaml.Unmarshal(data, &legacy); errLegacy == nil {
|
||||||
|
cfg.migrateLegacyGeminiKeys(legacy.LegacyGeminiKeys)
|
||||||
|
cfg.migrateLegacyOpenAICompatibilityKeys(legacy.OpenAICompat)
|
||||||
|
}
|
||||||
|
|
||||||
// Hash remote management key if plaintext is detected (nested)
|
// Hash remote management key if plaintext is detected (nested)
|
||||||
// We consider a value to be already hashed if it looks like a bcrypt hash ($2a$, $2b$, or $2y$ prefix).
|
// We consider a value to be already hashed if it looks like a bcrypt hash ($2a$, $2b$, or $2y$ prefix).
|
||||||
if cfg.RemoteManagement.SecretKey != "" && !looksLikeBcrypt(cfg.RemoteManagement.SecretKey) {
|
if cfg.RemoteManagement.SecretKey != "" && !looksLikeBcrypt(cfg.RemoteManagement.SecretKey) {
|
||||||
@@ -451,22 +461,94 @@ func (cfg *Config) SanitizeGeminiKeys() {
|
|||||||
out = append(out, entry)
|
out = append(out, entry)
|
||||||
}
|
}
|
||||||
cfg.GeminiKey = out
|
cfg.GeminiKey = out
|
||||||
|
}
|
||||||
|
|
||||||
if len(cfg.GlAPIKey) > 0 {
|
func (cfg *Config) migrateLegacyGeminiKeys(legacy []string) {
|
||||||
for _, raw := range cfg.GlAPIKey {
|
if cfg == nil || len(legacy) == 0 {
|
||||||
key := strings.TrimSpace(raw)
|
return
|
||||||
if key == "" {
|
}
|
||||||
continue
|
seen := make(map[string]struct{}, len(cfg.GeminiKey))
|
||||||
}
|
for i := range cfg.GeminiKey {
|
||||||
if _, exists := seen[key]; exists {
|
key := strings.TrimSpace(cfg.GeminiKey[i].APIKey)
|
||||||
continue
|
if key == "" {
|
||||||
}
|
continue
|
||||||
cfg.GeminiKey = append(cfg.GeminiKey, GeminiKey{APIKey: key})
|
}
|
||||||
seen[key] = struct{}{}
|
seen[key] = struct{}{}
|
||||||
|
}
|
||||||
|
for _, raw := range legacy {
|
||||||
|
key := strings.TrimSpace(raw)
|
||||||
|
if key == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, exists := seen[key]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cfg.GeminiKey = append(cfg.GeminiKey, GeminiKey{APIKey: key})
|
||||||
|
seen[key] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg *Config) migrateLegacyOpenAICompatibilityKeys(legacy []legacyOpenAICompatibility) {
|
||||||
|
if cfg == nil || len(cfg.OpenAICompatibility) == 0 || len(legacy) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lookup := make(map[string]*OpenAICompatibility, len(cfg.OpenAICompatibility))
|
||||||
|
for i := range cfg.OpenAICompatibility {
|
||||||
|
if key := legacyOpenAICompatKey(cfg.OpenAICompatibility[i].Name, cfg.OpenAICompatibility[i].BaseURL); key != "" {
|
||||||
|
lookup[key] = &cfg.OpenAICompatibility[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, legacyEntry := range legacy {
|
||||||
|
if len(legacyEntry.APIKeys) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key := legacyOpenAICompatKey(legacyEntry.Name, legacyEntry.BaseURL)
|
||||||
|
if key == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
target := lookup[key]
|
||||||
|
if target == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mergeLegacyOpenAICompatAPIKeys(target, legacyEntry.APIKeys)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cfg.GlAPIKey = nil
|
func mergeLegacyOpenAICompatAPIKeys(entry *OpenAICompatibility, keys []string) {
|
||||||
|
if entry == nil || len(keys) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
existing := make(map[string]struct{}, len(entry.APIKeyEntries))
|
||||||
|
for i := range entry.APIKeyEntries {
|
||||||
|
key := strings.TrimSpace(entry.APIKeyEntries[i].APIKey)
|
||||||
|
if key == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
existing[key] = struct{}{}
|
||||||
|
}
|
||||||
|
for _, raw := range keys {
|
||||||
|
key := strings.TrimSpace(raw)
|
||||||
|
if key == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := existing[key]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
entry.APIKeyEntries = append(entry.APIKeyEntries, OpenAICompatibilityAPIKey{APIKey: key})
|
||||||
|
existing[key] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func legacyOpenAICompatKey(name, baseURL string) string {
|
||||||
|
trimmedName := strings.ToLower(strings.TrimSpace(name))
|
||||||
|
if trimmedName != "" {
|
||||||
|
return "name:" + trimmedName
|
||||||
|
}
|
||||||
|
trimmedBase := strings.ToLower(strings.TrimSpace(baseURL))
|
||||||
|
if trimmedBase != "" {
|
||||||
|
return "base:" + trimmedBase
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncInlineAccessProvider(cfg *Config) {
|
func syncInlineAccessProvider(cfg *Config) {
|
||||||
@@ -605,6 +687,7 @@ func SaveConfigPreserveComments(configFile string, cfg *Config) error {
|
|||||||
// Remove deprecated auth block before merging to avoid persisting it again.
|
// Remove deprecated auth block before merging to avoid persisting it again.
|
||||||
removeMapKey(original.Content[0], "auth")
|
removeMapKey(original.Content[0], "auth")
|
||||||
removeLegacyOpenAICompatAPIKeys(original.Content[0])
|
removeLegacyOpenAICompatAPIKeys(original.Content[0])
|
||||||
|
removeMapKey(original.Content[0], "generative-language-api-key")
|
||||||
pruneMappingToGeneratedKeys(original.Content[0], generated.Content[0], "oauth-excluded-models")
|
pruneMappingToGeneratedKeys(original.Content[0], generated.Content[0], "oauth-excluded-models")
|
||||||
|
|
||||||
// Merge generated into original in-place, preserving comments/order of existing nodes.
|
// Merge generated into original in-place, preserving comments/order of existing nodes.
|
||||||
|
|||||||
@@ -1162,71 +1162,37 @@ func (w *Watcher) SnapshotCoreAuths() []*coreauth.Auth {
|
|||||||
|
|
||||||
// Handle new APIKeyEntries format (preferred)
|
// Handle new APIKeyEntries format (preferred)
|
||||||
createdEntries := 0
|
createdEntries := 0
|
||||||
if len(compat.APIKeyEntries) > 0 {
|
for j := range compat.APIKeyEntries {
|
||||||
for j := range compat.APIKeyEntries {
|
entry := &compat.APIKeyEntries[j]
|
||||||
entry := &compat.APIKeyEntries[j]
|
key := strings.TrimSpace(entry.APIKey)
|
||||||
key := strings.TrimSpace(entry.APIKey)
|
proxyURL := strings.TrimSpace(entry.ProxyURL)
|
||||||
proxyURL := strings.TrimSpace(entry.ProxyURL)
|
idKind := fmt.Sprintf("openai-compatibility:%s", providerName)
|
||||||
idKind := fmt.Sprintf("openai-compatibility:%s", providerName)
|
id, token := idGen.next(idKind, key, base, proxyURL)
|
||||||
id, token := idGen.next(idKind, key, base, proxyURL)
|
attrs := map[string]string{
|
||||||
attrs := map[string]string{
|
"source": fmt.Sprintf("config:%s[%s]", providerName, token),
|
||||||
"source": fmt.Sprintf("config:%s[%s]", providerName, token),
|
"base_url": base,
|
||||||
"base_url": base,
|
"compat_name": compat.Name,
|
||||||
"compat_name": compat.Name,
|
"provider_key": providerName,
|
||||||
"provider_key": providerName,
|
|
||||||
}
|
|
||||||
if key != "" {
|
|
||||||
attrs["api_key"] = key
|
|
||||||
}
|
|
||||||
if hash := computeOpenAICompatModelsHash(compat.Models); hash != "" {
|
|
||||||
attrs["models_hash"] = hash
|
|
||||||
}
|
|
||||||
addConfigHeadersToAttrs(compat.Headers, attrs)
|
|
||||||
a := &coreauth.Auth{
|
|
||||||
ID: id,
|
|
||||||
Provider: providerName,
|
|
||||||
Label: compat.Name,
|
|
||||||
Status: coreauth.StatusActive,
|
|
||||||
ProxyURL: proxyURL,
|
|
||||||
Attributes: attrs,
|
|
||||||
CreatedAt: now,
|
|
||||||
UpdatedAt: now,
|
|
||||||
}
|
|
||||||
out = append(out, a)
|
|
||||||
createdEntries++
|
|
||||||
}
|
}
|
||||||
} else {
|
if key != "" {
|
||||||
// Handle legacy APIKeys format for backward compatibility
|
|
||||||
for j := range compat.APIKeys {
|
|
||||||
key := strings.TrimSpace(compat.APIKeys[j])
|
|
||||||
if key == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
idKind := fmt.Sprintf("openai-compatibility:%s", providerName)
|
|
||||||
id, token := idGen.next(idKind, key, base)
|
|
||||||
attrs := map[string]string{
|
|
||||||
"source": fmt.Sprintf("config:%s[%s]", providerName, token),
|
|
||||||
"base_url": base,
|
|
||||||
"compat_name": compat.Name,
|
|
||||||
"provider_key": providerName,
|
|
||||||
}
|
|
||||||
attrs["api_key"] = key
|
attrs["api_key"] = key
|
||||||
if hash := computeOpenAICompatModelsHash(compat.Models); hash != "" {
|
|
||||||
attrs["models_hash"] = hash
|
|
||||||
}
|
|
||||||
addConfigHeadersToAttrs(compat.Headers, attrs)
|
|
||||||
a := &coreauth.Auth{
|
|
||||||
ID: id,
|
|
||||||
Provider: providerName,
|
|
||||||
Label: compat.Name,
|
|
||||||
Status: coreauth.StatusActive,
|
|
||||||
Attributes: attrs,
|
|
||||||
CreatedAt: now,
|
|
||||||
UpdatedAt: now,
|
|
||||||
}
|
|
||||||
out = append(out, a)
|
|
||||||
createdEntries++
|
|
||||||
}
|
}
|
||||||
|
if hash := computeOpenAICompatModelsHash(compat.Models); hash != "" {
|
||||||
|
attrs["models_hash"] = hash
|
||||||
|
}
|
||||||
|
addConfigHeadersToAttrs(compat.Headers, attrs)
|
||||||
|
a := &coreauth.Auth{
|
||||||
|
ID: id,
|
||||||
|
Provider: providerName,
|
||||||
|
Label: compat.Name,
|
||||||
|
Status: coreauth.StatusActive,
|
||||||
|
ProxyURL: proxyURL,
|
||||||
|
Attributes: attrs,
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
}
|
||||||
|
out = append(out, a)
|
||||||
|
createdEntries++
|
||||||
}
|
}
|
||||||
if createdEntries == 0 {
|
if createdEntries == 0 {
|
||||||
idKind := fmt.Sprintf("openai-compatibility:%s", providerName)
|
idKind := fmt.Sprintf("openai-compatibility:%s", providerName)
|
||||||
@@ -1530,12 +1496,7 @@ func BuildAPIKeyClients(cfg *config.Config) (int, int, int, int, int) {
|
|||||||
if len(cfg.OpenAICompatibility) > 0 {
|
if len(cfg.OpenAICompatibility) > 0 {
|
||||||
// Do not construct legacy clients for OpenAI-compat providers; these are handled by the stateless executor.
|
// Do not construct legacy clients for OpenAI-compat providers; these are handled by the stateless executor.
|
||||||
for _, compatConfig := range cfg.OpenAICompatibility {
|
for _, compatConfig := range cfg.OpenAICompatibility {
|
||||||
// Count from new APIKeyEntries format if present, otherwise fall back to legacy APIKeys
|
openAICompatCount += len(compatConfig.APIKeyEntries)
|
||||||
if len(compatConfig.APIKeyEntries) > 0 {
|
|
||||||
openAICompatCount += len(compatConfig.APIKeyEntries)
|
|
||||||
} else {
|
|
||||||
openAICompatCount += len(compatConfig.APIKeys)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return geminiAPIKeyCount, vertexCompatAPIKeyCount, claudeAPIKeyCount, codexAPIKeyCount, openAICompatCount
|
return geminiAPIKeyCount, vertexCompatAPIKeyCount, claudeAPIKeyCount, codexAPIKeyCount, openAICompatCount
|
||||||
@@ -1612,24 +1573,9 @@ func describeOpenAICompatibilityUpdate(oldEntry, newEntry config.OpenAICompatibi
|
|||||||
}
|
}
|
||||||
|
|
||||||
func countAPIKeys(entry config.OpenAICompatibility) int {
|
func countAPIKeys(entry config.OpenAICompatibility) int {
|
||||||
// Prefer new APIKeyEntries format
|
|
||||||
if len(entry.APIKeyEntries) > 0 {
|
|
||||||
count := 0
|
|
||||||
for _, keyEntry := range entry.APIKeyEntries {
|
|
||||||
if strings.TrimSpace(keyEntry.APIKey) != "" {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
// Fall back to legacy APIKeys format
|
|
||||||
return countNonEmptyStrings(entry.APIKeys)
|
|
||||||
}
|
|
||||||
|
|
||||||
func countNonEmptyStrings(values []string) int {
|
|
||||||
count := 0
|
count := 0
|
||||||
for _, value := range values {
|
for _, keyEntry := range entry.APIKeyEntries {
|
||||||
if strings.TrimSpace(value) != "" {
|
if strings.TrimSpace(keyEntry.APIKey) != "" {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1754,9 +1700,6 @@ func buildConfigChangeDetails(oldCfg, newCfg *config.Config) []string {
|
|||||||
changes = append(changes, fmt.Sprintf("gemini[%d].excluded-models: updated (%d -> %d entries)", i, oldExcluded.count, newExcluded.count))
|
changes = append(changes, fmt.Sprintf("gemini[%d].excluded-models: updated (%d -> %d entries)", i, oldExcluded.count, newExcluded.count))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(trimStrings(oldCfg.GlAPIKey), trimStrings(newCfg.GlAPIKey)) {
|
|
||||||
changes = append(changes, "generative-language-api-key: values updated (legacy view, redacted)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Claude keys (do not print key material)
|
// Claude keys (do not print key material)
|
||||||
|
|||||||
Reference in New Issue
Block a user