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) } }) } }