refactor(config): rename model-name-mappings to oauth-model-mappings
Unified · Split
| @@ -156,9 +156,9 @@ ws-auth: false · 155 unmodified lines | ||
| 156 | 156 | # headers: |
| 157 | 157 | # X-Custom-Header: "custom-value" |
| 158 | 158 | # models: # optional: map aliases to upstream model names |
| 159 | −# - name: "gemini-2.0-flash" # upstream model name | |
| 159 | +# - name: "gemini-2.5-flash" # upstream model name | |
| 160 | 160 | # alias: "vertex-flash" # client-visible alias |
| 161 | −# - name: "gemini-1.5-pro" | |
| 161 | +# - name: "gemini-2.5-pro" | |
| 162 | 162 | # alias: "vertex-pro" |
| 163 | 163 | |
| 164 | 164 | # Amp Integration |
| @@ -188,38 +188,42 @@ ws-auth: false · 23 unmodified lines | ||
| 188 | 188 | # # Useful when Amp CLI requests models you don't have access to (e.g., Claude Opus 4.5) |
| 189 | 189 | # # but you have a similar model available (e.g., Claude Sonnet 4). |
| 190 | 190 | # model-mappings: |
| 191 | −# - from: "claude-opus-4.5" # Model requested by Amp CLI | |
| 192 | −# to: "claude-sonnet-4" # Route to this available model instead | |
| 193 | −# - from: "gpt-5" | |
| 194 | −# to: "gemini-2.5-pro" | |
| 195 | −# - from: "claude-3-opus-20240229" | |
| 196 | −# to: "claude-3-5-sonnet-20241022" | |
| 191 | +# - from: "claude-opus-4-5-20251101" # Model requested by Amp CLI | |
| 192 | +# to: "gemini-claude-opus-4-5-thinking" # Route to this available model instead | |
| 193 | +# - from: "claude-sonnet-4-5-20250929" | |
| 194 | +# to: "gemini-claude-sonnet-4-5-thinking" | |
| 195 | +# - from: "claude-haiku-4-5-20251001" | |
| 196 | +# to: "gemini-2.5-flash" | |
| 197 | 197 | |
| 198 | −# Global model name mappings (per channel) | |
| 198 | +# Global OAuth model name mappings (per channel) | |
| 199 | 199 | # These mappings rename model IDs for both model listing and request routing. |
| 200 | −# NOTE: Mappings do not apply to codex-api-key, claude-api-key, openai-compatibility, vertex-api-key, or ampcode. | |
| 201 | −# model-name-mappings: | |
| 202 | −# gemini: | |
| 203 | −# - from: "gemini-2.5-pro" # original model name under this channel | |
| 204 | −# to: "gpt-5" # client-visible alias | |
| 205 | −# apikey-gemini: | |
| 206 | −# - from: "gemini-2.5-pro" | |
| 207 | −# to: "gpt-5" | |
| 208 | −# claude: | |
| 209 | −# - from: "claude-sonnet-4" | |
| 210 | −# to: "gpt-4o" | |
| 200 | +# Supported channels: gemini-cli, vertex, aistudio, antigravity, claude, codex, qwen, iflow. | |
| 201 | +# NOTE: Mappings do not apply to gemini-api-key, codex-api-key, claude-api-key, openai-compatibility, vertex-api-key, or ampcode. | |
| 202 | +# oauth-model-mappings: | |
| 203 | +# gemini-cli: | |
| 204 | +# - name: "gemini-2.5-pro" # original model name under this channel | |
| 205 | +# alias: "g2.5p" # client-visible alias | |
| 211 | 206 | # vertex: |
| 212 | −# - from: "gemini-2.5-pro" | |
| 213 | −# to: "gpt-5" | |
| 207 | +# - name: "gemini-2.5-pro" | |
| 208 | +# alias: "g2.5p" | |
| 209 | +# aistudio: | |
| 210 | +# - name: "gemini-2.5-pro" | |
| 211 | +# alias: "g2.5p" | |
| 212 | +# antigravity: | |
| 213 | +# - name: "gemini-3-pro-preview" | |
| 214 | +# alias: "g3p" | |
| 215 | +# claude: | |
| 216 | +# - name: "claude-sonnet-4-5-20250929" | |
| 217 | +# alias: "cs4.5" | |
| 218 | +# codex: | |
| 219 | +# - name: "gpt-5" | |
| 220 | +# alias: "g5" | |
| 214 | 221 | # qwen: |
| 215 | −# - from: "qwen3-coder-plus" | |
| 216 | −# to: "gpt-4o-mini" | |
| 222 | +# - name: "qwen3-coder-plus" | |
| 223 | +# alias: "qwen-plus" | |
| 217 | 224 | # iflow: |
| 218 | −# - from: "glm-4.7" | |
| 219 | −# to: "gpt-5.1-mini" | |
| 220 | −# antigravity: | |
| 221 | −# - from: "gemini-3-pro-preview" | |
| 222 | −# to: "gpt-5" | |
| 225 | +# - name: "glm-4.7" | |
| 226 | +# alias: "glm-god" | |
| 223 | 227 | |
| 224 | 228 | # OAuth provider excluded models |
| 225 | 229 | # oauth-excluded-models: |
| @@ -91,12 +91,13 @@ type Config struct { · 90 unmodified lines | ||
| 91 | 91 | // OAuthExcludedModels defines per-provider global model exclusions applied to OAuth/file-backed auth entries. |
| 92 | 92 | OAuthExcludedModels map[string][]string `yaml:"oauth-excluded-models,omitempty" json:"oauth-excluded-models,omitempty"` |
| 93 | 93 | |
| 94 | − // ModelNameMappings defines global per-channel model name mappings. | |
| 95 | − // These mappings affect both model listing and model routing for supported channels. | |
| 94 | + // OAuthModelMappings defines global model name mappings for OAuth/file-backed auth channels. | |
| 95 | + // These mappings affect both model listing and model routing for supported channels: | |
| 96 | + // gemini-cli, vertex, aistudio, antigravity, claude, codex, qwen, iflow. | |
| 96 | 97 | // |
| 97 | 98 | // NOTE: This does not apply to existing per-credential model alias features under: |
| 98 | − // codex-api-key, claude-api-key, openai-compatibility, vertex-api-key, and ampcode. | |
| 99 | − ModelNameMappings map[string][]ModelNameMapping `yaml:"model-name-mappings,omitempty" json:"model-name-mappings,omitempty"` | |
| 99 | + // gemini-api-key, codex-api-key, claude-api-key, openai-compatibility, vertex-api-key, and ampcode. | |
| 100 | + OAuthModelMappings map[string][]ModelNameMapping `yaml:"oauth-model-mappings,omitempty" json:"oauth-model-mappings,omitempty"` | |
| 100 | 101 | |
| 101 | 102 | // Payload defines default and override rules for provider payload parameters. |
| 102 | 103 | Payload PayloadConfig `yaml:"payload" json:"payload"` |
| @@ -145,10 +146,10 @@ type RoutingConfig struct { · 42 unmodified lines | ||
| 145 | 146 | } |
| 146 | 147 | |
| 147 | 148 | // ModelNameMapping defines a model ID rename mapping for a specific channel. |
| 148 | −// It maps the original model name (From) to the client-visible alias (To). | |
| 149 | +// It maps the original model name (Name) to the client-visible alias (Alias). | |
| 149 | 150 | type ModelNameMapping struct { |
| 150 | − From string `yaml:"from" json:"from"` | |
| 151 | − To string `yaml:"to" json:"to"` | |
| 151 | + Name string `yaml:"name" json:"name"` | |
| 152 | + Alias string `yaml:"alias" json:"alias"` | |
| 152 | 153 | } |
| 153 | 154 | |
| 154 | 155 | // AmpModelMapping defines a model name mapping for Amp CLI requests. |
| @@ -475,8 +476,8 @@ func LoadConfigOptional(configFile string, optional bool) (*Config, error) { · 320 unmodified lines | ||
| 475 | 476 | // Normalize OAuth provider model exclusion map. |
| 476 | 477 | cfg.OAuthExcludedModels = NormalizeOAuthExcludedModels(cfg.OAuthExcludedModels) |
| 477 | 478 | |
| 478 | − // Normalize global model name mappings. | |
| 479 | − cfg.SanitizeModelNameMappings() | |
| 479 | + // Normalize global OAuth model name mappings. | |
| 480 | + cfg.SanitizeOAuthModelMappings() | |
| 480 | 481 | |
| 481 | 482 | if cfg.legacyMigrationPending { |
| 482 | 483 | fmt.Println("Detected legacy configuration keys, attempting to persist the normalized config...") |
| @@ -494,48 +495,48 @@ func LoadConfigOptional(configFile string, optional bool) (*Config, error) { · 11 unmodified lines | ||
| 494 | 495 | return &cfg, nil |
| 495 | 496 | } |
| 496 | 497 | |
| 497 | −// SanitizeModelNameMappings normalizes and deduplicates global model name mappings. | |
| 498 | +// SanitizeOAuthModelMappings normalizes and deduplicates global OAuth model name mappings. | |
| 498 | 499 | // It trims whitespace, normalizes channel keys to lower-case, drops empty entries, |
| 499 | 500 | // and ensures (From, To) pairs are unique within each channel. |
| 500 | −func (cfg *Config) SanitizeModelNameMappings() { | |
| 501 | − if cfg == nil || len(cfg.ModelNameMappings) == 0 { | |
| 501 | +func (cfg *Config) SanitizeOAuthModelMappings() { | |
| 502 | + if cfg == nil || len(cfg.OAuthModelMappings) == 0 { | |
| 502 | 503 | return |
| 503 | 504 | } |
| 504 | − out := make(map[string][]ModelNameMapping, len(cfg.ModelNameMappings)) | |
| 505 | − for rawChannel, mappings := range cfg.ModelNameMappings { | |
| 505 | + out := make(map[string][]ModelNameMapping, len(cfg.OAuthModelMappings)) | |
| 506 | + for rawChannel, mappings := range cfg.OAuthModelMappings { | |
| 506 | 507 | channel := strings.ToLower(strings.TrimSpace(rawChannel)) |
| 507 | 508 | if channel == "" || len(mappings) == 0 { |
| 508 | 509 | continue |
| 509 | 510 | } |
| 510 | − seenFrom := make(map[string]struct{}, len(mappings)) | |
| 511 | − seenTo := make(map[string]struct{}, len(mappings)) | |
| 511 | + seenName := make(map[string]struct{}, len(mappings)) | |
| 512 | + seenAlias := make(map[string]struct{}, len(mappings)) | |
| 512 | 513 | clean := make([]ModelNameMapping, 0, len(mappings)) |
| 513 | 514 | for _, mapping := range mappings { |
| 514 | − from := strings.TrimSpace(mapping.From) | |
| 515 | − to := strings.TrimSpace(mapping.To) | |
| 516 | − if from == "" || to == "" { | |
| 515 | + name := strings.TrimSpace(mapping.Name) | |
| 516 | + alias := strings.TrimSpace(mapping.Alias) | |
| 517 | + if name == "" || alias == "" { | |
| 517 | 518 | continue |
| 518 | 519 | } |
| 519 | − if strings.EqualFold(from, to) { | |
| 520 | + if strings.EqualFold(name, alias) { | |
| 520 | 521 | continue |
| 521 | 522 | } |
| 522 | − fromKey := strings.ToLower(from) | |
| 523 | − toKey := strings.ToLower(to) | |
| 524 | − if _, ok := seenFrom[fromKey]; ok { | |
| 523 | + nameKey := strings.ToLower(name) | |
| 524 | + aliasKey := strings.ToLower(alias) | |
| 525 | + if _, ok := seenName[nameKey]; ok { | |
| 525 | 526 | continue |
| 526 | 527 | } |
| 527 | − if _, ok := seenTo[toKey]; ok { | |
| 528 | + if _, ok := seenAlias[aliasKey]; ok { | |
| 528 | 529 | continue |
| 529 | 530 | } |
| 530 | − seenFrom[fromKey] = struct{}{} | |
| 531 | − seenTo[toKey] = struct{}{} | |
| 532 | − clean = append(clean, ModelNameMapping{From: from, To: to}) | |
| 531 | + seenName[nameKey] = struct{}{} | |
| 532 | + seenAlias[aliasKey] = struct{}{} | |
| 533 | + clean = append(clean, ModelNameMapping{Name: name, Alias: alias}) | |
| 533 | 534 | } |
| 534 | 535 | if len(clean) > 0 { |
| 535 | 536 | out[channel] = clean |
| 536 | 537 | } |
| 537 | 538 | } |
| 538 | − cfg.ModelNameMappings = out | |
| 539 | + cfg.OAuthModelMappings = out | |
| 539 | 540 | } |
| 540 | 541 | |
| 541 | 542 | // SanitizeOpenAICompatibility removes OpenAI-compatibility provider entries that are |
| @@ -127,7 +127,7 @@ func (w *Watcher) reloadConfig() bool { · 126 unmodified lines | ||
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | authDirChanged := oldConfig == nil || oldConfig.AuthDir != newConfig.AuthDir |
| 130 | − forceAuthRefresh := oldConfig != nil && (oldConfig.ForceModelPrefix != newConfig.ForceModelPrefix || !reflect.DeepEqual(oldConfig.ModelNameMappings, newConfig.ModelNameMappings)) | |
| 130 | + forceAuthRefresh := oldConfig != nil && (oldConfig.ForceModelPrefix != newConfig.ForceModelPrefix || !reflect.DeepEqual(oldConfig.OAuthModelMappings, newConfig.OAuthModelMappings)) | |
| 131 | 131 | |
| 132 | 132 | log.Infof("config successfully reloaded, triggering client reload") |
| 133 | 133 | w.reloadClients(authDirChanged, affectedOAuthProviders, forceAuthRefresh) |
| @@ -413,7 +413,7 @@ func (m *Manager) executeWithProvider(ctx context.Context, provider string, req · 412 unmodified lines | ||
| 413 | 413 | } |
| 414 | 414 | execReq := req |
| 415 | 415 | execReq.Model, execReq.Metadata = rewriteModelForAuth(routeModel, req.Metadata, auth) |
| 416 | − execReq.Metadata = m.applyGlobalModelNameMappingMetadata(auth, execReq.Model, execReq.Metadata) | |
| 416 | + execReq.Metadata = m.applyOAuthModelMappingMetadata(auth, execReq.Model, execReq.Metadata) | |
| 417 | 417 | resp, errExec := executor.Execute(execCtx, auth, execReq, opts) |
| 418 | 418 | result := Result{AuthID: auth.ID, Provider: provider, Model: routeModel, Success: errExec == nil} |
| 419 | 419 | if errExec != nil { |
| @@ -475,7 +475,7 @@ func (m *Manager) executeCountWithProvider(ctx context.Context, provider string, · 55 unmodified lines | ||
| 475 | 475 | } |
| 476 | 476 | execReq := req |
| 477 | 477 | execReq.Model, execReq.Metadata = rewriteModelForAuth(routeModel, req.Metadata, auth) |
| 478 | − execReq.Metadata = m.applyGlobalModelNameMappingMetadata(auth, execReq.Model, execReq.Metadata) | |
| 478 | + execReq.Metadata = m.applyOAuthModelMappingMetadata(auth, execReq.Model, execReq.Metadata) | |
| 479 | 479 | resp, errExec := executor.CountTokens(execCtx, auth, execReq, opts) |
| 480 | 480 | result := Result{AuthID: auth.ID, Provider: provider, Model: routeModel, Success: errExec == nil} |
| 481 | 481 | if errExec != nil { |
| @@ -537,7 +537,7 @@ func (m *Manager) executeStreamWithProvider(ctx context.Context, provider string · 55 unmodified lines | ||
| 537 | 537 | } |
| 538 | 538 | execReq := req |
| 539 | 539 | execReq.Model, execReq.Metadata = rewriteModelForAuth(routeModel, req.Metadata, auth) |
| 540 | − execReq.Metadata = m.applyGlobalModelNameMappingMetadata(auth, execReq.Model, execReq.Metadata) | |
| 540 | + execReq.Metadata = m.applyOAuthModelMappingMetadata(auth, execReq.Model, execReq.Metadata) | |
| 541 | 541 | chunks, errStream := executor.ExecuteStream(execCtx, auth, execReq, opts) |
| 542 | 542 | if errStream != nil { |
| 543 | 543 | rerr := &Error{Message: errStream.Error()} |
| @@ -26,19 +26,19 @@ func compileModelNameMappingTable(mappings map[string][]internalconfig.ModelName · 25 unmodified lines | ||
| 26 | 26 | } |
| 27 | 27 | rev := make(map[string]string, len(entries)) |
| 28 | 28 | for _, entry := range entries { |
| 29 | − from := strings.TrimSpace(entry.From) | |
| 30 | − to := strings.TrimSpace(entry.To) | |
| 31 | − if from == "" || to == "" { | |
| 29 | + name := strings.TrimSpace(entry.Name) | |
| 30 | + alias := strings.TrimSpace(entry.Alias) | |
| 31 | + if name == "" || alias == "" { | |
| 32 | 32 | continue |
| 33 | 33 | } |
| 34 | − if strings.EqualFold(from, to) { | |
| 34 | + if strings.EqualFold(name, alias) { | |
| 35 | 35 | continue |
| 36 | 36 | } |
| 37 | − aliasKey := strings.ToLower(to) | |
| 37 | + aliasKey := strings.ToLower(alias) | |
| 38 | 38 | if _, exists := rev[aliasKey]; exists { |
| 39 | 39 | continue |
| 40 | 40 | } |
| 41 | − rev[aliasKey] = from | |
| 41 | + rev[aliasKey] = name | |
| 42 | 42 | } |
| 43 | 43 | if len(rev) > 0 { |
| 44 | 44 | out.reverse[channel] = rev |
| @@ -50,10 +50,10 @@ func compileModelNameMappingTable(mappings map[string][]internalconfig.ModelName · 5 unmodified lines | ||
| 50 | 50 | return out |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | −// SetGlobalModelNameMappings updates the global model name mapping table used during execution. | |
| 53 | +// SetOAuthModelMappings updates the OAuth model name mapping table used during execution. | |
| 54 | 54 | // The mapping is applied per-auth channel to resolve the upstream model name while keeping the |
| 55 | 55 | // client-visible model name unchanged for translation/response formatting. |
| 56 | −func (m *Manager) SetGlobalModelNameMappings(mappings map[string][]internalconfig.ModelNameMapping) { | |
| 56 | +func (m *Manager) SetOAuthModelMappings(mappings map[string][]internalconfig.ModelNameMapping) { | |
| 57 | 57 | if m == nil { |
| 58 | 58 | return |
| 59 | 59 | } |
| @@ -65,8 +65,8 @@ func (m *Manager) SetGlobalModelNameMappings(mappings map[string][]internalconfi · 5 unmodified lines | ||
| 65 | 65 | m.modelNameMappings.Store(table) |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | −func (m *Manager) applyGlobalModelNameMappingMetadata(auth *Auth, requestedModel string, metadata map[string]any) map[string]any { | |
| 69 | − original := m.resolveGlobalUpstreamModelForAuth(auth, requestedModel) | |
| 68 | +func (m *Manager) applyOAuthModelMappingMetadata(auth *Auth, requestedModel string, metadata map[string]any) map[string]any { | |
| 69 | + original := m.resolveOAuthUpstreamModel(auth, requestedModel) | |
| 70 | 70 | if original == "" { |
| 71 | 71 | return metadata |
| 72 | 72 | } |
| @@ -88,11 +88,11 @@ func (m *Manager) applyGlobalModelNameMappingMetadata(auth *Auth, requestedModel · 15 unmodified lines | ||
| 88 | 88 | return out |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | −func (m *Manager) resolveGlobalUpstreamModelForAuth(auth *Auth, requestedModel string) string { | |
| 91 | +func (m *Manager) resolveOAuthUpstreamModel(auth *Auth, requestedModel string) string { | |
| 92 | 92 | if m == nil || auth == nil { |
| 93 | 93 | return "" |
| 94 | 94 | } |
| 95 | − channel := globalModelMappingChannelForAuth(auth) | |
| 95 | + channel := modelMappingChannel(auth) | |
| 96 | 96 | if channel == "" { |
| 97 | 97 | return "" |
| 98 | 98 | } |
| @@ -116,7 +116,10 @@ func (m *Manager) resolveGlobalUpstreamModelForAuth(auth *Auth, requestedModel s · 17 unmodified lines | ||
| 116 | 116 | return original |
| 117 | 117 | } |
| 118 | 118 | |
| 119 | −func globalModelMappingChannelForAuth(auth *Auth) string { | |
| 119 | +// modelMappingChannel extracts the OAuth model mapping channel from an Auth object. | |
| 120 | +// It determines the provider and auth kind from the Auth's attributes and delegates | |
| 121 | +// to OAuthModelMappingChannel for the actual channel resolution. | |
| 122 | +func modelMappingChannel(auth *Auth) string { | |
| 120 | 123 | if auth == nil { |
| 121 | 124 | return "" |
| 122 | 125 | } |
| @@ -130,32 +133,38 @@ func globalModelMappingChannelForAuth(auth *Auth) string { · 7 unmodified lines | ||
| 130 | 133 | authKind = "apikey" |
| 131 | 134 | } |
| 132 | 135 | } |
| 133 | − return globalModelMappingChannel(provider, authKind) | |
| 136 | + return OAuthModelMappingChannel(provider, authKind) | |
| 134 | 137 | } |
| 135 | 138 | |
| 136 | −func globalModelMappingChannel(provider, authKind string) string { | |
| 139 | +// OAuthModelMappingChannel returns the OAuth model mapping channel name for a given provider | |
| 140 | +// and auth kind. Returns empty string if the provider/authKind combination doesn't support | |
| 141 | +// OAuth model mappings (e.g., API key authentication). | |
| 142 | +// | |
| 143 | +// Supported channels: gemini-cli, vertex, aistudio, antigravity, claude, codex, qwen, iflow. | |
| 144 | +func OAuthModelMappingChannel(provider, authKind string) string { | |
| 145 | + provider = strings.ToLower(strings.TrimSpace(provider)) | |
| 146 | + authKind = strings.ToLower(strings.TrimSpace(authKind)) | |
| 137 | 147 | switch provider { |
| 138 | 148 | case "gemini": |
| 139 | − if authKind == "apikey" { | |
| 140 | − return "apikey-gemini" | |
| 141 | − } | |
| 142 | − return "gemini" | |
| 143 | − case "codex": | |
| 149 | + // gemini provider uses gemini-api-key config, not oauth-model-mappings. | |
| 150 | + // OAuth-based gemini auth is converted to "gemini-cli" by the synthesizer. | |
| 151 | + return "" | |
| 152 | + case "vertex": | |
| 144 | 153 | if authKind == "apikey" { |
| 145 | 154 | return "" |
| 146 | 155 | } |
| 147 | − return "codex" | |
| 156 | + return "vertex" | |
| 148 | 157 | case "claude": |
| 149 | 158 | if authKind == "apikey" { |
| 150 | 159 | return "" |
| 151 | 160 | } |
| 152 | 161 | return "claude" |
| 153 | − case "vertex": | |
| 162 | + case "codex": | |
| 154 | 163 | if authKind == "apikey" { |
| 155 | 164 | return "" |
| 156 | 165 | } |
| 157 | − return "vertex" | |
| 158 | − case "antigravity", "qwen", "iflow": | |
| 166 | + return "codex" | |
| 167 | + case "gemini-cli", "aistudio", "antigravity", "qwen", "iflow": | |
| 159 | 168 | return provider |
| 160 | 169 | default: |
| 161 | 170 | return "" |
| @@ -215,7 +215,7 @@ func (b *Builder) Build() (*Service, error) { · 214 unmodified lines | ||
| 215 | 215 | } |
| 216 | 216 | // Attach a default RoundTripper provider so providers can opt-in per-auth transports. |
| 217 | 217 | coreManager.SetRoundTripperProvider(newDefaultRoundTripperProvider()) |
| 218 | − coreManager.SetGlobalModelNameMappings(b.cfg.ModelNameMappings) | |
| 218 | + coreManager.SetOAuthModelMappings(b.cfg.OAuthModelMappings) | |
| 219 | 219 | |
| 220 | 220 | service := &Service{ |
| 221 | 221 | cfg: b.cfg, |
| @@ -553,7 +553,7 @@ func (s *Service) Run(ctx context.Context) error { · 552 unmodified lines | ||
| 553 | 553 | s.cfg = newCfg |
| 554 | 554 | s.cfgMu.Unlock() |
| 555 | 555 | if s.coreManager != nil { |
| 556 | − s.coreManager.SetGlobalModelNameMappings(newCfg.ModelNameMappings) | |
| 556 | + s.coreManager.SetOAuthModelMappings(newCfg.OAuthModelMappings) | |
| 557 | 557 | } |
| 558 | 558 | s.rebindExecutors() |
| 559 | 559 | } |
| @@ -844,7 +844,7 @@ func (s *Service) registerModelsForAuth(a *coreauth.Auth) { · 284 unmodified lines | ||
| 844 | 844 | } |
| 845 | 845 | } |
| 846 | 846 | } |
| 847 | − models = applyGlobalModelNameMappings(s.cfg, provider, authKind, models) | |
| 847 | + models = applyOAuthModelMappings(s.cfg, provider, authKind, models) | |
| 848 | 848 | if len(models) > 0 { |
| 849 | 849 | key := provider |
| 850 | 850 | if key == "" { |
| @@ -1154,37 +1154,6 @@ func buildVertexCompatConfigModels(entry *config.VertexCompatKey) []*ModelInfo { · 303 unmodified lines | ||
| 1154 | 1154 | return out |
| 1155 | 1155 | } |
| 1156 | 1156 | |
| 1157 | −func globalModelMappingChannel(provider, authKind string) string { | |
| 1158 | − provider = strings.ToLower(strings.TrimSpace(provider)) | |
| 1159 | − authKind = strings.ToLower(strings.TrimSpace(authKind)) | |
| 1160 | − switch provider { | |
| 1161 | − case "gemini": | |
| 1162 | − if authKind == "apikey" { | |
| 1163 | − return "apikey-gemini" | |
| 1164 | − } | |
| 1165 | − return "gemini" | |
| 1166 | − case "codex": | |
| 1167 | − if authKind == "apikey" { | |
| 1168 | − return "" | |
| 1169 | − } | |
| 1170 | − return "codex" | |
| 1171 | − case "claude": | |
| 1172 | − if authKind == "apikey" { | |
| 1173 | − return "" | |
| 1174 | − } | |
| 1175 | − return "claude" | |
| 1176 | − case "vertex": | |
| 1177 | − if authKind == "apikey" { | |
| 1178 | − return "" | |
| 1179 | − } | |
| 1180 | − return "vertex" | |
| 1181 | − case "antigravity", "qwen", "iflow": | |
| 1182 | − return provider | |
| 1183 | − default: | |
| 1184 | − return "" | |
| 1185 | − } | |
| 1186 | −} | |
| 1187 | − | |
| 1188 | 1157 | func rewriteModelInfoName(name, oldID, newID string) string { |
| 1189 | 1158 | trimmed := strings.TrimSpace(name) |
| 1190 | 1159 | if trimmed == "" { |
| @@ -1208,33 +1177,33 @@ func rewriteModelInfoName(name, oldID, newID string) string { · 17 unmodified lines | ||
| 1208 | 1177 | return name |
| 1209 | 1178 | } |
| 1210 | 1179 | |
| 1211 | −func applyGlobalModelNameMappings(cfg *config.Config, provider, authKind string, models []*ModelInfo) []*ModelInfo { | |
| 1180 | +func applyOAuthModelMappings(cfg *config.Config, provider, authKind string, models []*ModelInfo) []*ModelInfo { | |
| 1212 | 1181 | if cfg == nil || len(models) == 0 { |
| 1213 | 1182 | return models |
| 1214 | 1183 | } |
| 1215 | − channel := globalModelMappingChannel(provider, authKind) | |
| 1216 | − if channel == "" || len(cfg.ModelNameMappings) == 0 { | |
| 1184 | + channel := coreauth.OAuthModelMappingChannel(provider, authKind) | |
| 1185 | + if channel == "" || len(cfg.OAuthModelMappings) == 0 { | |
| 1217 | 1186 | return models |
| 1218 | 1187 | } |
| 1219 | − mappings := cfg.ModelNameMappings[channel] | |
| 1188 | + mappings := cfg.OAuthModelMappings[channel] | |
| 1220 | 1189 | if len(mappings) == 0 { |
| 1221 | 1190 | return models |
| 1222 | 1191 | } |
| 1223 | 1192 | forward := make(map[string]string, len(mappings)) |
| 1224 | 1193 | for i := range mappings { |
| 1225 | − from := strings.TrimSpace(mappings[i].From) | |
| 1226 | − to := strings.TrimSpace(mappings[i].To) | |
| 1227 | − if from == "" || to == "" { | |
| 1194 | + name := strings.TrimSpace(mappings[i].Name) | |
| 1195 | + alias := strings.TrimSpace(mappings[i].Alias) | |
| 1196 | + if name == "" || alias == "" { | |
| 1228 | 1197 | continue |
| 1229 | 1198 | } |
| 1230 | − if strings.EqualFold(from, to) { | |
| 1199 | + if strings.EqualFold(name, alias) { | |
| 1231 | 1200 | continue |
| 1232 | 1201 | } |
| 1233 | − key := strings.ToLower(from) | |
| 1202 | + key := strings.ToLower(name) | |
| 1234 | 1203 | if _, exists := forward[key]; exists { |
| 1235 | 1204 | continue |
| 1236 | 1205 | } |
| 1237 | − forward[key] = to | |
| 1206 | + forward[key] = alias | |
| 1238 | 1207 | } |
| 1239 | 1208 | if len(forward) == 0 { |
| 1240 | 1209 | return models |