mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 13:00:52 +08:00
Fixed: #936
feat(cliproxy): support multiple aliases for OAuth model mappings - Updated mapping logic to allow multiple aliases per upstream model name. - Adjusted `SanitizeOAuthModelMappings` to ensure aliases remain unique within channels. - Added test cases to validate multi-alias scenarios. - Updated example config to clarify multi-alias support.
This commit is contained in:
@@ -1237,7 +1237,7 @@ func applyOAuthModelMappings(cfg *config.Config, provider, authKind string, mode
|
||||
fork bool
|
||||
}
|
||||
|
||||
forward := make(map[string]mappingEntry, len(mappings))
|
||||
forward := make(map[string][]mappingEntry, len(mappings))
|
||||
for i := range mappings {
|
||||
name := strings.TrimSpace(mappings[i].Name)
|
||||
alias := strings.TrimSpace(mappings[i].Alias)
|
||||
@@ -1248,14 +1248,12 @@ func applyOAuthModelMappings(cfg *config.Config, provider, authKind string, mode
|
||||
continue
|
||||
}
|
||||
key := strings.ToLower(name)
|
||||
if _, exists := forward[key]; exists {
|
||||
continue
|
||||
}
|
||||
forward[key] = mappingEntry{alias: alias, fork: mappings[i].Fork}
|
||||
forward[key] = append(forward[key], mappingEntry{alias: alias, fork: mappings[i].Fork})
|
||||
}
|
||||
if len(forward) == 0 {
|
||||
return models
|
||||
}
|
||||
|
||||
out := make([]*ModelInfo, 0, len(models))
|
||||
seen := make(map[string]struct{}, len(models))
|
||||
for _, model := range models {
|
||||
@@ -1267,17 +1265,8 @@ func applyOAuthModelMappings(cfg *config.Config, provider, authKind string, mode
|
||||
continue
|
||||
}
|
||||
key := strings.ToLower(id)
|
||||
entry, ok := forward[key]
|
||||
if !ok {
|
||||
if _, exists := seen[key]; exists {
|
||||
continue
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
out = append(out, model)
|
||||
continue
|
||||
}
|
||||
mappedID := strings.TrimSpace(entry.alias)
|
||||
if mappedID == "" {
|
||||
entries := forward[key]
|
||||
if len(entries) == 0 {
|
||||
if _, exists := seen[key]; exists {
|
||||
continue
|
||||
}
|
||||
@@ -1286,11 +1275,29 @@ func applyOAuthModelMappings(cfg *config.Config, provider, authKind string, mode
|
||||
continue
|
||||
}
|
||||
|
||||
if entry.fork {
|
||||
keepOriginal := false
|
||||
for _, entry := range entries {
|
||||
if entry.fork {
|
||||
keepOriginal = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if keepOriginal {
|
||||
if _, exists := seen[key]; !exists {
|
||||
seen[key] = struct{}{}
|
||||
out = append(out, model)
|
||||
}
|
||||
}
|
||||
|
||||
addedAlias := false
|
||||
for _, entry := range entries {
|
||||
mappedID := strings.TrimSpace(entry.alias)
|
||||
if mappedID == "" {
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(mappedID, id) {
|
||||
continue
|
||||
}
|
||||
aliasKey := strings.ToLower(mappedID)
|
||||
if _, exists := seen[aliasKey]; exists {
|
||||
continue
|
||||
@@ -1302,24 +1309,16 @@ func applyOAuthModelMappings(cfg *config.Config, provider, authKind string, mode
|
||||
clone.Name = rewriteModelInfoName(clone.Name, id, mappedID)
|
||||
}
|
||||
out = append(out, &clone)
|
||||
continue
|
||||
addedAlias = true
|
||||
}
|
||||
|
||||
uniqueKey := strings.ToLower(mappedID)
|
||||
if _, exists := seen[uniqueKey]; exists {
|
||||
continue
|
||||
}
|
||||
seen[uniqueKey] = struct{}{}
|
||||
if mappedID == id {
|
||||
if !keepOriginal && !addedAlias {
|
||||
if _, exists := seen[key]; exists {
|
||||
continue
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
out = append(out, model)
|
||||
continue
|
||||
}
|
||||
clone := *model
|
||||
clone.ID = mappedID
|
||||
if clone.Name != "" {
|
||||
clone.Name = rewriteModelInfoName(clone.Name, id, mappedID)
|
||||
}
|
||||
out = append(out, &clone)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -56,3 +56,37 @@ func TestApplyOAuthModelMappings_ForkAddsAlias(t *testing.T) {
|
||||
t.Fatalf("expected forked model name %q, got %q", "models/g5", out[1].Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyOAuthModelMappings_ForkAddsMultipleAliases(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
OAuthModelMappings: map[string][]config.ModelNameMapping{
|
||||
"codex": {
|
||||
{Name: "gpt-5", Alias: "g5", Fork: true},
|
||||
{Name: "gpt-5", Alias: "g5-2", Fork: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
models := []*ModelInfo{
|
||||
{ID: "gpt-5", Name: "models/gpt-5"},
|
||||
}
|
||||
|
||||
out := applyOAuthModelMappings(cfg, "codex", "oauth", models)
|
||||
if len(out) != 3 {
|
||||
t.Fatalf("expected 3 models, got %d", len(out))
|
||||
}
|
||||
if out[0].ID != "gpt-5" {
|
||||
t.Fatalf("expected first model id %q, got %q", "gpt-5", out[0].ID)
|
||||
}
|
||||
if out[1].ID != "g5" {
|
||||
t.Fatalf("expected second model id %q, got %q", "g5", out[1].ID)
|
||||
}
|
||||
if out[1].Name != "models/g5" {
|
||||
t.Fatalf("expected forked model name %q, got %q", "models/g5", out[1].Name)
|
||||
}
|
||||
if out[2].ID != "g5-2" {
|
||||
t.Fatalf("expected third model id %q, got %q", "g5-2", out[2].ID)
|
||||
}
|
||||
if out[2].Name != "models/g5-2" {
|
||||
t.Fatalf("expected forked model name %q, got %q", "models/g5-2", out[2].Name)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user