Files
new-api/relay/relay_adaptor.go
T

236 lines
8.9 KiB
Go

package relay
import (
"fmt"
"strconv"
"github.com/QuantumNous/new-api/constant"
pluginruntime "github.com/QuantumNous/new-api/pkg/jsplugin"
_ "github.com/QuantumNous/new-api/plugins"
"github.com/QuantumNous/new-api/relay/channel"
"github.com/QuantumNous/new-api/relay/channel/advancedcustom"
"github.com/QuantumNous/new-api/relay/channel/ali"
"github.com/QuantumNous/new-api/relay/channel/aws"
"github.com/QuantumNous/new-api/relay/channel/baidu"
"github.com/QuantumNous/new-api/relay/channel/baidu_v2"
"github.com/QuantumNous/new-api/relay/channel/claude"
"github.com/QuantumNous/new-api/relay/channel/cloudflare"
"github.com/QuantumNous/new-api/relay/channel/codex"
"github.com/QuantumNous/new-api/relay/channel/cohere"
"github.com/QuantumNous/new-api/relay/channel/coze"
"github.com/QuantumNous/new-api/relay/channel/deepseek"
"github.com/QuantumNous/new-api/relay/channel/dify"
"github.com/QuantumNous/new-api/relay/channel/gemini"
"github.com/QuantumNous/new-api/relay/channel/jimeng"
"github.com/QuantumNous/new-api/relay/channel/jina"
"github.com/QuantumNous/new-api/relay/channel/minimax"
"github.com/QuantumNous/new-api/relay/channel/mistral"
"github.com/QuantumNous/new-api/relay/channel/mokaai"
"github.com/QuantumNous/new-api/relay/channel/moonshot"
"github.com/QuantumNous/new-api/relay/channel/newapi"
"github.com/QuantumNous/new-api/relay/channel/ollama"
"github.com/QuantumNous/new-api/relay/channel/openai"
"github.com/QuantumNous/new-api/relay/channel/palm"
"github.com/QuantumNous/new-api/relay/channel/perplexity"
"github.com/QuantumNous/new-api/relay/channel/replicate"
"github.com/QuantumNous/new-api/relay/channel/siliconflow"
"github.com/QuantumNous/new-api/relay/channel/sub2api"
"github.com/QuantumNous/new-api/relay/channel/submodel"
jspluginadaptor "github.com/QuantumNous/new-api/relay/channel/task/jsplugin"
"github.com/QuantumNous/new-api/relay/channel/tencent"
"github.com/QuantumNous/new-api/relay/channel/vertex"
"github.com/QuantumNous/new-api/relay/channel/volcengine"
"github.com/QuantumNous/new-api/relay/channel/xai"
"github.com/QuantumNous/new-api/relay/channel/xunfei"
"github.com/QuantumNous/new-api/relay/channel/zhipu"
"github.com/QuantumNous/new-api/relay/channel/zhipu_4v"
"github.com/gin-gonic/gin"
)
func GetAdaptor(apiType int) channel.Adaptor {
switch apiType {
case constant.APITypeAli:
return &ali.Adaptor{}
case constant.APITypeAnthropic:
return &claude.Adaptor{}
case constant.APITypeBaidu:
return &baidu.Adaptor{}
case constant.APITypeGemini:
return &gemini.Adaptor{}
case constant.APITypeOpenAI:
return &openai.Adaptor{}
case constant.APITypePaLM:
return &palm.Adaptor{}
case constant.APITypeTencent:
return &tencent.DispatchAdaptor{}
case constant.APITypeXunfei:
return &xunfei.Adaptor{}
case constant.APITypeZhipu:
return &zhipu.Adaptor{}
case constant.APITypeZhipuV4:
return &zhipu_4v.Adaptor{}
case constant.APITypeOllama:
return &ollama.Adaptor{}
case constant.APITypePerplexity:
return &perplexity.Adaptor{}
case constant.APITypeAws:
return &aws.Adaptor{}
case constant.APITypeCohere:
return &cohere.Adaptor{}
case constant.APITypeDify:
return &dify.Adaptor{}
case constant.APITypeJina:
return &jina.Adaptor{}
case constant.APITypeCloudflare:
return &cloudflare.Adaptor{}
case constant.APITypeSiliconFlow:
return &siliconflow.Adaptor{}
case constant.APITypeVertexAi:
return &vertex.Adaptor{}
case constant.APITypeMistral:
return &mistral.Adaptor{}
case constant.APITypeDeepSeek:
return &deepseek.Adaptor{}
case constant.APITypeMokaAI:
return &mokaai.Adaptor{}
case constant.APITypeVolcEngine:
return &volcengine.Adaptor{}
case constant.APITypeBaiduV2:
return &baidu_v2.Adaptor{}
case constant.APITypeOpenRouter:
return &openai.Adaptor{}
case constant.APITypeXinference:
return &openai.Adaptor{}
case constant.APITypeXai:
return &xai.Adaptor{}
case constant.APITypeCoze:
return &coze.Adaptor{}
case constant.APITypeJimeng:
return &jimeng.Adaptor{}
case constant.APITypeMoonshot:
return &moonshot.Adaptor{} // Moonshot uses Claude API
case constant.APITypeSubmodel:
return &submodel.Adaptor{}
case constant.APITypeMiniMax:
return &minimax.Adaptor{}
case constant.APITypeReplicate:
return &replicate.Adaptor{}
case constant.APITypeCodex:
return &codex.Adaptor{}
case constant.APITypeAdvancedCustom:
return &advancedcustom.Adaptor{}
case constant.APITypeSub2API:
return &sub2api.Adaptor{}
case constant.APITypeNewAPI:
return &newapi.Adaptor{}
}
return nil
}
func GetTaskPlatform(c *gin.Context) constant.TaskPlatform {
if pluginKey := c.GetString("task_plugin_key"); pluginKey != "" {
return constant.TaskPlatform(pluginKey)
}
channelType := c.GetInt("channel_type")
if channelType > 0 {
return constant.TaskPlatform(strconv.Itoa(channelType))
}
return constant.TaskPlatform(c.GetString("platform"))
}
var taskPluginKeys = map[constant.TaskPlatform]string{
constant.TaskPlatformSuno: "sunoapi",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeAli)): "alibaba",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeKling)): "kling",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeJimeng)): "jimeng",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeVidu)): "vidu",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeDoubaoVideo)): "doubao",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeVolcEngine)): "doubao",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeGemini)): "google",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeMiniMax)): "hailuo",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeSora)): "sora",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeOpenAI)): "sora",
constant.TaskPlatform(strconv.Itoa(constant.ChannelTypeVertexAi)): "vertex-ai",
}
func ResolveTaskPluginForPlatform(generation *pluginruntime.RoutingGeneration, platform constant.TaskPlatform) (*pluginruntime.LoadedPlugin, bool) {
if generation == nil {
return nil, false
}
if key, ok := taskPluginKeys[platform]; ok {
if plugin, found := generation.Get(key); found {
return plugin, true
}
}
return generation.Get(string(platform))
}
// TaskPlatformUnavailableError explains why no adaptor serves the platform:
// the task-plugin system is switched off, the resolved plugin is disabled,
// or the platform simply names nothing. The distinction is user-actionable,
// so it must survive into the client-facing message.
func TaskPlatformUnavailableError(platform constant.TaskPlatform) (string, string) {
if !pluginruntime.DefaultRegistry.Enabled() {
return "task_plugin_system_disabled", "the task plugin system is disabled on this gateway"
}
key := string(platform)
if mapped, ok := taskPluginKeys[platform]; ok {
key = mapped
}
for _, meta := range pluginruntime.DefaultRegistry.Snapshot().Factory {
if meta.Key == key {
return "task_plugin_disabled", fmt.Sprintf("task plugin %q is disabled on this gateway", key)
}
}
return "invalid_api_platform", fmt.Sprintf("invalid api platform: %s", platform)
}
func GetTaskAdaptor(platform constant.TaskPlatform) channel.TaskAdaptor {
plugin, ok := ResolveTaskPluginForPlatform(pluginruntime.DefaultRegistry.Generation(), platform)
if !ok {
return nil
}
return jspluginadaptor.New(plugin)
}
// getTaskAdaptorForRequest preserves the exact plugin object pinned by the
// declarative or shared-endpoint router. Legacy task routes are pinned here
// from one registry generation before the adaptor is returned.
func getTaskAdaptorForRequest(c *gin.Context, platform constant.TaskPlatform) (constant.TaskPlatform, channel.TaskAdaptor) {
if c != nil {
if value, exists := c.Get(pluginruntime.ContextKeyPinnedPlugin); exists {
if pinned, ok := value.(pluginruntime.PinnedPlugin); ok && pinned.Plugin != nil {
platform = constant.TaskPlatform(pinned.Plugin.Meta.Key)
return platform, jspluginadaptor.New(pinned.Plugin)
}
return platform, nil
}
if value, exists := c.Get(pluginruntime.ContextKeyPinnedEndpoint); exists {
if pinned, ok := value.(pluginruntime.PinnedEndpoint); ok && pinned.Plugin != nil {
platform = constant.TaskPlatform(pinned.Plugin.Meta.Key)
return platform, jspluginadaptor.New(pinned.Plugin)
}
return platform, nil
}
if value, exists := c.Get(pluginruntime.ContextKeyPinnedRoute); exists {
if pinned, ok := value.(pluginruntime.PinnedRoute); ok && pinned.Plugin != nil {
platform = constant.TaskPlatform(pinned.Plugin.Meta.Key)
return platform, jspluginadaptor.New(pinned.Plugin)
}
return platform, nil
}
}
generation := pluginruntime.DefaultRegistry.Generation()
plugin, ok := ResolveTaskPluginForPlatform(generation, platform)
if !ok {
return platform, nil
}
if c != nil {
c.Set(pluginruntime.ContextKeyPinnedPlugin, pluginruntime.PinnedPlugin{
Generation: generation,
Plugin: plugin,
})
}
return platform, jspluginadaptor.New(plugin)
}