feat: expose generic image background option

This commit is contained in:
Peter Steinberger
2026-04-25 20:21:46 +01:00
parent 03fd7df929
commit 75d64cd4b8
19 changed files with 173 additions and 59 deletions

View File

@@ -76,6 +76,7 @@ describe("fal image-generation provider", () => {
cfg: {},
count: 2,
size: "1536x1024",
outputFormat: "jpeg",
});
expectFalJsonPost({
@@ -85,7 +86,7 @@ describe("fal image-generation provider", () => {
prompt: "draw a cat",
image_size: { width: 1536, height: 1024 },
num_images: 2,
output_format: "png",
output_format: "jpeg",
},
});
expect(fetchWithSsrFGuardMock).toHaveBeenNthCalledWith(

View File

@@ -25,6 +25,7 @@ const DEFAULT_FAL_BASE_URL = "https://fal.run";
const DEFAULT_FAL_IMAGE_MODEL = "fal-ai/flux/dev";
const DEFAULT_FAL_EDIT_SUBPATH = "image-to-image";
const DEFAULT_OUTPUT_FORMAT = "png";
const FAL_OUTPUT_FORMATS = ["png", "jpeg"] as const;
const FAL_SUPPORTED_SIZES = [
"1024x1024",
"1024x1536",
@@ -292,6 +293,9 @@ export function buildFalImageGenerationProvider(): ImageGenerationProvider {
aspectRatios: [...FAL_SUPPORTED_ASPECT_RATIOS],
resolutions: ["1K", "2K", "4K"],
},
output: {
formats: [...FAL_OUTPUT_FORMATS],
},
},
async generateImage(req) {
const auth = await resolveApiKeyForProvider({
@@ -333,7 +337,7 @@ export function buildFalImageGenerationProvider(): ImageGenerationProvider {
const requestBody: Record<string, unknown> = {
prompt: req.prompt,
num_images: req.count ?? 1,
output_format: DEFAULT_OUTPUT_FORMAT,
output_format: req.outputFormat ?? DEFAULT_OUTPUT_FORMAT,
};
if (imageSize !== undefined) {
requestBody.image_size = imageSize;

View File

@@ -206,6 +206,7 @@ describe("openai image generation provider", () => {
expect(provider.capabilities.output).toEqual({
formats: ["png", "jpeg", "webp"],
qualities: ["low", "medium", "high", "auto"],
backgrounds: ["transparent", "opaque", "auto"],
});
});
@@ -443,11 +444,7 @@ describe("openai image generation provider", () => {
prompt: "Transparent sticker",
cfg: {},
outputFormat: "png",
providerOptions: {
openai: {
background: "transparent",
},
},
background: "transparent",
});
expect(postJsonRequestMock).toHaveBeenCalledWith(

View File

@@ -52,6 +52,7 @@ const MAX_CODEX_IMAGE_BASE64_CHARS = 64 * 1024 * 1024;
const LOG_VALUE_MAX_CHARS = 256;
const MOCK_OPENAI_PROVIDER_ID = "mock-openai";
const OPENAI_OUTPUT_FORMATS = ["png", "jpeg", "webp"] as const;
const OPENAI_BACKGROUNDS = ["transparent", "opaque", "auto"] as const;
const OPENAI_QUALITIES = ["low", "medium", "high", "auto"] as const;
const OPENAI_IMAGE_MODELS = [
DEFAULT_OPENAI_IMAGE_MODEL,
@@ -174,10 +175,11 @@ function appendOpenAIImageOptions(
req: Parameters<ImageGenerationProvider["generateImage"]>[0],
): void {
const openai = req.providerOptions?.openai;
const background = openai?.background ?? req.background;
const entries: Record<string, unknown> = {
...(req.quality !== undefined ? { quality: req.quality } : {}),
...(req.outputFormat !== undefined ? { output_format: req.outputFormat } : {}),
...(openai?.background !== undefined ? { background: openai.background } : {}),
...(background !== undefined ? { background } : {}),
...(openai?.moderation !== undefined ? { moderation: openai.moderation } : {}),
...(openai?.outputCompression !== undefined
? { output_compression: openai.outputCompression }
@@ -201,7 +203,7 @@ function resolveOpenAIImageRequestModel(
if (
options?.allowTransparentDefaultReroute === true &&
model === DEFAULT_OPENAI_IMAGE_MODEL &&
req.providerOptions?.openai?.background === "transparent"
(req.providerOptions?.openai?.background ?? req.background) === "transparent"
) {
return OPENAI_TRANSPARENT_BACKGROUND_IMAGE_MODEL;
}
@@ -513,6 +515,7 @@ function createOpenAIImageGenerationProviderBase(params: {
output: {
formats: [...OPENAI_OUTPUT_FORMATS],
qualities: [...OPENAI_QUALITIES],
backgrounds: [...OPENAI_BACKGROUNDS],
},
},
generateImage: params.generateImage,
@@ -580,6 +583,7 @@ async function generateOpenAICodexImage(params: {
const size = req.size ?? DEFAULT_SIZE;
const timeoutMs = resolveOpenAIImageTimeoutMs(req.timeoutMs);
const openai = req.providerOptions?.openai;
const background = openai?.background ?? req.background;
headers.set("Content-Type", "application/json");
const content: Array<Record<string, unknown>> = [
{ type: "input_text", text: req.prompt },
@@ -610,7 +614,7 @@ async function generateOpenAICodexImage(params: {
size,
...(req.quality !== undefined ? { quality: req.quality } : {}),
...(req.outputFormat !== undefined ? { output_format: req.outputFormat } : {}),
...(openai?.background !== undefined ? { background: openai.background } : {}),
...(background !== undefined ? { background } : {}),
...(openai?.outputCompression !== undefined
? { output_compression: openai.outputCompression }
: {}),