2026-03-14 10:47:31 +08:00
|
|
|
package service
|
|
|
|
|
|
2026-04-24 07:42:31 +00:00
|
|
|
import "strings"
|
|
|
|
|
|
2026-04-04 14:07:19 +08:00
|
|
|
// resolveOpenAIForwardModel determines the upstream model for OpenAI-compatible
|
|
|
|
|
// forwarding. Group-level default mapping only applies when the account itself
|
|
|
|
|
// did not match any explicit model_mapping rule.
|
2026-03-14 10:47:31 +08:00
|
|
|
func resolveOpenAIForwardModel(account *Account, requestedModel, defaultMappedModel string) string {
|
|
|
|
|
if account == nil {
|
|
|
|
|
if defaultMappedModel != "" {
|
|
|
|
|
return defaultMappedModel
|
|
|
|
|
}
|
|
|
|
|
return requestedModel
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mappedModel, matched := account.ResolveMappedModel(requestedModel)
|
2026-04-24 07:42:31 +00:00
|
|
|
if !matched && defaultMappedModel != "" && !isExplicitCodexModel(requestedModel) {
|
2026-03-14 10:47:31 +08:00
|
|
|
return defaultMappedModel
|
|
|
|
|
}
|
|
|
|
|
return mappedModel
|
|
|
|
|
}
|
2026-04-24 07:42:31 +00:00
|
|
|
|
|
|
|
|
func isExplicitCodexModel(model string) bool {
|
|
|
|
|
model = strings.TrimSpace(model)
|
|
|
|
|
if model == "" {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
if strings.Contains(model, "/") {
|
|
|
|
|
parts := strings.Split(model, "/")
|
|
|
|
|
model = parts[len(parts)-1]
|
|
|
|
|
}
|
|
|
|
|
model = strings.ToLower(strings.TrimSpace(model))
|
|
|
|
|
if getNormalizedCodexModel(model) != "" {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
if strings.HasSuffix(model, "-openai-compact") {
|
|
|
|
|
base := strings.TrimSuffix(model, "-openai-compact")
|
|
|
|
|
return getNormalizedCodexModel(base) != ""
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
2026-04-25 14:40:03 +08:00
|
|
|
|
|
|
|
|
// resolveOpenAICompactForwardModel determines the compact-only upstream model
|
|
|
|
|
// for /responses/compact requests. It never affects normal /responses traffic.
|
|
|
|
|
// When no compact-specific mapping matches, the input model is returned as-is.
|
|
|
|
|
func resolveOpenAICompactForwardModel(account *Account, model string) string {
|
|
|
|
|
trimmedModel := strings.TrimSpace(model)
|
|
|
|
|
if trimmedModel == "" || account == nil {
|
|
|
|
|
return trimmedModel
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mappedModel, matched := account.ResolveCompactMappedModel(trimmedModel)
|
|
|
|
|
if !matched {
|
|
|
|
|
return trimmedModel
|
|
|
|
|
}
|
|
|
|
|
if trimmedMapped := strings.TrimSpace(mappedModel); trimmedMapped != "" {
|
|
|
|
|
return trimmedMapped
|
|
|
|
|
}
|
|
|
|
|
return trimmedModel
|
|
|
|
|
}
|