mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-10-28 08:35:33 +08:00
When a task plugin claimed a model on a shared host endpoint (/v1/images/generations, /v1/images/edits, /v1/responses, /v1/videos), every request for that model went to the plugin, even when an ordinary OpenAI-compatible channel served the model too. Ordinary channels and the matching plugin channels now compete for the request under the usual group, priority, weight, affinity and channel-pin rules. When an ordinary channel wins, the original request reaches the ordinary relay unchanged: no plugin decoder, mode check or model rewrite runs, and retries stay on ordinary channels. When a plugin channel wins, the plugin handles the request as before and retries stay on its accepted plugin candidates. Native plugin routes still belong to their plugins. Ordinary and plugin prices are kept apart. Task expressions return USD, while ordinary expressions keep their USD-per-million result, so an ordinary request now fails with 400 model_price_error before any quota is reserved when the model's expression reads task usage (u()) or is still inherited by a task plugin on that endpoint. The model pricing editor can set ordinary OpenAI prices, per returned image with fixed(...) * image_count, while each plugin keeps its price in its own override. A model served by a single plugin now shows that plugin's pricing editor as well.
61 lines
2.7 KiB
Go
61 lines
2.7 KiB
Go
package router
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/QuantumNous/new-api/controller"
|
|
"github.com/QuantumNous/new-api/middleware"
|
|
pluginruntime "github.com/QuantumNous/new-api/pkg/jsplugin"
|
|
"github.com/QuantumNous/new-api/relaykit/types"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func SetTaskPluginProtocolRouter(router *gin.Engine) {
|
|
for _, protocol := range pluginruntime.HostProtocols() {
|
|
for _, operation := range protocol.Operations {
|
|
for _, method := range operation.Methods {
|
|
handlers, err := taskPluginProtocolHandlers(protocol.Name, operation.Name)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
router.Handle(method, operation.Path, handlers...)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func taskPluginProtocolHandlers(protocol, operation string) ([]gin.HandlerFunc, error) {
|
|
switch protocol + "." + operation {
|
|
case "openai_responses.create":
|
|
return []gin.HandlerFunc{
|
|
middleware.RouteTag("relay"), middleware.SystemPerformanceCheck(), middleware.TokenAuth(),
|
|
middleware.ModelRequestRateLimit(), middleware.RouteTaskPluginEndpoint(), middleware.PrepareTaskPluginEndpoint(), middleware.Distribute(),
|
|
func(c *gin.Context) {
|
|
controller.RelayTaskPluginEndpoint(c, func(c *gin.Context) { controller.Relay(c, types.RelayFormatOpenAIResponses) })
|
|
},
|
|
}, nil
|
|
case "openai_image.generate", "openai_image.edit":
|
|
return []gin.HandlerFunc{
|
|
middleware.RouteTag("relay"), middleware.SystemPerformanceCheck(), middleware.TokenAuth(),
|
|
middleware.ModelRequestRateLimit(), middleware.RouteTaskPluginEndpoint(), middleware.PrepareTaskPluginEndpoint(), middleware.Distribute(),
|
|
func(c *gin.Context) {
|
|
controller.RelayTaskPluginEndpoint(c, func(c *gin.Context) { controller.Relay(c, types.RelayFormatOpenAIImage) })
|
|
},
|
|
}, nil
|
|
case "openai_video.create":
|
|
return []gin.HandlerFunc{
|
|
middleware.RouteTag("relay"), middleware.TokenAuth(), middleware.SystemPerformanceCheck(),
|
|
middleware.RouteTaskPluginEndpoint(), middleware.TaskPluginEndpointOnly(middleware.ModelRequestRateLimit()), middleware.PrepareTaskPluginEndpoint(), middleware.Distribute(),
|
|
func(c *gin.Context) { controller.RelayTaskPluginEndpoint(c, controller.RelayTask) },
|
|
}, nil
|
|
case "openai_responses.retrieve":
|
|
return []gin.HandlerFunc{middleware.RouteTag("relay"), middleware.TokenAuth(), controller.RetrieveTaskPluginResponse}, nil
|
|
case "openai_video.retrieve":
|
|
return []gin.HandlerFunc{middleware.RouteTag("relay"), middleware.TokenAuth(), middleware.Distribute(), controller.RelayTaskFetch}, nil
|
|
case "openai_video.content":
|
|
return []gin.HandlerFunc{middleware.RouteTag("relay"), middleware.TokenAuth(), controller.VideoProxy}, nil
|
|
default:
|
|
return nil, fmt.Errorf("host protocol registry operation %s.%s has no handler", protocol, operation)
|
|
}
|
|
}
|