From 8df87875de950346cea07a2b2a8aee92df6fd679 Mon Sep 17 00:00:00 2001 From: wangbo Date: Fri, 24 Jul 2026 09:04:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(images):=20=E4=BC=98=E5=85=88=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E7=BC=96=E8=BE=91=E5=9B=BE=E7=89=87=E4=B8=BA=20multip?= =?UTF-8?q?art=20=E4=BA=8C=E8=BF=9B=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenAI 编辑即使声明支持 URL,也必须在 multipart 提交前转存为二进制文件。 --- apps/api/internal/runner/request_assets.go | 12 +++++++----- apps/api/internal/runner/request_assets_test.go | 6 ++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/api/internal/runner/request_assets.go b/apps/api/internal/runner/request_assets.go index 4b128ef..85670e8 100644 --- a/apps/api/internal/runner/request_assets.go +++ b/apps/api/internal/runner/request_assets.go @@ -159,9 +159,11 @@ func (s *Service) hydrateProviderRequestAssetString(ctx context.Context, value s if raw == "" || !imageInputFieldNeedsHydration(path) { return value, nil } - style, ok := requestAssetCapabilityHydrationForMedia("image", candidate, raw, "") - if !ok && openAIImageEditRequiresMultipartBytes(candidate) { + style, ok := requestAssetHydrateUnsupported, false + if openAIImageEditRequiresMultipartBytes(candidate) { style, ok = requestAssetHydrateDataURL, true + } else { + style, ok = requestAssetCapabilityHydrationForMedia("image", candidate, raw, "") } if !ok { return value, nil @@ -320,12 +322,12 @@ func requestAssetHydrationForField(path []string, asset store.RequestAsset, cand return requestAssetHydrateDataURL } if requestAssetMediaKindForHydration(path, asset) == "image" { - if style, ok := requestAssetCapabilityHydrationForMedia("image", candidate, asset.URL, asset.StorageProvider); ok { - return style - } if openAIImageEditRequiresMultipartBytes(candidate) { return requestAssetHydrateDataURL } + if style, ok := requestAssetCapabilityHydrationForMedia("image", candidate, asset.URL, asset.StorageProvider); ok { + return style + } } if mediaURLFieldNeedsHydration(path) { if style := configuredRequestAssetMediaURLHydration(candidate, requestAssetMediaURLKind(path)); style != "" { diff --git a/apps/api/internal/runner/request_assets_test.go b/apps/api/internal/runner/request_assets_test.go index b85a009..0f3f542 100644 --- a/apps/api/internal/runner/request_assets_test.go +++ b/apps/api/internal/runner/request_assets_test.go @@ -223,6 +223,12 @@ func TestHydrateProviderRequestAssetsConvertsOpenAIEditImagesForMultipart(t *tes hydrated, err := service.hydrateProviderRequestAssets(context.Background(), body, store.RuntimeModelCandidate{ Provider: "openai", ModelType: "image_edit", + Capabilities: map[string]any{ + "image_edit": map[string]any{ + "support_url_input": true, + "support_base64_input": false, + }, + }, }) if err != nil { t.Fatalf("hydrate OpenAI edit images: %v", err)