diff --git a/src/app/api/generate/__tests__/route.test.ts b/src/app/api/generate/__tests__/route.test.ts index 6d763545..37489823 100644 --- a/src/app/api/generate/__tests__/route.test.ts +++ b/src/app/api/generate/__tests__/route.test.ts @@ -1020,6 +1020,60 @@ describe("/api/generate route", () => { expect(data.image).toMatch(/^data:image\/png;base64,/); expect(data.contentType).toBe("image"); }); + + it("should pass top-level aspect ratio and resolution to native NewApiWG image models", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({ + candidates: [ + { + content: { + parts: [ + { + inlineData: { + mimeType: "image/png", + data: "nativeImageData", + }, + }, + ], + }, + }, + ], + }), + }); + + const request = createMockPostRequest( + { + prompt: "A tall poster", + aspectRatio: "9:16", + resolution: "2K", + selectedModel: { + provider: "newapiwg", + modelId: "apiyi_nano_banana_2", + displayName: "PopiArt Nano Pro", + capabilities: ["text-to-image", "image-to-image"], + }, + }, + { "X-NewApiWG-Key": "test-newapiwg-key" } + ); + + const response = await POST(request); + const data = await response.json(); + + expect(response.status).toBe(200); + expect(data.success).toBe(true); + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining("/models/gemini-3.1-flash-image-preview:generateContent"), + expect.objectContaining({ + body: expect.stringContaining('"aspectRatio":"9:16"'), + }) + ); + const body = JSON.parse(mockFetch.mock.calls[0][1].body as string); + expect(body.generationConfig.imageConfig).toMatchObject({ + aspectRatio: "9:16", + imageSize: "2K", + }); + }); }); describe("Replicate provider", () => { diff --git a/src/app/api/generate/route.ts b/src/app/api/generate/route.ts index 6f51b4ee..059598ff 100644 --- a/src/app/api/generate/route.ts +++ b/src/app/api/generate/route.ts @@ -83,6 +83,23 @@ function capabilitiesForMediaType(mediaType?: string): ModelCapability[] { return map[mediaType ?? ""] ?? ["text-to-image"]; } +function mergeImageGenerationParameters( + parameters: Record | undefined, + aspectRatio: string | undefined, + resolution: string | undefined +): Record | undefined { + const merged = { ...(parameters || {}) }; + if (aspectRatio && merged.aspectRatio === undefined && merged.aspect_ratio === undefined) { + merged.aspectRatio = aspectRatio; + merged.aspect_ratio = aspectRatio; + } + if (resolution && merged.resolution === undefined && merged.imageSize === undefined) { + merged.resolution = resolution; + merged.imageSize = resolution; + } + return Object.keys(merged).length > 0 ? merged : undefined; +} + export async function POST(request: NextRequest) { const requestId = Math.random().toString(36).substring(7); console.log(`\n[API:${requestId}] ========== NEW GENERATE REQUEST ==========`); @@ -162,7 +179,7 @@ export async function POST(request: NextRequest) { }, prompt: prompt || "", images: images ? [...images] : [], - parameters, + parameters: mergeImageGenerationParameters(parameters, aspectRatio, resolution), dynamicInputs, };