diff --git a/app/(chat)/api/chat/_lib/image-failover.ts b/app/(chat)/api/chat/_lib/image-failover.ts index 8476992aa..c88298c24 100644 --- a/app/(chat)/api/chat/_lib/image-failover.ts +++ b/app/(chat)/api/chat/_lib/image-failover.ts @@ -214,15 +214,25 @@ function messagePartHasImageInput(part: any) { return false; } +function countImageInputPartsInMessage(message: any) { + const countParts = (parts: any[] | undefined) => + Array.isArray(parts) ? parts.filter(messagePartHasImageInput).length : 0; + + const contentCount = countParts(Array.isArray(message?.content) ? message.content : undefined); + if (contentCount > 0) return contentCount; + + return countParts(Array.isArray(message?.parts) ? message.parts : undefined); +} + +export function countChatMessageImageInputs(messages: ChatMessage[]) { + return messages.reduce( + (count, message) => count + countImageInputPartsInMessage(message), + 0 + ); +} + export function chatMessagesHaveImageInput(messages: ChatMessage[]) { - return messages.some((message: any) => { - const content = message?.content; - if (Array.isArray(content) && content.some(messagePartHasImageInput)) { - return true; - } - const parts = message?.parts; - return Array.isArray(parts) && parts.some(messagePartHasImageInput); - }); + return countChatMessageImageInputs(messages) > 0; } export function getImageFailoverConvertProvider(providerType?: string | null) { @@ -384,13 +394,16 @@ export async function generateImageWithFailoverCandidate(params: { getImageFailoverConvertProvider(providerType) ); const effectiveImageParams = imageParams || fallbackImageParams; + const imageInputCount = countChatMessageImageInputs(messages); chatApiLogger.info("[Chat API] Image failover candidate params:", { model: candidate.model?.modelId || candidate.model?.id, providerType, aspectRatio: effectiveImageParams?.aspectRatio, imageSize: effectiveImageParams?.imageSize, imageCount: effectiveImageParams?.imageCount, - hasImageInput: chatMessagesHaveImageInput(messages), + hasImageInput: imageInputCount > 0, + imageInputCount, + multiImageInput: imageInputCount > 1, }); const candidateResult = await (candidateLanguageModel as any).doGenerate({ messages: candidateMessages, diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index dd0a4df20..3dd0b80fc 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -9373,7 +9373,9 @@ export async function POST(request: Request) { ); chatApiLogger.info("[Chat API] Image provider target images:", { resolutionMode: requestTargetResolution?.resolutionMode || null, + targetImageCount: resolvedTargetImageUrlsForProvider.length, imageCount: resolvedTargetImageUrlsForProvider.length, + multiImageTarget: resolvedTargetImageUrlsForProvider.length > 1, firstImageUrl: summarizeTargetImageUrl(resolvedTargetImageUrlsForProvider[0]), }); } diff --git a/lib/ai/providers/snapgen-image.ts b/lib/ai/providers/snapgen-image.ts index a0026c75d..15d104cab 100644 --- a/lib/ai/providers/snapgen-image.ts +++ b/lib/ai/providers/snapgen-image.ts @@ -901,6 +901,13 @@ export function createSnapgenImage({ apiKey, baseURL }: SnapgenImageConfig) { resolutionParam, imageCount, referenceImageCount: imageUrls.length, + multiImageReference: imageUrls.length > 1, + referenceTransport: + imageUrls.length === 0 + ? "none" + : apiFormat === "snapgen-generic-image" + ? "file_urls" + : "files", }); const createPayload = await requestSnapgenMultipart({