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

+134 -105
View File
@@ -3,6 +3,7 @@ package middleware
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
@@ -19,6 +20,7 @@ import (
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/constant"
"github.com/QuantumNous/new-api/dto"
"github.com/QuantumNous/new-api/i18n"
"github.com/QuantumNous/new-api/logger"
"github.com/QuantumNous/new-api/model"
pluginruntime "github.com/QuantumNous/new-api/pkg/jsplugin"
@@ -77,11 +79,12 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if err != nil {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=invalid_request",
generation,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=invalid_request err=%q",
generation,
pinned.Plugin.Meta.Key,
err.Error()),
)
status := http.StatusBadRequest
status := invalidRequestStatus(err)
if errors.Is(err, errTaskPluginUnsupportedMediaType) {
status = http.StatusUnsupportedMediaType
}
@@ -93,10 +96,10 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if pinned.Route.Type == pluginruntime.RouteTypeQuery && bodyKind != string(pluginruntime.BodyNone) || pinned.Route.Type != pluginruntime.RouteTypeQuery && bodyKind != string(pluginruntime.BodyJSON) {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=body_kind_mismatch body_kind=%q",
generation,
pinned.Plugin.Meta.Key,
bodyKind,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=body_kind_mismatch body_kind=%q",
generation,
pinned.Plugin.Meta.Key,
bodyKind),
)
detail := "this route requires a JSON body"
if pinned.Route.Type == pluginruntime.RouteTypeQuery {
@@ -124,10 +127,10 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if claimedModel == "" || !slices.Contains(pinned.Route.Models, claimedModel) {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=model_not_allowed model=%q",
generation,
pinned.Plugin.Meta.Key,
claimedModel,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=model_not_allowed model=%q",
generation,
pinned.Plugin.Meta.Key,
claimedModel),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, fmt.Sprintf("model %q is not allowed on this route", claimedModel))
return
@@ -135,15 +138,18 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
}
hookStarted := time.Now()
resolvedValue, err := pinned.Plugin.Engine.CallMember(c.Request.Context(), "native", pinned.Route.Decode, requestContext.JSValue())
resolvedValue, requestBodyText, err := pinned.Plugin.Engine.CallPathWithMemberJSON(
c.Request.Context(), 0, pinned.Plugin.Meta.JSONTextMember("requestBody"),
"native", []string{pinned.Route.Decode}, requestContext.JSValueFor(pinned.Plugin.Meta),
)
if err != nil {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=hook_failed err=%q elapsed_ms=%d",
generation,
pinned.Plugin.Meta.Key,
err.Error(),
time.Since(hookStarted).Milliseconds(),
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=hook_failed err=%q elapsed_ms=%d",
generation,
pinned.Plugin.Meta.Key,
err.Error(),
time.Since(hookStarted).Milliseconds()),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, taskPluginHookDetail(err))
return
@@ -152,10 +158,10 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if !ok {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=result_not_object elapsed_ms=%d",
generation,
pinned.Plugin.Meta.Key,
time.Since(hookStarted).Milliseconds(),
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=result_not_object elapsed_ms=%d",
generation,
pinned.Plugin.Meta.Key,
time.Since(hookStarted).Milliseconds()),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, taskPluginInvalidRouteResult)
return
@@ -164,16 +170,16 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if !ok {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=missing_kind elapsed_ms=%d",
generation,
pinned.Plugin.Meta.Key,
time.Since(hookStarted).Milliseconds(),
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=missing_kind elapsed_ms=%d",
generation,
pinned.Plugin.Meta.Key,
time.Since(hookStarted).Milliseconds()),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, taskPluginInvalidRouteResult)
return
}
if _, forbidden := resolved["renderer"]; forbidden {
logger.LogWarn(c, "task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=forbidden_renderer", generation, pinned.Plugin.Meta.Key)
logger.LogWarn(c, common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=forbidden_renderer", generation, pinned.Plugin.Meta.Key))
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, taskPluginInvalidRouteResult)
return
}
@@ -184,9 +190,9 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if !valid || strings.TrimSpace(modelName) == "" {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=invalid_model",
generation,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=invalid_model",
generation,
pinned.Plugin.Meta.Key),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, "decoded request is missing a model")
return
@@ -195,10 +201,10 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if !owned {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=model_not_owned model=%q",
generation,
pinned.Plugin.Meta.Key,
modelName,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=model_not_owned model=%q",
generation,
pinned.Plugin.Meta.Key,
modelName),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, fmt.Sprintf("model %q is not served by this plugin", modelName))
return
@@ -206,10 +212,10 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if len(pinned.Route.Models) > 0 && !slices.Contains(pinned.Route.Models, modelName) {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=resolved_model_not_allowed model=%q",
generation,
pinned.Plugin.Meta.Key,
modelName,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=resolved_model_not_allowed model=%q",
generation,
pinned.Plugin.Meta.Key,
modelName),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, fmt.Sprintf("model %q is not allowed on this route", modelName))
return
@@ -220,9 +226,9 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if !actionOK {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=invalid_action",
generation,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=invalid_action",
generation,
pinned.Plugin.Meta.Key),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, taskPluginInvalidRouteResult)
return
@@ -236,6 +242,9 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
c.Set(pluginruntime.ContextKeyRouteRequest, requestContext)
}
c.Set("task_request", requestContext.RequestBody)
if requestBodyText != nil {
c.Set(pluginruntime.ContextKeyRequestBodyText, requestBodyText)
}
c.Set("resolved_task_model", modelName)
c.Set("expected_task_plugin_key", pinned.Plugin.Meta.Key)
c.Set("task_plugin_key", pinned.Plugin.Meta.Key)
@@ -248,10 +257,10 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if intentErr := applyOriginTaskIntent(c, resolved, pinned.Plugin.Meta); intentErr != nil {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=origin_task reason=%s",
generation,
pinned.Plugin.Meta.Key,
intentErr.Code,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=origin_task reason=%s",
generation,
pinned.Plugin.Meta.Key,
intentErr.Code),
)
abortTaskPluginRouteErrorDetail(c, intentErr.StatusCode, intentErr.Message)
return
@@ -272,9 +281,9 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if pinned.Route.Type != pluginruntime.RouteTypeDynamic {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=query_from_non_dynamic_route",
generation,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=query_from_non_dynamic_route",
generation,
pinned.Plugin.Meta.Key),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, taskPluginInvalidRouteResult)
return
@@ -283,9 +292,9 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
if !valid {
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=invalid_query_result",
generation,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=invalid_query_result",
generation,
pinned.Plugin.Meta.Key),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, taskPluginInvalidRouteResult)
return
@@ -303,9 +312,9 @@ func PrepareTaskPluginRoute() gin.HandlerFunc {
default:
logger.LogWarn(
c,
"task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=unsupported_kind",
generation,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=route event=prepare_rejected generation=%d plugin=%q stage=resolve_request reason=unsupported_kind",
generation,
pinned.Plugin.Meta.Key),
)
abortTaskPluginRouteErrorDetail(c, http.StatusBadRequest, taskPluginInvalidRouteResult)
}
@@ -326,7 +335,7 @@ func PinTaskPluginEndpoint() gin.HandlerFunc {
modelRequest, err := getModelFromRequest(c)
if err != nil {
if _, _, protocolPath := pluginruntime.LookupHostProtocolOperation(c.Request.Method, c.Request.URL.Path); protocolPath {
abortWithOpenAiMessage(c, http.StatusBadRequest, "Invalid task protocol request")
abortWithOpenAiMessage(c, invalidRequestStatus(err), i18n.T(c, i18n.MsgDistributorInvalidRequest, map[string]any{"Error": err.Error()}))
return
}
c.Next()
@@ -525,9 +534,9 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
if !pluginruntime.SupportsHostProtocol(pinned.Protocol) {
logger.LogWarn(
c,
"task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=protocol_check reason=unsupported_protocol",
pinned.Generation.Number,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=protocol_check reason=unsupported_protocol",
pinned.Generation.Number,
pinned.Plugin.Meta.Key),
)
abortWithOpenAiMessage(c, http.StatusNotImplemented, "Task protocol bridge is not available")
return
@@ -536,9 +545,9 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
if err != nil {
logger.LogWarn(
c,
"task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=invalid_request",
pinned.Generation.Number,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=invalid_request",
pinned.Generation.Number,
pinned.Plugin.Meta.Key),
)
status := http.StatusBadRequest
if errors.Is(err, errTaskPluginUnsupportedMediaType) {
@@ -566,10 +575,10 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
if !allowedBody {
logger.LogWarn(
c,
"task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=body_kind_mismatch body_kind=%q",
pinned.Generation.Number,
pinned.Plugin.Meta.Key,
bodyKind,
common.LogText("task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=body_kind_mismatch body_kind=%q",
pinned.Generation.Number,
pinned.Plugin.Meta.Key,
bodyKind),
)
detail := "unsupported request body for this operation"
if len(pinned.Operation.BodyKinds) == 1 && pinned.Operation.BodyKinds[0] == pluginruntime.BodyJSON {
@@ -586,9 +595,9 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
if !ok {
logger.LogWarn(
c,
"task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=invalid_stream_flag",
pinned.Generation.Number,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=request_decode reason=invalid_stream_flag",
pinned.Generation.Number,
pinned.Plugin.Meta.Key),
)
abortWithOpenAiMessage(c, http.StatusBadRequest, "stream must be a boolean")
return
@@ -610,6 +619,7 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
}
accepted := make([]pluginruntime.ProtocolBinding, 0, len(candidates))
var resolved map[string]any
var resolvedBodyText json.RawMessage
var failures []string
rejectedPlugins := make(map[string][]string)
for _, candidate := range candidates {
@@ -618,9 +628,10 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
candidateContext.Operation = candidate.Operation.Name
// Parsing belongs to durable submission; disconnecting only stops
// the later Responses observation.
resolvedValue, callErr := candidate.Plugin.Engine.CallPathWithAdmissionTimeout(
resolvedValue, requestBodyText, callErr := candidate.Plugin.Engine.CallPathWithMemberJSON(
context.WithoutCancel(c.Request.Context()), pluginruntime.DefaultCallTimeout,
"protocols", []string{candidate.Protocol, "decodeRequest"}, candidateContext.JSValue(),
candidate.Plugin.Meta.JSONTextMember("requestBody"),
"protocols", []string{candidate.Protocol, "decodeRequest"}, candidateContext.JSValueFor(candidate.Plugin.Meta),
)
result, resultOK := resolvedValue.(map[string]any)
detail := ""
@@ -645,8 +656,8 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
detail = fmt.Sprintf("model %q is not served by this plugin", model)
}
if detail != "" {
logger.LogWarn(c, "task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=parse_request reason=%s err=%q elapsed_ms=%d",
pinned.Generation.Number, candidate.Plugin.Meta.Key, reason, detail, time.Since(hookStarted).Milliseconds())
logger.LogWarn(c, common.LogText("task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=parse_request reason=%s err=%q elapsed_ms=%d",
pinned.Generation.Number, candidate.Plugin.Meta.Key, reason, detail, time.Since(hookStarted).Milliseconds()))
if _, seen := rejectedPlugins[detail]; !seen {
failures = append(failures, detail)
}
@@ -656,6 +667,7 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
accepted = append(accepted, candidate)
if resolved == nil {
resolved = result
resolvedBodyText = requestBodyText
protocolContext = candidateContext
}
}
@@ -683,9 +695,9 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
if !ok {
logger.LogWarn(
c,
"task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=parse_request reason=invalid_action",
pinned.Generation.Number,
pinned.Plugin.Meta.Key,
common.LogText("task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=parse_request reason=invalid_action",
pinned.Generation.Number,
pinned.Plugin.Meta.Key),
)
abortWithOpenAiMessage(c, http.StatusBadRequest, taskPluginInvalidRouteResult)
return
@@ -697,6 +709,9 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
}
c.Set(pluginruntime.ContextKeyRouteRequest, requestContext)
c.Set("task_request", requestContext.RequestBody)
if resolvedBodyText != nil {
c.Set(pluginruntime.ContextKeyRequestBodyText, resolvedBodyText)
}
c.Set("resolved_task_model", resolvedModel)
c.Set("expected_task_plugin_key", pinned.Plugin.Meta.Key)
c.Set("task_plugin_key", pinned.Plugin.Meta.Key)
@@ -709,10 +724,10 @@ func PrepareTaskPluginEndpoint() gin.HandlerFunc {
if intentErr := applyOriginTaskIntent(c, resolved, pinned.Plugin.Meta); intentErr != nil {
logger.LogWarn(
c,
"task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=origin_task reason=%s",
pinned.Generation.Number,
pinned.Plugin.Meta.Key,
intentErr.Code,
common.LogText("task_plugin subsystem=endpoint event=prepare_rejected generation=%d plugin=%q stage=origin_task reason=%s",
pinned.Generation.Number,
pinned.Plugin.Meta.Key,
intentErr.Code),
)
abortWithOpenAiMessage(c, intentErr.StatusCode, intentErr.Message, types.ErrorCode(intentErr.Code))
return
@@ -791,6 +806,9 @@ func buildTaskPluginRouteRequest(c *gin.Context) (pluginruntime.RouteRequestCont
return requestContext, err
}
requestContext.Body = map[string]any{"kind": string(pluginruntime.BodyJSON), "value": value}
// Body storage never changes its bytes in place (a rewrite stores a
// new copy), so the text needs no copy of its own.
requestContext.BodyText = raw
case mediaType == "application/x-www-form-urlencoded":
storage, storageErr := common.GetBodyStorage(c)
if storageErr != nil {
@@ -933,7 +951,7 @@ func buildTaskPluginRouteRequest(c *gin.Context) (pluginruntime.RouteRequestCont
if !utf8.ValidString(field) || len(field) > maxTaskPluginFieldNameBytes {
return requestContext, fmt.Errorf("invalid multipart file field name")
}
for _, header := range headers {
for index, header := range headers {
if !utf8.ValidString(header.Filename) || len(header.Filename) > maxTaskPluginFilenameBytes {
return requestContext, fmt.Errorf("invalid multipart filename")
}
@@ -947,7 +965,7 @@ func buildTaskPluginRouteRequest(c *gin.Context) (pluginruntime.RouteRequestCont
if header.Size < 0 || header.Size > int64(fileLimitMB)<<20 {
return requestContext, fmt.Errorf("multipart file exceeds %d MB", fileLimitMB)
}
ref := "request_file:" + field
ref := pluginruntime.FileReference(field, index)
files = append(files, map[string]any{"ref": ref, "field": field, "filename": header.Filename, "mimeType": header.Header.Get("Content-Type"), "size": header.Size})
}
}
@@ -1163,10 +1181,10 @@ func renderTaskPluginQuery(
for _, task := range tasks {
tasksByID[task.TaskID] = task
}
views := make([]map[string]any, 0, len(taskIDs))
views := make([]dto.TaskView, 0, len(taskIDs))
for _, taskID := range taskIDs {
task := tasksByID[taskID]
if task == nil {
if task == nil || !task.ResultRetrievable() {
logger.LogDebug(
c,
"task_plugin subsystem=query event=lookup_failed generation=%d plugin=%q reason=task_not_found requested=%d found=%d",
@@ -1183,25 +1201,20 @@ func renderTaskPluginQuery(
abortTaskPluginRouteError(c, http.StatusInternalServerError)
return
}
var viewValue map[string]any
encoded, marshalErr := common.Marshal(view)
if marshalErr != nil {
abortTaskPluginRouteError(c, http.StatusInternalServerError)
return
}
if unmarshalErr := common.Unmarshal(encoded, &viewValue); unmarshalErr != nil {
abortTaskPluginRouteError(c, http.StatusInternalServerError)
return
}
views = append(views, viewValue)
views = append(views, view)
}
var rendererInput any = views
if !multiple {
rendererInput = views[0]
}
encoded, err := common.Marshal(rendererInput)
if err != nil {
abortTaskPluginRouteError(c, http.StatusInternalServerError)
return
}
renderStarted := time.Now()
result, err := pinned.Plugin.Engine.CallPath(c.Request.Context(), "native", []string{renderer}, requestContext.JSValue(), rendererInput)
result, err := pinned.Plugin.Engine.CallPath(c.Request.Context(), "native", []string{renderer}, requestContext.JSValue(), pluginruntime.RawJSON(encoded))
if err != nil {
logger.LogDebug(
c,
@@ -1264,18 +1277,18 @@ func RespondTaskPluginError(c *gin.Context, taskErr *dto.TaskError) bool {
}
logger.LogWarn(
c,
"task_plugin subsystem=route event=error_renderer_failed plugin=%q reason=hook_failed status=%d err=%q",
pinned.Plugin.Meta.Key,
sanitized.HTTPStatus,
callErr.Error(),
common.LogText("task_plugin subsystem=route event=error_renderer_failed plugin=%q reason=hook_failed status=%d err=%q",
pinned.Plugin.Meta.Key,
sanitized.HTTPStatus,
callErr.Error()),
)
}
logger.LogWarn(
c,
"task_plugin subsystem=route event=error_rendered plugin=%q renderer=host_fallback status=%d code=%q",
pinned.Plugin.Meta.Key,
sanitized.HTTPStatus,
sanitized.Code,
common.LogText("task_plugin subsystem=route event=error_rendered plugin=%q renderer=host_fallback status=%d code=%q",
pinned.Plugin.Meta.Key,
sanitized.HTTPStatus,
sanitized.Code),
)
message := sanitized.Message
if requestID != "" {
@@ -1373,8 +1386,11 @@ func logTaskPluginChannelDecision(c *gin.Context, channel *model.Channel, modelN
return
}
identityMode := "legacy_channel_type"
if channel.Type == constant.ChannelTypeTaskPlugin {
switch channel.Type {
case constant.ChannelTypeTaskPlugin:
identityMode = "type59_setting"
case constant.ChannelTypeNewAPI:
identityMode = "type60_setting"
}
logger.LogDebug(
c,
@@ -1412,7 +1428,7 @@ func PrepareTaskPluginSubmit() gin.HandlerFunc {
)
var requestBody map[string]any
if err := common.UnmarshalBodyReusable(c, &requestBody); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": gin.H{"message": err.Error(), "type": "invalid_request_error"}})
c.AbortWithStatusJSON(invalidRequestStatus(err), gin.H{"error": gin.H{"message": err.Error(), "type": "invalid_request_error"}})
return
}
modelName, _ := requestBody["model"].(string)
@@ -1442,6 +1458,19 @@ func PrepareTaskPluginSubmit() gin.HandlerFunc {
}
}
c.Set("task_request", requestBody)
if plugin.Meta.PreservesJSONOrder() {
// The body as stored after any model rewrite: the text hooks get.
storage, err := common.GetBodyStorage(c)
var raw []byte
if err == nil {
raw, err = storage.Bytes()
}
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": gin.H{"message": err.Error(), "type": "invalid_request_error"}})
return
}
c.Set(pluginruntime.ContextKeyRequestBodyText, json.RawMessage(raw))
}
c.Set("resolved_task_model", modelName)
c.Set("expected_task_plugin_key", pluginKey)
service.AppendTaskPluginIdentityFilter(c, pluginKey)