feat: publish sanitized custom.97 source

This commit is contained in:
cneicy committed 2026-10-27 20:43:39 +08:00
1 parent 8e6ed0317b
commit 86c0276156
1022 files changed
+69903 -19207

No files matched your search

+39 -24
View File
@@ -57,7 +57,7 @@ func Distribute() func(c *gin.Context) {
service.AppendTaskPluginIdentityFilter(c, c.GetString("expected_task_plugin_key"))
modelRequest, shouldSelectChannel, err := getModelRequest(c)
if err != nil {
abortWithOpenAiMessage(c, http.StatusBadRequest, i18n.T(c, i18n.MsgDistributorInvalidRequest, map[string]any{"Error": err.Error()}))
abortWithOpenAiMessage(c, invalidRequestStatus(err), i18n.T(c, i18n.MsgDistributorInvalidRequest, map[string]any{"Error": err.Error()}))
return
}
requestedStream = modelRequest.Stream || strings.Contains(c.Request.URL.Path, "streamGenerateContent") || strings.EqualFold(c.GetHeader("Upgrade"), "websocket")
@@ -130,14 +130,7 @@ func Distribute() func(c *gin.Context) {
message = i18n.T(c, selectErr.MessageID, selectErr.Params)
}
if service.RequestRoutingPolicy(c) != nil && selectErr.NoAvailableChannel {
if c.GetBool("pool_degradation_unavailable") {
message = "Group quality checks are temporarily unavailable. Please retry later."
} else if wait := c.GetInt("pool_retry_after"); wait > 0 {
message = fmt.Sprintf("No eligible group is currently available; failed groups are cooling down or being checked. Retry after %d seconds.", wait)
c.Header("Retry-After", fmt.Sprint(wait))
} else {
message = "No eligible group is available for this model under the current pool and quality settings."
}
message = noAvailableGroupPoolMessage(c)
}
rejectionMessage = message
abortWithOpenAiMessage(c, selectErr.StatusCode, message, selectErr.Code)
@@ -157,6 +150,13 @@ func Distribute() func(c *gin.Context) {
}
}
func noAvailableGroupPoolMessage(c *gin.Context) string {
if wait := c.GetInt("pool_retry_after"); wait > 0 {
c.Header("Retry-After", fmt.Sprint(wait))
}
return "分组池中无条件内可用分组"
}
// noAvailableChannelMessage explains a 503 for a task-plugin-claimed model.
// The response tells the caller the model is plugin-claimed without naming the
// plugin; the candidate plugin keys go to the server log under the request id.
@@ -175,7 +175,7 @@ func noAvailableChannelMessage(c *gin.Context, group, modelName string) string {
}
}
}
logger.LogWarn(c, "task_plugin subsystem=distribution event=no_available_channel group=%q model=%q plugins=%q reason=no_eligible_channel", group, modelName, strings.Join(keys, ","))
logger.LogWarn(c, common.LogText("task_plugin subsystem=distribution event=no_available_channel group=%q model=%q plugins=%q reason=no_eligible_channel", group, modelName, strings.Join(keys, ",")))
return i18n.T(c, i18n.MsgDistributorNoAvailableChannelTaskPlugin, map[string]any{"Group": group, "Model": modelName})
}
return i18n.T(c, i18n.MsgDistributorNoAvailableChannel, map[string]any{"Group": group, "Model": modelName})
@@ -190,11 +190,11 @@ func channelMatchesExpectedTaskPlugin(c *gin.Context, channel *model.Channel, ex
return true
}
}
if channel.Type == constant.ChannelTypeTaskPlugin {
return expected != "" && channel.GetSetting().TaskPluginKey == expected
}
if expected == "" {
return true
return channel.Type != constant.ChannelTypeTaskPlugin
}
if channel.Type == constant.ChannelTypeTaskPlugin || channel.Type == constant.ChannelTypeNewAPI {
return channel.GetSetting().BindsTaskPlugin(expected)
}
if c == nil {
@@ -224,6 +224,7 @@ func pinnedEndpointCandidateForChannel(c *gin.Context, channel *model.Channel, e
}
expectedOwned := false
selected := jsplugin.ProtocolBinding{}
setting := channel.GetSetting()
for _, candidate := range candidates {
if candidate.Plugin == nil {
continue
@@ -231,8 +232,12 @@ func pinnedEndpointCandidateForChannel(c *gin.Context, channel *model.Channel, e
if candidate.Plugin.Meta.Key == expected {
expectedOwned = true
}
if channel.Type == constant.ChannelTypeTaskPlugin {
if channel.GetSetting().TaskPluginKey == candidate.Plugin.Meta.Key {
if channel.Type == constant.ChannelTypeTaskPlugin || channel.Type == constant.ChannelTypeNewAPI {
// A New API channel may bind several candidates. The first bound
// candidate in generation order executes, so the billing provider
// depends only on the channel and the request, never on which
// channels an earlier retry attempt happened to try.
if selected.Plugin == nil && setting.BindsTaskPlugin(candidate.Plugin.Meta.Key) {
selected = candidate
}
continue
@@ -258,17 +263,13 @@ func getModelFromRequest(c *gin.Context) (*ModelRequest, error) {
}
}
if strings.HasPrefix(c.Request.Header.Get("Content-Type"), "application/json") {
modelRequest, err := getModelFromJSONBody(c)
if err != nil {
return nil, errors.New(i18n.T(c, i18n.MsgDistributorInvalidRequest, map[string]any{"Error": err.Error()}))
}
return modelRequest, nil
return getModelFromJSONBody(c)
}
var modelRequest ModelRequest
err := common.UnmarshalBodyReusable(c, &modelRequest)
if err != nil {
return nil, errors.New(i18n.T(c, i18n.MsgDistributorInvalidRequest, map[string]any{"Error": err.Error()}))
return nil, err
}
return &modelRequest, nil
}
@@ -402,7 +403,7 @@ func getModelRequest(c *gin.Context) (*ModelRequest, bool, error) {
midjourneyRequest := taskdto.MidjourneyRequest{}
err = common.UnmarshalBodyReusable(c, &midjourneyRequest)
if err != nil {
return nil, false, errors.New(i18n.T(c, i18n.MsgDistributorInvalidMidjourney, map[string]any{"Error": err.Error()}))
return nil, false, err
}
midjourneyModel, mjErr, success := service.GetMjRequestModel(relayMode, &midjourneyRequest)
if mjErr != nil {
@@ -491,6 +492,13 @@ func getModelRequest(c *gin.Context) (*ModelRequest, bool, error) {
modelRequest.Model = c.Param("model")
}
}
// The routing name is also the billing name, so a model named in the body
// must not replace it: DeepSeek ignores that field.
if strings.HasPrefix(c.Request.URL.Path, "/v1/tools/search") {
modelRequest.Model = constant.DeepSeekSearchModel
} else if strings.HasPrefix(c.Request.URL.Path, "/v1/tools/fetch") {
modelRequest.Model = constant.DeepSeekFetchModel
}
if strings.HasPrefix(c.Request.URL.Path, "/v1/images/generations") {
modelRequest.Model = common.GetStringIfEmpty(modelRequest.Model, "dall-e")
} else if strings.HasPrefix(c.Request.URL.Path, "/v1/images/edits") {
@@ -620,8 +628,15 @@ func SetupContextForSelectedChannel(c *gin.Context, channel *model.Channel, mode
common.SetContextKey(c, constant.ContextKeyChannelCreateTime, channel.CreatedTime)
common.SetContextKey(c, constant.ContextKeyChannelSetting, channel.GetSetting())
common.SetContextKey(c, constant.ContextKeyChannelOtherSetting, channel.GetOtherSettings())
if channel.Type == constant.ChannelTypeTaskPlugin {
switch channel.Type {
case constant.ChannelTypeTaskPlugin:
c.Set("task_plugin_key", channel.GetSetting().TaskPluginKey)
case constant.ChannelTypeNewAPI:
// The bound plugin verified above executes; ordinary requests through
// the same gateway channel carry no pinned plugin.
if executing := c.GetString("expected_task_plugin_key"); executing != "" {
c.Set("task_plugin_key", executing)
}
}
logTaskPluginChannelDecision(c, channel, modelName, "channel_selected", "")
paramOverride := channel.GetParamOverride()