From 9e8817f89e68bd96ca66f3e2242b01746c5d3195 Mon Sep 17 00:00:00 2001 From: 134 Date: Mon, 22 Jun 2026 02:28:47 +0800 Subject: [PATCH] fix: preserve Agnes image edit aspect ratio --- lib/ai/providers/openai-image.ts | 44 +++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/ai/providers/openai-image.ts b/lib/ai/providers/openai-image.ts index 23b5af919..2c3a05085 100644 --- a/lib/ai/providers/openai-image.ts +++ b/lib/ai/providers/openai-image.ts @@ -34,6 +34,13 @@ const OPENAI_IMAGE_DIMENSION_MULTIPLE = 16; const COMFLY_GPT_IMAGE_STABLE_EDIT_EDGE = 1536; const COMFLY_GPT_IMAGE_MAX_EDGE = 3840; const COMFLY_GPT_IMAGE_MAX_TOTAL_PIXELS = 8_294_400; +const AGNES_IMAGE_LONG_EDGE_BY_SIZE: Record<"1K" | "2K" | "4K", number> = { + "1K": 1024, + "2K": 1536, + "4K": 2048, +}; +const AGNES_IMAGE_MAX_EDGE = 2048; +const AGNES_IMAGE_MAX_TOTAL_PIXELS = 4_194_304; const BLTCY_HOST_REGEX = /(^|\.)bltcy\.ai$/i; const COMFLY_HOST_REGEX = /(^|\.)ai\.comfly\.org$/i; const AGNES_HOST_REGEX = /(^|\.)agnes-ai\.com$/i; @@ -240,6 +247,20 @@ function resolveComflyGptImageSize(aspectRatio: string, imageSize: "1K" | "2K" | return `${width}x${height}`; } +function resolveAgnesImageSize(aspectRatio: string, imageSize: "1K" | "2K" | "4K") { + const { width, height } = resolveLongestEdgeDimensions({ + aspectRatio, + longestEdge: AGNES_IMAGE_LONG_EDGE_BY_SIZE[imageSize] || AGNES_IMAGE_LONG_EDGE_BY_SIZE["2K"], + constraints: { + maxEdge: AGNES_IMAGE_MAX_EDGE, + maxPixels: AGNES_IMAGE_MAX_TOTAL_PIXELS, + multiple: 8, + }, + }); + + return `${width}x${height}`; +} + function resolveProviderImageSize( baseURL: string, aspectRatio: string, @@ -248,6 +269,9 @@ function resolveProviderImageSize( if (isComflyBaseURL(baseURL)) { return resolveComflyGptImageSize(aspectRatio, imageSize); } + if (isAgnesBaseURL(baseURL)) { + return resolveAgnesImageSize(aspectRatio, imageSize); + } return resolveOpenAISize(aspectRatio, imageSize); } @@ -785,9 +809,17 @@ export function createOpenAIImage({ apiKey, baseURL }: OpenAIImageConfig) { const activeModelId = options.overrideModelId || modelId; const normalizedAspectRatio = normalizeAspectRatio(options.imageParams?.aspectRatio); const promptAspectRatio = inferAspectRatioFromPrompt(prompt); + const referenceAspectRatio = + imageUrls.length > 0 + ? await inferAspectRatioFromImageUrl(imageUrls[0] || "") + : null; + const shouldPreferReferenceAspectRatio = + imageUrls.length > 0 && isAgnesImageModel(baseURL, activeModelId); const aspectRatio = - normalizedAspectRatio === "auto" - ? promptAspectRatio || (await inferAspectRatioFromImageUrl(imageUrls[0] || "")) + shouldPreferReferenceAspectRatio + ? referenceAspectRatio || promptAspectRatio || normalizedAspectRatio + : normalizedAspectRatio === "auto" + ? promptAspectRatio || referenceAspectRatio : normalizedAspectRatio; const requestedImageSize = normalizeImageSizeLabel(options.imageParams?.imageSize); const modelImageSize = isComflyBaseURL(baseURL) @@ -808,11 +840,17 @@ export function createOpenAIImage({ apiKey, baseURL }: OpenAIImageConfig) { apiModel: resolveProviderApiModelId(baseURL, activeModelId), size, aspectRatio: aspectRatio || "auto", + referenceAspectRatio: referenceAspectRatio || undefined, + preferReferenceAspectRatio: shouldPreferReferenceAspectRatio, promptAspectRatio: promptAspectRatio || undefined, imageSize, requestedImageSize, modelImageSize, - resolutionMode: isComflyBaseURL(baseURL) ? "comfly-gpt-image-constraints" : "pixel-area", + resolutionMode: isComflyBaseURL(baseURL) + ? "comfly-gpt-image-constraints" + : isAgnesBaseURL(baseURL) + ? "agnes-long-edge-constraints" + : "pixel-area", timeoutMs: resolveRequestTimeoutMs(baseURL, imageSize, activeModelId), useBltcyImageCompatParams: shouldUseBltcyImageCompatParams(baseURL), imageCount: imageUrls.length,