diff --git a/extensions/openai/image-generation-provider.test.ts b/extensions/openai/image-generation-provider.test.ts index 0bcd052146e..9305e5a4e59 100644 --- a/extensions/openai/image-generation-provider.test.ts +++ b/extensions/openai/image-generation-provider.test.ts @@ -1181,6 +1181,38 @@ describe("openai image generation provider", () => { ); }); + it("omits model from Azure generation body because deployment is URL-scoped", async () => { + mockGeneratedPngResponse(); + + const provider = buildOpenAIImageGenerationProvider(); + await provider.generateImage({ + provider: "openai", + model: "gpt-image-2-1", + prompt: "Azure cat", + cfg: { + models: { + providers: { + openai: { + baseUrl: "https://myresource.openai.azure.com/openai/v1", + models: [], + }, + }, + }, + }, + }); + + expect(postJsonRequestMock).toHaveBeenCalledWith( + expect.objectContaining({ + url: "https://myresource.openai.azure.com/openai/deployments/gpt-image-2-1/images/generations?api-version=2024-12-01-preview", + body: { + prompt: "Azure cat", + n: 1, + size: "1024x1024", + }, + }), + ); + }); + it("uses api-key header and deployment-scoped URL for .cognitiveservices.azure.com hosts", async () => { mockGeneratedPngResponse(); @@ -1308,6 +1340,41 @@ describe("openai image generation provider", () => { ); }); + it("omits model from Azure edit form because deployment is URL-scoped", async () => { + mockGeneratedPngResponse(); + + const provider = buildOpenAIImageGenerationProvider(); + await provider.generateImage({ + provider: "openai", + model: "gpt-image-2-1", + prompt: "Change background", + cfg: { + models: { + providers: { + openai: { + baseUrl: "https://myresource.openai.azure.com/openai/v1", + models: [], + }, + }, + }, + }, + inputImages: [ + { + buffer: Buffer.from("png-bytes"), + mimeType: "image/png", + fileName: "reference.png", + }, + ], + }); + + const editCallArgs = postMultipartRequestMock.mock.calls[0]?.[0] as { + body: FormData; + }; + expect(editCallArgs.body.has("model")).toBe(false); + expect(editCallArgs.body.get("prompt")).toBe("Change background"); + expect(editCallArgs.body.get("size")).toBe("1024x1024"); + }); + it("strips trailing /v1 from Azure base URL", async () => { mockGeneratedPngResponse(); diff --git a/extensions/openai/image-generation-provider.ts b/extensions/openai/image-generation-provider.ts index 5f0e056b030..31a30e65dd1 100644 --- a/extensions/openai/image-generation-provider.ts +++ b/extensions/openai/image-generation-provider.ts @@ -721,7 +721,9 @@ export function buildOpenAIImageGenerationProvider(): ImageGenerationProvider { const requestResult = isEdit ? await (() => { const form = new FormData(); - form.set("model", model); + if (!isAzure) { + form.set("model", model); + } form.set("prompt", req.prompt); form.set("n", String(count)); form.set("size", size); @@ -755,11 +757,13 @@ export function buildOpenAIImageGenerationProvider(): ImageGenerationProvider { const jsonHeaders = new Headers(headers); jsonHeaders.set("Content-Type", "application/json"); const body: Record = { - model, prompt: req.prompt, n: count, size, }; + if (!isAzure) { + body.model = model; + } appendOpenAIImageOptions(body, req); return postJsonRequest({ url,