fix(protocol): Seedream 声明式结果 - 裸 b64_json 补全 data URL
声明式解析把 Ark/Seedream 的裸 b64_json 写成 DataURL 时未加 data: 前缀,导致图片任务在上游成功后仍报媒体结果下载失败。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -172,7 +172,7 @@ func asyncAudioErrorMessage(state map[string]interface{}) string {
|
||||
func decodeProviderDataURL(value string) (string, []byte, error) {
|
||||
header, encoded, ok := strings.Cut(value, ",")
|
||||
if !ok || !strings.HasPrefix(header, "data:") || !strings.HasSuffix(strings.ToLower(header), ";base64") {
|
||||
return "", nil, errors.New("音频 data URL 格式无效")
|
||||
return "", nil, errors.New("data URL 格式无效")
|
||||
}
|
||||
mimeType := strings.TrimSuffix(strings.TrimPrefix(header, "data:"), ";base64")
|
||||
data, err := base64.StdEncoding.DecodeString(encoded)
|
||||
|
||||
@@ -711,6 +711,8 @@ func mediaReferencesFromManifestValue(value any, kind string, ephemeral bool) []
|
||||
if reference.DataURL == "" {
|
||||
reference.DataURL = firstString(typed, "data_url", "b64_json")
|
||||
}
|
||||
// OpenAI / Ark 等渠道常直接返回裸 b64_json;声明式结果下载要求 data URL。
|
||||
reference.DataURL = normalizeManifestInlineDataURL(reference.DataURL, reference.Kind, firstString(typed, "output_format", "mime_type", "mimeType"))
|
||||
if reference.URL != "" || reference.DataURL != "" {
|
||||
result = append(result, reference)
|
||||
}
|
||||
@@ -719,6 +721,50 @@ func mediaReferencesFromManifestValue(value any, kind string, ephemeral bool) []
|
||||
return result
|
||||
}
|
||||
|
||||
func normalizeManifestInlineDataURL(value, kind, formatHint string) string {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" || strings.HasPrefix(value, "data:") {
|
||||
return value
|
||||
}
|
||||
return "data:" + manifestInlineMediaMIME(kind, formatHint) + ";base64," + value
|
||||
}
|
||||
|
||||
func manifestInlineMediaMIME(kind, formatHint string) string {
|
||||
hint := strings.ToLower(strings.TrimSpace(formatHint))
|
||||
switch hint {
|
||||
case "image/png", "image/jpeg", "image/webp", "image/gif", "audio/mpeg", "audio/wav", "audio/ogg", "video/mp4", "video/webm":
|
||||
return hint
|
||||
case "image/jpg":
|
||||
return "image/jpeg"
|
||||
case "audio/mp3":
|
||||
return "audio/mpeg"
|
||||
case "png":
|
||||
return "image/png"
|
||||
case "jpeg", "jpg":
|
||||
return "image/jpeg"
|
||||
case "webp":
|
||||
return "image/webp"
|
||||
case "gif":
|
||||
return "image/gif"
|
||||
case "mp3", "mpeg":
|
||||
return "audio/mpeg"
|
||||
case "wav":
|
||||
return "audio/wav"
|
||||
case "mp4":
|
||||
return "video/mp4"
|
||||
case "webm":
|
||||
return "video/webm"
|
||||
}
|
||||
switch strings.ToLower(strings.TrimSpace(kind)) {
|
||||
case "audio":
|
||||
return "audio/mpeg"
|
||||
case "video":
|
||||
return "video/mp4"
|
||||
default:
|
||||
return "image/png"
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
manifestMDImageRegex = regexp.MustCompile(`!\[[^\]]*\]\(([^)\s]+)\)`)
|
||||
manifestHTMLVideoRegex = regexp.MustCompile(`(?i)<video[^>]+src=['"]([^'"]+)['"]`)
|
||||
|
||||
@@ -784,3 +784,27 @@ func TestOfficialOpenAIAudioSpeedDefaultsInvalidAndZeroValues(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOfficialArkSeedreamParsesB64JSONAsDataURL(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
packageName, providerID string
|
||||
}{
|
||||
{"volcengine-ark-seedream.yingce-plugin", "volcengine-ark-image"},
|
||||
{"volcengine-ark-agent-plan-seedream.yingce-plugin", "volcengine-ark-agent-plan-image"},
|
||||
} {
|
||||
t.Run(tc.providerID, func(t *testing.T) {
|
||||
adapter := officialPackageAdapter(t, tc.packageName, tc.providerID)
|
||||
result, err := adapter.ParseCreate(context.Background(), []byte(`{"created":1,"data":[{"b64_json":"aW1hZ2U=","output_format":"jpeg","size":"1824x1024"}]}`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result.Result == nil || len(result.Result.Images) != 1 {
|
||||
t.Fatalf("result = %#v", result.Result)
|
||||
}
|
||||
dataURL := result.Result.Images[0].DataURL
|
||||
if dataURL != "data:image/jpeg;base64,aW1hZ2U=" {
|
||||
t.Fatalf("DataURL = %q, want jpeg data URL from b64_json + output_format", dataURL)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user