Files
new-api-custom/plugins/builtin_plugins_test.go
T
Codex bb7968b612
Publish Docker image (Multi-arch) / Build & push (amd64) (push) Failing after 9m20s
Release (Linux, macOS, Windows) / Linux Release (push) Failing after 55m7s
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Canceled after 0s
Release (Linux, macOS, Windows) / macOS Release (push) Canceled after 0s
Release (Linux, macOS, Windows) / Windows Release (push) Canceled after 0s
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Canceled after 0s
feat: publish v1.0.0-rc.36-custom.1
2026-09-11 05:07:48 +08:00

158 lines
5.8 KiB
Go

package plugins
import (
"io/fs"
"testing"
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/pkg/jsplugin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var expectedKeys = []string{"alibaba", "doubao", "google", "hailuo", "jimeng", "kling", "sora", "sunoapi", "vertex-ai", "vidu"}
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) {
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)
}
})
}
}
func TestBuiltInResponsesDecodersEchoChannelMappedAlias(t *testing.T) {
bodyOverrides := map[string]map[string]any{}
for _, key := range expectedKeys {
t.Run(key, func(t *testing.T) {
source, sourceErr := Source(key)
require.NoError(t, sourceErr)
registry := jsplugin.NewRegistry()
plugin, registerErr := registry.RegisterFactory(source, jsplugin.Options{Key: key})
require.NoError(t, registerErr)
require.NotEmpty(t, plugin.Meta.Models)
alias := "alias-under-test"
upstreamModel := plugin.Meta.Models[0]
body := map[string]any{"model": alias, "input": "a cat walking on the beach"}
if override, ok := bodyOverrides[key]; ok {
body = override
}
value, callErr := plugin.Engine.CallPath(t.Context(), "protocols", []string{"openai_responses", "decodeRequest"}, map[string]any{
"model": alias, "upstreamModel": upstreamModel, "stream": false,
"body": map[string]any{"kind": "json", "value": body},
})
require.NoError(t, callErr)
encoded, marshalErr := common.Marshal(value)
require.NoError(t, marshalErr)
var decoded map[string]any
require.NoError(t, common.Unmarshal(encoded, &decoded))
assert.Equal(t, "submit", decoded["kind"])
assert.Equal(t, alias, decoded["model"])
})
}
}