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

+49 -18
View File
@@ -12,6 +12,7 @@ import (
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/constant"
taskdto "github.com/QuantumNous/new-api/dto"
"github.com/QuantumNous/new-api/i18n"
"github.com/QuantumNous/new-api/logger"
"github.com/QuantumNous/new-api/middleware"
"github.com/QuantumNous/new-api/model"
@@ -126,7 +127,7 @@ func Relay(c *gin.Context, relayFormat types.RelayFormat) {
defer func() {
if newAPIError != nil {
service.RecordRequestPolicyTermination(c, newAPIError)
logger.LogError(c, fmt.Sprintf("relay error: %s", common.LocalLogPreview(newAPIError.Error())))
logger.LogError(c, common.LogText("relay error: %s", common.LocalLogPreview(newAPIError.Error())))
if c.GetBool("response_guard_error_sent") {
return
}
@@ -311,7 +312,7 @@ func Relay(c *gin.Context, relayFormat types.RelayFormat) {
useChannel := c.GetStringSlice("use_channel")
if len(useChannel) > 1 {
retryLogStr := fmt.Sprintf("重试:%s", strings.Trim(strings.Join(strings.Fields(fmt.Sprint(useChannel)), "->"), "[]"))
retryLogStr := common.LogText("retry: %s", strings.Trim(strings.Join(strings.Fields(fmt.Sprint(useChannel)), "->"), "[]"))
logger.LogInfo(c, retryLogStr)
}
}
@@ -391,10 +392,10 @@ func getChannel(c *gin.Context, info *relaycommon.RelayInfo, retryParam *service
}
channel, selectGroup, err := service.CacheGetRandomSatisfiedChannel(retryParam)
if err != nil {
return nil, types.NewError(fmt.Errorf("获取分组 %s 下模型 %s 的可用渠道失败(retry): %s", selectGroup, info.OriginModelName, err.Error()), types.ErrorCodeGetChannelFailed, types.ErrOptionWithSkipRetry())
return nil, types.NewError(errors.New(i18n.T(c, i18n.MsgRelayRetryGetChannelFailed, map[string]any{"Group": selectGroup, "Model": info.OriginModelName, "Error": err.Error()})), types.ErrorCodeGetChannelFailed, types.ErrOptionWithSkipRetry())
}
if channel == nil {
return nil, types.NewError(fmt.Errorf("分组 %s 下模型 %s 的可用渠道不存在(retry)", selectGroup, info.OriginModelName), types.ErrorCodeGetChannelFailed, types.ErrOptionWithSkipRetry())
return nil, types.NewError(errors.New(i18n.T(c, i18n.MsgRelayRetryNoAvailableChannel, map[string]any{"Group": selectGroup, "Model": info.OriginModelName})), types.ErrorCodeGetChannelFailed, types.ErrOptionWithSkipRetry())
}
info.PriceData.GroupRatioInfo = helper.HandleGroupRatio(c, info)
@@ -476,7 +477,7 @@ func RelayMidjourney(c *gin.Context) {
policy.Successful = false
statusCode := http.StatusBadRequest
if mjErr.Code == 30 {
mjErr.Result = "当前分组负载已饱和,请稍后再试,或升级账户以提升服务质量。"
mjErr.Result = i18n.T(c, i18n.MsgRelayGroupSaturated)
statusCode = http.StatusTooManyRequests
}
c.JSON(statusCode, gin.H{
@@ -485,7 +486,7 @@ func RelayMidjourney(c *gin.Context) {
"code": mjErr.Code,
})
channelId := c.GetInt("channel_id")
logger.LogError(c, fmt.Sprintf("relay error (channel #%d, status code %d): %s", channelId, statusCode, fmt.Sprintf("%s %s", mjErr.Description, mjErr.Result)))
logger.LogError(c, common.LogText("relay error (channel #%d, status code %d): %s", channelId, statusCode, fmt.Sprintf("%s %s", mjErr.Description, mjErr.Result)))
}
}
@@ -538,11 +539,14 @@ func RelayTaskPluginEndpoint(c *gin.Context, fallback gin.HandlerFunc) {
})
return
}
if pinned.Protocol != "openai_responses" {
switch pinned.Protocol {
case "openai_responses":
serveTaskPluginProtocol(c, pinned, defaultPluginProtocolBridgeDeps())
case pluginruntime.ProtocolOpenAIImage:
serveTaskPluginImageProtocol(c, pinned, defaultPluginProtocolBridgeDeps())
default:
fallback(c)
return
}
serveTaskPluginProtocol(c, pinned, defaultPluginProtocolBridgeDeps())
}
func RelayTaskFetch(c *gin.Context) {
@@ -715,7 +719,7 @@ func executeTaskSubmissionWith(
useChannel := c.GetStringSlice("use_channel")
if len(useChannel) > 1 {
retryLogStr := fmt.Sprintf("重试:%s", strings.Trim(strings.Join(strings.Fields(fmt.Sprint(useChannel)), "->"), "[]"))
retryLogStr := common.LogText("retry: %s", strings.Trim(strings.Join(strings.Fields(fmt.Sprint(useChannel)), "->"), "[]"))
logger.LogInfo(c, retryLogStr)
}
@@ -740,7 +744,7 @@ func executeTaskSubmissionWith(
stage = "reserve"
diagnostics.reserve("reserve_start", result.Quota)
if reserveErr := relayInfo.Billing.Reserve(result.Quota); reserveErr != nil {
common.SysError("reserve adjusted task billing error: " + reserveErr.Error())
common.SysError(common.LogText("reserve adjusted task billing error: %s", reserveErr.Error()))
taskErr = service.TaskErrorWrapperLocal(errors.New("insufficient quota for adjusted task cost"), string(types.ErrorCodeInsufficientUserQuota), http.StatusForbidden)
diagnostics.failed("reserve", "insufficient_quota", taskErr, false)
return nil, taskErr
@@ -790,9 +794,36 @@ func executeTaskSubmissionWith(
task.PrivateData.ResultURL = taskcommon.BuildProxyURL(task.TaskID)
}
}
// A native submit route may declare retainResult: false. It applies only
// to immediate terminal results: the client receives the complete response
// once, the upstream snapshot is never persisted, and the task is not
// retrievable afterwards. An asynchronous result on such a route keeps its
// snapshot because polling and retrieval need it. The OpenAI Images
// protocol delivers its images inline in the same HTTP response, so its
// immediate results follow the same rule; an asynchronous image task is
// expected there and is polled inside the request.
var insertOmits []string
immediateTerminal := result.Immediate != nil && (result.Immediate.Status == model.TaskStatusSuccess || result.Immediate.Status == model.TaskStatusFailure)
if pinnedValue, exists := c.Get(pluginruntime.ContextKeyPinnedRoute); exists {
pinned, ok := pinnedValue.(pluginruntime.PinnedRoute)
if ok && pinned.Route.RetainResult != nil && !*pinned.Route.RetainResult {
if immediateTerminal {
task.PrivateData.ResultDiscarded = true
insertOmits = append(insertOmits, "data")
} else {
logger.LogWarn(c, common.LogText("task plugin route %s %s declares retainResult: false but returned an asynchronous result; retaining task %s", pinned.Route.Method, pinned.Route.Path, task.TaskID))
}
}
}
if pinnedValue, exists := c.Get(pluginruntime.ContextKeyPinnedEndpoint); exists && immediateTerminal {
if pinned, ok := pinnedValue.(pluginruntime.PinnedEndpoint); ok && pinned.Protocol == pluginruntime.ProtocolOpenAIImage {
task.PrivateData.ResultDiscarded = true
insertOmits = append(insertOmits, "data")
}
}
diagnostics.insertStart(task)
if insertErr := task.InsertWithContext(c.Request.Context()); insertErr != nil {
common.SysError("insert task error: " + insertErr.Error())
if insertErr := task.InsertWithContext(c.Request.Context(), insertOmits...); insertErr != nil {
common.SysError(common.LogText("insert task error: %s", insertErr.Error()))
taskErr = service.TaskErrorWrapperLocal(errors.New("failed to persist task"), "task_insert_failed", http.StatusInternalServerError)
diagnostics.failed("insert", "database_error", taskErr, false)
return nil, taskErr
@@ -803,7 +834,7 @@ func executeTaskSubmissionWith(
diagnostics.settleStart(task, result.Quota)
if settleErr := service.SettleBilling(c, relayInfo, result.Quota); settleErr != nil {
common.SysError("settle task billing error: " + settleErr.Error())
common.SysError(common.LogText("settle task billing error: %s", settleErr.Error()))
taskErr = service.TaskErrorWrapperLocal(errors.New("failed to settle task billing"), "task_billing_settlement_failed", http.StatusInternalServerError)
diagnostics.failed("settle", "billing_error", taskErr, true)
return nil, taskErr
@@ -841,13 +872,13 @@ func presentTaskSubmission(c *gin.Context, outcome *taskSubmissionOutcome) {
c.JSON(http.StatusOK, body)
return
} else {
logger.LogError(c, "task plugin native submit presenter failed: "+callErr.Error())
logger.LogError(c, common.LogText("task plugin native submit presenter failed: %s", callErr.Error()))
}
} else {
logger.LogError(c, "encode task plugin native submit view failed: "+valueErr.Error())
logger.LogError(c, common.LogText("encode task plugin native submit view failed: %s", valueErr.Error()))
}
} else {
logger.LogError(c, "build task plugin native submit view failed: "+err.Error())
logger.LogError(c, common.LogText("build task plugin native submit view failed: %s", err.Error()))
}
}
}
@@ -884,7 +915,7 @@ func respondTaskSubmissionError(c *gin.Context, taskErr *taskdto.TaskError) {
// respondTaskError 统一输出 Task 错误响应(含 429 限流提示改写)
func respondTaskError(c *gin.Context, taskErr *taskdto.TaskError) {
if taskErr.StatusCode == http.StatusTooManyRequests {
taskErr.Message = "当前分组上游负载已饱和,请稍后再试"
taskErr.Message = i18n.T(c, i18n.MsgRelayGroupUpstreamSaturated)
}
c.JSON(taskErr.StatusCode, taskErr)
}