mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-01 19:41:57 +00:00
124 lines
4.5 KiB
Go
124 lines
4.5 KiB
Go
package plugins
|
|
|
|
import (
|
|
"io/fs"
|
|
"testing"
|
|
|
|
"github.com/QuantumNous/new-api/pkg/jsplugin"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestBuiltInVendorPluginsDeclareNativeRoutesAndLegacyChannelTypes(t *testing.T) {
|
|
generation := jsplugin.DefaultRegistry.Generation()
|
|
require.NotNil(t, generation)
|
|
|
|
routes := []struct {
|
|
method string
|
|
path string
|
|
key string
|
|
routeType jsplugin.RouteType
|
|
action string
|
|
renderer string
|
|
}{
|
|
{"POST", "/kling/v1/videos/text2video", "kling", jsplugin.RouteTypeSubmit, "text_to_video", "taskCreated"},
|
|
{"POST", "/kling/v1/videos/image2video", "kling", jsplugin.RouteTypeSubmit, "image_to_video", "taskCreated"},
|
|
{"GET", "/kling/v1/videos/text2video/:task_id", "kling", jsplugin.RouteTypeQuery, "", "taskStatus"},
|
|
{"GET", "/kling/v1/videos/image2video/:task_id", "kling", jsplugin.RouteTypeQuery, "", "taskStatus"},
|
|
{"POST", "/jimeng/", "jimeng", jsplugin.RouteTypeDynamic, "", "renderTask"},
|
|
{"POST", "/suno/submit/:action", "sunoapi", jsplugin.RouteTypeSubmit, "", "renderSubmit"},
|
|
{"POST", "/suno/fetch", "sunoapi", jsplugin.RouteTypeDynamic, "", "renderTasks"},
|
|
{"GET", "/suno/fetch/:task_id", "sunoapi", jsplugin.RouteTypeQuery, "", "renderTask"},
|
|
{"POST", "/doubao/api/v3/contents/generations/tasks", "doubao", jsplugin.RouteTypeSubmit, "", "taskCreated"},
|
|
{"GET", "/doubao/api/v3/contents/generations/tasks/:task_id", "doubao", jsplugin.RouteTypeQuery, "", "taskStatus"},
|
|
}
|
|
for _, expected := range routes {
|
|
t.Run(expected.method+" "+expected.path, func(t *testing.T) {
|
|
binding, found := generation.LookupDeclaredRoute(expected.method, expected.path)
|
|
require.True(t, found)
|
|
require.Equal(t, expected.key, binding.Plugin.Meta.Key)
|
|
require.Equal(t, expected.routeType, binding.Route.Type)
|
|
require.Equal(t, expected.action, binding.Route.Action)
|
|
require.Equal(t, expected.renderer, binding.Route.Render)
|
|
})
|
|
}
|
|
|
|
channelTypes := []struct {
|
|
value int
|
|
key string
|
|
}{
|
|
{1, "sora"},
|
|
{36, "sunoapi"},
|
|
{45, "doubao"},
|
|
{50, "kling"},
|
|
{51, "jimeng"},
|
|
{54, "doubao"},
|
|
{55, "sora"},
|
|
}
|
|
for _, channelType := range channelTypes {
|
|
plugin, found := generation.GetByChannelType(channelType.value)
|
|
require.True(t, found)
|
|
require.Equal(t, channelType.key, plugin.Meta.Key)
|
|
}
|
|
}
|
|
|
|
func TestBuiltInTaskPluginResponsesAndUsageContracts(t *testing.T) {
|
|
expectedKeys := []string{"alibaba", "doubao", "google", "hailuo", "jimeng", "kling", "sora", "sunoapi", "vertex-ai", "vidu"}
|
|
generation := jsplugin.DefaultRegistry.Generation()
|
|
require.NotNil(t, generation)
|
|
|
|
entries, err := fs.ReadDir(taskPlugins, "tasks")
|
|
require.NoError(t, err)
|
|
actualKeys := make([]string, 0, len(entries))
|
|
for _, entry := range entries {
|
|
if entry.IsDir() {
|
|
actualKeys = append(actualKeys, entry.Name())
|
|
}
|
|
}
|
|
assert.Equal(t, expectedKeys, actualKeys)
|
|
|
|
for _, key := range expectedKeys {
|
|
t.Run(key, func(t *testing.T) {
|
|
_, found := generation.Get(key)
|
|
require.True(t, found, "factory plugin was excluded from the active generation")
|
|
|
|
source, sourceErr := Source(key)
|
|
require.NoError(t, sourceErr)
|
|
registry := jsplugin.NewRegistry()
|
|
plugin, registerErr := registry.RegisterFactory(source, jsplugin.Options{Key: key})
|
|
require.NoError(t, registerErr)
|
|
|
|
var responsesClaim jsplugin.ProtocolClaim
|
|
foundResponses := false
|
|
for _, claim := range plugin.Meta.Protocols {
|
|
if claim.Name == "openai_responses" {
|
|
responsesClaim = claim
|
|
foundResponses = true
|
|
break
|
|
}
|
|
}
|
|
require.True(t, foundResponses, "openai_responses claim must be present")
|
|
assert.Equal(t, []string{"stream", "sync", "background"}, responsesClaim.Supports)
|
|
for _, model := range plugin.Meta.Models {
|
|
binding, claimed := registry.Generation().LookupEndpoint("POST", "/v1/responses", model)
|
|
require.True(t, claimed, model)
|
|
assert.Same(t, plugin, binding.Plugin)
|
|
}
|
|
for _, hook := range []string{"decodeRequest", "renderEvents", "renderFinal"} {
|
|
callable, callableErr := plugin.Engine.HasCallablePath(t.Context(), "protocols", "openai_responses", hook)
|
|
require.NoError(t, callableErr)
|
|
assert.True(t, callable, hook)
|
|
}
|
|
for _, hook := range []string{"extractUsage", "extractUsageOnComplete"} {
|
|
callable, callableErr := plugin.Engine.HasExport(t.Context(), hook)
|
|
require.NoError(t, callableErr)
|
|
assert.True(t, callable, hook)
|
|
}
|
|
require.NotEmpty(t, plugin.Meta.UsageSchema)
|
|
for usageKey, schema := range plugin.Meta.UsageSchema {
|
|
assert.NotEmpty(t, schema.Description, usageKey)
|
|
}
|
|
})
|
|
}
|
|
}
|