From 534bb557e59911606b8a94f9140f3df4aed9dded Mon Sep 17 00:00:00 2001 From: qiuliw Date: Wed, 23 Sep 2026 14:52:58 +0800 Subject: [PATCH] =?UTF-8?q?fix(plugin):=20=E4=B8=87=E7=9B=B83.0=E8=A7=86?= =?UTF-8?q?=E9=A2=91=20-=20=E4=BF=AE=E5=A4=8D=E4=B8=8A=E6=B8=B8=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E9=94=99=E8=AF=AF=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/app/provider_error.go | 42 ++++++++++++++------- backend/internal/app/provider_error_test.go | 32 +++++++++++++++- 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/backend/internal/app/provider_error.go b/backend/internal/app/provider_error.go index d20979b0b..9195ba63e 100644 --- a/backend/internal/app/provider_error.go +++ b/backend/internal/app/provider_error.go @@ -48,27 +48,43 @@ func providerResponseBusinessFailure(responseBody []byte) (string, string, bool) } func providerPayloadBusinessFailure(payload map[string]any) (string, string, bool) { + if code, message, failed := providerBusinessFailure(payload); failed { + return code, message, true + } + // DashScope 业务失败在 output 内 + if output, ok := payload["output"].(map[string]any); ok { + return providerBusinessFailure(output) + } + return "", "", false +} + +func providerBusinessFailure(payload map[string]any) (string, string, bool) { if errorValue, ok := payload["error"].(map[string]any); ok { code, message := providerFailureDetails(map[string]any{"error": errorValue}) if code != "" || message != "" { return code, message, true } } - if !providerBusinessCodeFailed(payload["code"]) { - return "", "", false - } - code, message := providerFailureDetails(payload) - return code, message, true -} -func providerBusinessCodeFailed(value any) bool { - code := strings.ToLower(strings.TrimSpace(fmt.Sprint(value))) - switch code { - case "", "0", "success", "succeeded", "ok", "": - return false - default: - return true + code := strings.ToLower(strings.TrimSpace(fmt.Sprint(payload["code"]))) + if code != "" && code != "0" && + code != "success" && code != "succeeded" && + code != "ok" && code != "" { + code, message := providerFailureDetails(payload) + return code, message, true } + + status := strings.ToLower(strings.TrimSpace(fmt.Sprint(payload["task_status"]))) + switch status { + case "failed", "failure", "error", "expired": + code, message := providerFailureDetails(payload) + if code == "" { + code = "task_failed" + } + return code, message, true + } + + return "", "", false } func normalizedProviderErrorCode(value any) string { diff --git a/backend/internal/app/provider_error_test.go b/backend/internal/app/provider_error_test.go index b4ad58acb..e20962eb8 100644 --- a/backend/internal/app/provider_error_test.go +++ b/backend/internal/app/provider_error_test.go @@ -1,6 +1,9 @@ package app -import "testing" +import ( + "strings" + "testing" +) func TestProviderFailureDetailsReadsTopLevelModerationError(t *testing.T) { code, message := providerFailureDetails(map[string]any{ @@ -59,3 +62,30 @@ func TestProviderPayloadBusinessFailureAcceptsStringSuccessCode(t *testing.T) { t.Fatalf("success payload was marked failed: (%q, %q)", code, message) } } + +func TestProviderPayloadBusinessFailureReadsNestedOutputFailure(t *testing.T) { + code, message, failed := providerPayloadBusinessFailure(map[string]any{ + "output": map[string]any{ + "code": "InvalidParameter", + "message": "Input should be '1080P', '720P' or '480P': parameters.resolution", + "task_id": "e0d8c86d-4939-4f2e-93f7-e2cd10a07d58", + "task_status": "FAILED", + }, + "request_id": "c3c98e67-830d-9f1d-8a62-fff019ffa522", + }) + if !failed || code != "InvalidParameter" { + t.Fatalf("nested output failure = (%q, %q, %v)", code, message, failed) + } + if !strings.Contains(message, "parameters.resolution") { + t.Fatalf("unexpected message: %q", message) + } +} + +func TestProviderPayloadBusinessFailureIgnoresPendingOutput(t *testing.T) { + if code, message, failed := providerPayloadBusinessFailure(map[string]any{ + "output": map[string]any{"task_id": "task-1", "task_status": "PENDING"}, + "request_id": "req-1", + }); failed { + t.Fatalf("pending output marked failed: (%q, %q)", code, message) + } +}