mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-12 07:00:42 +00:00
feat(task): replace built-in task adaptors with a sandboxed JS plugin system (#7076)
This commit is contained in:
+44
-5
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/QuantumNous/new-api/constant"
|
||||
"github.com/QuantumNous/new-api/i18n"
|
||||
"github.com/QuantumNous/new-api/model"
|
||||
"github.com/QuantumNous/new-api/pkg/jsplugin"
|
||||
relaychannel "github.com/QuantumNous/new-api/relay/channel"
|
||||
"github.com/QuantumNous/new-api/relay/channel/ollama"
|
||||
relaycommon "github.com/QuantumNous/new-api/relay/common"
|
||||
@@ -480,6 +481,21 @@ func validateChannel(channel *model.Channel, isAdd bool) error {
|
||||
if err := channel.ValidateSettings(); err != nil {
|
||||
return fmt.Errorf("渠道额外设置[channel setting] 格式错误:%s", err.Error())
|
||||
}
|
||||
if channel.Type == constant.ChannelTypeTaskPlugin {
|
||||
pluginKey := strings.TrimSpace(channel.GetSetting().TaskPluginKey)
|
||||
if pluginKey == "" {
|
||||
return fmt.Errorf("task plugin key is required")
|
||||
}
|
||||
if len(pluginKey) > 30 {
|
||||
return fmt.Errorf("task plugin key must not exceed 30 characters")
|
||||
}
|
||||
if _, ok := jsplugin.DefaultRegistry.Get(pluginKey); !ok {
|
||||
return fmt.Errorf("task plugin %q is not registered", pluginKey)
|
||||
}
|
||||
if channel.BaseURL == nil || strings.TrimSpace(*channel.BaseURL) == "" {
|
||||
return fmt.Errorf("base URL is required for task plugin channels")
|
||||
}
|
||||
}
|
||||
|
||||
if channel.Type == constant.ChannelTypeNewAPI && strings.TrimSpace(channel.GetBaseURL()) == "" {
|
||||
return fmt.Errorf("New API channel base URL cannot be empty")
|
||||
@@ -617,6 +633,15 @@ func AddChannel(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if addChannelRequest.Channel != nil && addChannelRequest.Channel.Type == constant.ChannelTypeTaskPlugin &&
|
||||
!authz.Can(c.GetInt("id"), c.GetInt("role"), authz.TaskPluginBind) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "task plugin channels require the task_plugin.bind permission",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 使用统一的校验函数
|
||||
if err := validateChannel(addChannelRequest.Channel, true); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
@@ -964,6 +989,15 @@ func UpdateChannel(c *gin.Context) {
|
||||
}
|
||||
clearChannelReadOnlyFields(&channel, requestData)
|
||||
|
||||
if channel.Type == constant.ChannelTypeTaskPlugin &&
|
||||
!authz.Can(c.GetInt("id"), c.GetInt("role"), authz.TaskPluginBind) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "task plugin channels require the task_plugin.bind permission",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 使用统一的校验函数
|
||||
if err := validateChannel(&channel.Channel, false); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
@@ -1299,7 +1333,7 @@ func FetchModels(c *gin.Context) {
|
||||
baseURL = strings.TrimSpace(*req.BaseURL)
|
||||
}
|
||||
if baseURL == "" {
|
||||
baseURL = constant.ChannelBaseURLs[req.Type]
|
||||
baseURL = constant.GetChannelBaseURL(req.Type)
|
||||
}
|
||||
|
||||
key := strings.TrimSpace(req.Key)
|
||||
@@ -1424,6 +1458,11 @@ func CopyChannel(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": "获取渠道信息失败,请稍后重试"})
|
||||
return
|
||||
}
|
||||
if origin.Type == constant.ChannelTypeTaskPlugin &&
|
||||
!authz.Can(c.GetInt("id"), c.GetInt("role"), authz.TaskPluginBind) {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": "task plugin channels require the task_plugin.bind permission"})
|
||||
return
|
||||
}
|
||||
|
||||
// clone channel
|
||||
clone := *origin // shallow copy is sufficient as we will overwrite primitives
|
||||
@@ -2010,7 +2049,7 @@ func OllamaPullModel(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
baseURL := constant.ChannelBaseURLs[channel.Type]
|
||||
baseURL := constant.GetChannelBaseURL(channel.Type)
|
||||
if channel.GetBaseURL() != "" {
|
||||
baseURL = channel.GetBaseURL()
|
||||
}
|
||||
@@ -2073,7 +2112,7 @@ func OllamaPullModelStream(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
baseURL := constant.ChannelBaseURLs[channel.Type]
|
||||
baseURL := constant.GetChannelBaseURL(channel.Type)
|
||||
if channel.GetBaseURL() != "" {
|
||||
baseURL = channel.GetBaseURL()
|
||||
}
|
||||
@@ -2155,7 +2194,7 @@ func OllamaDeleteModel(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
baseURL := constant.ChannelBaseURLs[channel.Type]
|
||||
baseURL := constant.GetChannelBaseURL(channel.Type)
|
||||
if channel.GetBaseURL() != "" {
|
||||
baseURL = channel.GetBaseURL()
|
||||
}
|
||||
@@ -2204,7 +2243,7 @@ func OllamaVersion(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
baseURL := constant.ChannelBaseURLs[channel.Type]
|
||||
baseURL := constant.GetChannelBaseURL(channel.Type)
|
||||
if channel.GetBaseURL() != "" {
|
||||
baseURL = channel.GetBaseURL()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user