fix(video): 内置协议 - 复用统一轮询容错

This commit is contained in:
hzw
2026-09-12 21:06:29 +08:00
parent ee13f49c43
commit 2df5bcc5cd
3 changed files with 101 additions and 63 deletions

View File

@@ -213,7 +213,7 @@ func TestRunVideoTaskUsesDeclarativeAgnesJSONProtocol(t *testing.T) {
defer server.Close()
ctx := withProtocolRegistry(context.Background(), center.registrySnapshot())
result, err := runVideoTask(ctx, canvasGenerationInput{
result, err := runVideoTaskForTest(ctx, canvasGenerationInput{
Mode: "video",
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL + "/v1", APIKey: "test-key", InterfaceType: "agnes-video", Model: "agnes-video-2.5", VideoSeconds: "5", Size: "16:9", VQuality: "720P"},
@@ -261,7 +261,7 @@ func TestRunVideoTaskDownloadsAuthenticatedDeclarativeResult(t *testing.T) {
defer server.Close()
ctx := withProtocolRegistry(context.Background(), center.registrySnapshot())
result, err := runVideoTask(ctx, canvasGenerationInput{
result, err := runVideoTaskForTest(ctx, canvasGenerationInput{
Mode: "video", Prompt: "cinematic shot",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", InterfaceType: "newapi", Model: "sora-2", VideoSeconds: "5", Size: "1280x720"},
})
@@ -871,7 +871,7 @@ func TestProviderPayloadErrorCategoryPrefersProviderCodeOverModerationWording(t
func TestRunVideoTaskRequiresOfficialPluginWhenRegistryEmpty(t *testing.T) {
ctx := withProtocolRegistry(context.Background(), emptyProtocolRegistry)
_, err := runVideoTask(ctx, canvasGenerationInput{
_, err := runVideoTaskForTest(ctx, canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: "https://example.com", APIKey: "key", Model: "MiniMax-H3", InterfaceType: "minimax-video"},
})
@@ -1568,7 +1568,7 @@ func TestRunVideoTaskUsesNewAPIForAnyVideoModel(t *testing.T) {
}))
defer server.Close()
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL + "/v1", APIKey: "test-key", Model: "custom-video-v1"},
})
@@ -1585,6 +1585,46 @@ func TestRunVideoTaskUsesNewAPIForAnyVideoModel(t *testing.T) {
}
}
func TestRunVideoTaskRetriesTransientPollFailureWithoutRecreating(t *testing.T) {
t.Setenv("CANVAS_ALLOW_PRIVATE_UPSTREAMS", "true")
createCalls := 0
pollCalls := 0
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.Method + " " + r.URL.Path {
case "POST /v1/videos":
createCalls++
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"id":"video-1","status":"queued"}`))
case "GET /v1/videos/video-1":
pollCalls++
w.Header().Set("Content-Type", "application/json")
if pollCalls == 1 {
w.WriteHeader(http.StatusServiceUnavailable)
_, _ = w.Write([]byte(`{"message":"temporary outage"}`))
return
}
_, _ = w.Write([]byte(`{"id":"video-1","status":"completed"}`))
case "GET /v1/videos/video-1/content":
w.Header().Set("Content-Type", "video/mp4")
_, _ = w.Write([]byte("video"))
default:
http.NotFound(w, r)
}
}))
defer server.Close()
result, err := runVideoTaskWithPolicy(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL + "/v1", APIKey: "test-key", Model: "custom-video-v1"},
}, fastVideoPollPolicy())
if err != nil {
t.Fatal(err)
}
if result["mode"] != "video" || createCalls != 1 || pollCalls != 2 {
t.Fatalf("result = %#v, create calls = %d, poll calls = %d", result, createCalls, pollCalls)
}
}
func TestRunVideoTaskSendsOnlyDeclaredResolutionName(t *testing.T) {
tests := []struct {
name string
@@ -1628,7 +1668,7 @@ func TestRunVideoTaskSendsOnlyDeclaredResolutionName(t *testing.T) {
if test.withoutProfile {
profile = nil
}
_, err := runVideoTask(context.Background(), canvasGenerationInput{
_, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "synthetic prompt",
Config: providerConfig{BaseURL: server.URL + "/v1", APIKey: "test-key", Model: "public-video", VideoSeconds: "8", Size: "16:9", VQuality: test.quality},
VideoCapability: profile,
@@ -1670,7 +1710,7 @@ func TestRunVideoTaskUsesNestedURLBeforeResultURL(t *testing.T) {
}))
defer server.Close()
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", Model: "grok-imagine-video-1.5-1080p", VideoSeconds: "15"},
})
@@ -1721,7 +1761,7 @@ func TestRunVideoTaskUsesJSONForGrokVideo(t *testing.T) {
}))
defer server.Close()
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL + "/v1", APIKey: "test-key", Model: "grok-video", VideoSeconds: "10"},
ReferenceImages: []providerMedia{{ID: "image-1", DataURL: testReferenceImageDataURL}},
@@ -1779,7 +1819,7 @@ func TestRunVideoTaskUsesXAIVideoGenerationEndpoint(t *testing.T) {
}))
defer server.Close()
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{
BaseURL: server.URL + "/v1",
@@ -1821,7 +1861,7 @@ func TestRunVideoTaskXAIVideoRejectsUnreachableResultURL(t *testing.T) {
}))
defer server.Close()
_, err := runVideoTask(context.Background(), canvasGenerationInput{
_, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{
BaseURL: server.URL + "/v1",
@@ -2000,7 +2040,7 @@ func TestVolcengineArkVideoProtocolUsesContentTaskAndDownloadsResult(t *testing.
}))
defer server.Close()
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL + "/api/v3", APIKey: "test-key", Model: "doubao-seedance-test", InterfaceType: "volcengine-ark-video"},
ReferenceImages: []providerMedia{{ID: "start", URL: server.URL + "/reference.png"}},
@@ -2196,7 +2236,7 @@ func TestRunNewAPIChannel1VideoTaskDownloadsSucceededObject(t *testing.T) {
}))
defer server.Close()
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL + "/v1", APIKey: "test-key", Model: "seedance-2.0", InterfaceType: "newapi-channel-1"},
})
@@ -2260,7 +2300,7 @@ func TestRunNewAPIChannel2VideoTaskDownloadsTemporaryResult(t *testing.T) {
profile := DefaultModelCapabilityConfigForModel("newapi-channel-2", "grok-image-video").Video
profile.Resolutions = []string{"720p"}
profile.DefaultResolution = "720p"
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", Model: "grok-image-video", InterfaceType: "newapi-channel-2", VideoSeconds: "15", Size: "9:16", VQuality: "720", VideoGenerateAudio: "true"},
ReferenceImages: []providerMedia{
@@ -2315,7 +2355,7 @@ func TestRunNewAPIChannel2VideoTaskResumesOriginalProviderTaskWithoutAnotherPost
ctx := withProviderAnalytics(context.Background(), nil, model.Task{
ID: "task-1", Type: "canvas_video", ProviderRequestID: "existing-provider-task", InputJSON: string(inputJSON),
})
result, err := runVideoTask(ctx, input)
result, err := runVideoTaskForTest(ctx, input)
if err != nil {
t.Fatalf("runVideoTask() error = %v", err)
}
@@ -2332,7 +2372,7 @@ func TestRunNewAPIChannel2VideoTaskReturnsTypedDeadlineWhenPollingWindowEnds(t *
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Second))
defer cancel()
ctx = withProviderAnalytics(ctx, nil, model.Task{ID: "task-1", Type: "canvas_video", ProviderRequestID: "existing-provider-task"})
_, err := runVideoTask(ctx, canvasGenerationInput{
_, err := runVideoTaskForTest(ctx, canvasGenerationInput{
Mode: "video",
Config: providerConfig{InterfaceType: string(model.ChannelInterfaceNewAPIChannel2), Model: "video-model", BaseURL: "https://example.com", APIKey: "key"},
})
@@ -2366,7 +2406,7 @@ func TestRunGeminiVeoVideoTaskUsesLongRunningOperation(t *testing.T) {
}))
defer server.Close()
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", APIFormat: "gemini", Model: "veo-test", InterfaceType: "gemini-veo", VideoSeconds: "6", Size: "16:9", VQuality: "720"},
})
@@ -2571,7 +2611,7 @@ func TestRunNovitaVideoTaskDownloadsSucceededVideo(t *testing.T) {
}))
defer server.Close()
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", Model: "kling2.5_turbo_pro_t2v", InterfaceType: "novita-video", VideoSeconds: "5", Size: "16:9"},
})
@@ -2604,7 +2644,7 @@ func TestRunNovitaVideoTaskReturnsFailureReason(t *testing.T) {
}))
defer server.Close()
_, err := runVideoTask(context.Background(), canvasGenerationInput{
_, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", Model: "kling2.5_turbo_pro_t2v", InterfaceType: "novita-video"},
})
@@ -2650,7 +2690,7 @@ func TestRunMiniMaxVideoTaskCreatesPollsAndDownloads(t *testing.T) {
}))
defer server.Close()
result, err := runVideoTask(context.Background(), canvasGenerationInput{
result, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Mode: "video",
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", Model: "MiniMax-H3", InterfaceType: "minimax-video", VideoSeconds: "5", VQuality: "768P", Size: "16:9"},
@@ -2686,7 +2726,7 @@ func TestRunMiniMaxVideoTaskSendsOfficial2KResolution(t *testing.T) {
_, _ = w.Write([]byte(`{}`))
}))
defer server.Close()
_, err := runVideoTask(context.Background(), canvasGenerationInput{
_, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Mode: "video", Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", Model: "MiniMax-H3", InterfaceType: "minimax-video", VideoSeconds: "6", VQuality: "2K"},
})
@@ -2731,7 +2771,7 @@ func TestRunMiniMaxVideoTaskUsesExplicitReferenceRoles(t *testing.T) {
}))
defer server.Close()
_, err := runVideoTask(context.Background(), canvasGenerationInput{
_, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Mode: "video",
Prompt: "保持角色一致",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", Model: "MiniMax-H3", InterfaceType: "minimax-video", VideoSeconds: "6", VQuality: "768P", Size: "16:9"},
@@ -2760,7 +2800,7 @@ func TestRunMiniMaxVideoTaskReturnsFailureReason(t *testing.T) {
}))
defer server.Close()
_, err := runVideoTask(context.Background(), canvasGenerationInput{
_, err := runVideoTaskForTest(context.Background(), canvasGenerationInput{
Mode: "video",
Prompt: "make it move",
Config: providerConfig{BaseURL: server.URL, APIKey: "test-key", Model: "MiniMax-H3", InterfaceType: "minimax-video", VideoSeconds: "6"},