From 240b9b5bc436189c945dfe3027fba16c0293df58 Mon Sep 17 00:00:00 2001 From: rinseaid Date: Sun, 9 Aug 2026 13:19:22 -0400 Subject: [PATCH] fix(image): return fal defaults as base64 (#9932) Co-authored-by: rinseaid --- open-sse/handlers/imageGeneration.ts | 10 ++-- .../unit/fal-image-generation-default.test.ts | 55 +++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 tests/unit/fal-image-generation-default.test.ts diff --git a/open-sse/handlers/imageGeneration.ts b/open-sse/handlers/imageGeneration.ts index 97941262ed..da944c7d73 100644 --- a/open-sse/handlers/imageGeneration.ts +++ b/open-sse/handlers/imageGeneration.ts @@ -1524,7 +1524,7 @@ async function handleFalAIImageGeneration({ } const payload = await response.json(); - const images = await normalizeProviderImagePayload(payload, body, log); + const images = await normalizeProviderImagePayload(payload, body, log, "b64_json"); return saveImageSuccessResult({ provider, model, @@ -2200,7 +2200,7 @@ function shouldIncludeStabilityMask(model) { ]).has(model); } -async function normalizeProviderImagePayload(payload, body, log) { +async function normalizeProviderImagePayload(payload, body, log, defaultFormat) { const candidates = []; const pushCandidate = (value) => { @@ -2226,7 +2226,7 @@ async function normalizeProviderImagePayload(payload, body, log) { const normalized = []; for (const candidate of candidates) { - const item = await normalizeProviderImageCandidate(candidate, body); + const item = await normalizeProviderImageCandidate(candidate, body, defaultFormat); if (item) normalized.push(item); } @@ -2240,8 +2240,8 @@ async function normalizeProviderImagePayload(payload, body, log) { return normalized; } -async function normalizeProviderImageCandidate(candidate, body) { - const wantsBase64 = body?.response_format === "b64_json"; +async function normalizeProviderImageCandidate(candidate, body, defaultFormat) { + const wantsBase64 = body?.response_format === "b64_json" || defaultFormat === "b64_json"; let url = null; let b64 = null; diff --git a/tests/unit/fal-image-generation-default.test.ts b/tests/unit/fal-image-generation-default.test.ts new file mode 100644 index 0000000000..91b9203150 --- /dev/null +++ b/tests/unit/fal-image-generation-default.test.ts @@ -0,0 +1,55 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import dns from "node:dns"; +import { mkdtempSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; + +process.env.DATA_DIR = mkdtempSync(join(tmpdir(), "omniroute-fal-images-")); + +const originalDnsLookup = dns.promises.lookup; +(dns.promises as { lookup: unknown }).lookup = (async ( + _hostname: string, + options?: { all?: boolean } +) => { + const record = { address: "203.0.113.1", family: 4 }; + return options?.all ? [record] : record; +}) as typeof dns.promises.lookup; +process.on("exit", () => { + (dns.promises as { lookup: unknown }).lookup = originalDnsLookup; +}); + +const { handleImageGeneration } = await import("../../open-sse/handlers/imageGeneration.ts"); + +test("handleImageGeneration returns Fal images as base64 when response_format is omitted", async () => { + const originalFetch = globalThis.fetch; + globalThis.fetch = async (url) => { + const stringUrl = String(url); + if (stringUrl === "https://fal.run/fal-ai/flux-2-flex") { + return new Response( + JSON.stringify({ images: [{ url: "https://cdn.example.com/fal-flex.png" }] }), + { status: 200, headers: { "content-type": "application/json" } } + ); + } + if (stringUrl === "https://cdn.example.com/fal-flex.png") { + return new Response(new Uint8Array([8, 9, 10]), { + status: 200, + headers: { "content-type": "image/png" }, + }); + } + throw new Error(`Unexpected URL: ${stringUrl}`); + }; + + try { + const result = await handleImageGeneration({ + body: { model: "fal-ai/fal-ai/flux-2-flex", prompt: "red apple" }, + credentials: { apiKey: "fal-key" }, + log: null, + }); + assert.equal(result.success, true); + assert.equal(result.data.data[0].b64_json, "CAkK"); + assert.equal(result.data.data[0].url, undefined); + } finally { + globalThis.fetch = originalFetch; + } +});