Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
123 lines
3.6 KiB
Go
123 lines
3.6 KiB
Go
package service
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/Wei-Shaw/sub2api/internal/pkg/xai"
|
|
)
|
|
|
|
const (
|
|
defaultOpenAIMessagesDispatchOpusMappedModel = "gpt-5.4"
|
|
defaultOpenAIMessagesDispatchSonnetMappedModel = "gpt-5.3-codex"
|
|
defaultOpenAIMessagesDispatchHaikuMappedModel = "gpt-5.4-mini"
|
|
)
|
|
|
|
func normalizeOpenAIMessagesDispatchMappedModel(model string) string {
|
|
model = NormalizeOpenAICompatRequestedModel(strings.TrimSpace(model))
|
|
return strings.TrimSpace(model)
|
|
}
|
|
|
|
func normalizeOpenAIMessagesDispatchModelConfig(cfg OpenAIMessagesDispatchModelConfig) OpenAIMessagesDispatchModelConfig {
|
|
out := OpenAIMessagesDispatchModelConfig{
|
|
OpusMappedModel: normalizeOpenAIMessagesDispatchMappedModel(cfg.OpusMappedModel),
|
|
SonnetMappedModel: normalizeOpenAIMessagesDispatchMappedModel(cfg.SonnetMappedModel),
|
|
HaikuMappedModel: normalizeOpenAIMessagesDispatchMappedModel(cfg.HaikuMappedModel),
|
|
}
|
|
|
|
if len(cfg.ExactModelMappings) > 0 {
|
|
out.ExactModelMappings = make(map[string]string, len(cfg.ExactModelMappings))
|
|
for requestedModel, mappedModel := range cfg.ExactModelMappings {
|
|
requestedModel = strings.TrimSpace(requestedModel)
|
|
mappedModel = normalizeOpenAIMessagesDispatchMappedModel(mappedModel)
|
|
if requestedModel == "" || mappedModel == "" {
|
|
continue
|
|
}
|
|
out.ExactModelMappings[requestedModel] = mappedModel
|
|
}
|
|
if len(out.ExactModelMappings) == 0 {
|
|
out.ExactModelMappings = nil
|
|
}
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
func claudeMessagesDispatchFamily(model string) string {
|
|
normalized := strings.ToLower(strings.TrimSpace(model))
|
|
if !strings.HasPrefix(normalized, "claude") {
|
|
return ""
|
|
}
|
|
switch {
|
|
case strings.Contains(normalized, "opus"):
|
|
return "opus"
|
|
case strings.Contains(normalized, "sonnet"):
|
|
return "sonnet"
|
|
case strings.Contains(normalized, "haiku"):
|
|
return "haiku"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func (g *Group) ResolveMessagesDispatchModel(requestedModel string) string {
|
|
if g == nil {
|
|
return ""
|
|
}
|
|
requestedModel = strings.TrimSpace(requestedModel)
|
|
if requestedModel == "" {
|
|
return ""
|
|
}
|
|
|
|
if g.Platform == PlatformGrok {
|
|
if claudeMessagesDispatchFamily(requestedModel) == "" {
|
|
return ""
|
|
}
|
|
opts := xai.RuntimeModelMappingOptions()
|
|
if !opts.EnableCrossClientMap {
|
|
return ""
|
|
}
|
|
return xai.ModelMappingWithOptions(opts)["claude-*"]
|
|
}
|
|
|
|
// 国产供应商分组:调度级模型映射不适用(其配置被 sanitize 置空,且下方的
|
|
// gpt-5.x 默认值是 openai 专属,发给 CN 上游必错)。模型改写完全交给账号级
|
|
// model_mapping;anthropic 协议上游本身接受 claude-* 模型名。
|
|
if IsCNProvider(g.Platform) {
|
|
return ""
|
|
}
|
|
|
|
cfg := normalizeOpenAIMessagesDispatchModelConfig(g.MessagesDispatchModelConfig)
|
|
if mappedModel := strings.TrimSpace(cfg.ExactModelMappings[requestedModel]); mappedModel != "" {
|
|
return mappedModel
|
|
}
|
|
|
|
switch claudeMessagesDispatchFamily(requestedModel) {
|
|
case "opus":
|
|
if mappedModel := strings.TrimSpace(cfg.OpusMappedModel); mappedModel != "" {
|
|
return mappedModel
|
|
}
|
|
return defaultOpenAIMessagesDispatchOpusMappedModel
|
|
case "sonnet":
|
|
if mappedModel := strings.TrimSpace(cfg.SonnetMappedModel); mappedModel != "" {
|
|
return mappedModel
|
|
}
|
|
return defaultOpenAIMessagesDispatchSonnetMappedModel
|
|
case "haiku":
|
|
if mappedModel := strings.TrimSpace(cfg.HaikuMappedModel); mappedModel != "" {
|
|
return mappedModel
|
|
}
|
|
return defaultOpenAIMessagesDispatchHaikuMappedModel
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func sanitizeGroupMessagesDispatchFields(g *Group) {
|
|
if g == nil || g.Platform == PlatformOpenAI {
|
|
return
|
|
}
|
|
g.AllowMessagesDispatch = false
|
|
g.DefaultMappedModel = ""
|
|
g.MessagesDispatchModelConfig = OpenAIMessagesDispatchModelConfig{}
|
|
}
|