




















@@ -233,4 +233,241 @@ describe("openai image generation provider", () => {
233233);
234234expect(result.images).toHaveLength(1);
235235});
236+237+describe("azure openai support", () => {
238+it("uses api-key header and deployment-scoped URL for Azure .openai.azure.com hosts", async () => {
239+mockGeneratedPngResponse();
240+241+const provider = buildOpenAIImageGenerationProvider();
242+await provider.generateImage({
243+provider: "openai",
244+model: "gpt-image-2",
245+prompt: "Azure cat",
246+cfg: {
247+models: {
248+providers: {
249+openai: {
250+baseUrl: "https://myresource.openai.azure.com",
251+models: [],
252+},
253+},
254+},
255+},
256+});
257+258+expect(resolveProviderHttpRequestConfigMock).toHaveBeenCalledWith(
259+expect.objectContaining({
260+defaultHeaders: { "api-key": "openai-key" },
261+}),
262+);
263+expect(postJsonRequestMock).toHaveBeenCalledWith(
264+expect.objectContaining({
265+url: "https://myresource.openai.azure.com/openai/deployments/gpt-image-2/images/generations?api-version=2024-12-01-preview",
266+}),
267+);
268+});
269+270+it("uses api-key header and deployment-scoped URL for .cognitiveservices.azure.com hosts", async () => {
271+mockGeneratedPngResponse();
272+273+const provider = buildOpenAIImageGenerationProvider();
274+await provider.generateImage({
275+provider: "openai",
276+model: "gpt-image-2",
277+prompt: "Azure cat",
278+cfg: {
279+models: {
280+providers: {
281+openai: {
282+baseUrl: "https://myresource.cognitiveservices.azure.com",
283+models: [],
284+},
285+},
286+},
287+},
288+});
289+290+expect(resolveProviderHttpRequestConfigMock).toHaveBeenCalledWith(
291+expect.objectContaining({
292+defaultHeaders: { "api-key": "openai-key" },
293+}),
294+);
295+expect(postJsonRequestMock).toHaveBeenCalledWith(
296+expect.objectContaining({
297+url: "https://myresource.cognitiveservices.azure.com/openai/deployments/gpt-image-2/images/generations?api-version=2024-12-01-preview",
298+}),
299+);
300+});
301+302+it("uses api-key header and deployment-scoped URL for .services.ai.azure.com hosts", async () => {
303+mockGeneratedPngResponse();
304+305+const provider = buildOpenAIImageGenerationProvider();
306+await provider.generateImage({
307+provider: "openai",
308+model: "gpt-image-2",
309+prompt: "Azure cat",
310+cfg: {
311+models: {
312+providers: {
313+openai: {
314+baseUrl: "https://my-resource.services.ai.azure.com",
315+models: [],
316+},
317+},
318+},
319+},
320+});
321+322+expect(resolveProviderHttpRequestConfigMock).toHaveBeenCalledWith(
323+expect.objectContaining({
324+defaultHeaders: { "api-key": "openai-key" },
325+}),
326+);
327+expect(postJsonRequestMock).toHaveBeenCalledWith(
328+expect.objectContaining({
329+url: "https://my-resource.services.ai.azure.com/openai/deployments/gpt-image-2/images/generations?api-version=2024-12-01-preview",
330+}),
331+);
332+});
333+334+it("respects AZURE_OPENAI_API_VERSION env override", async () => {
335+mockGeneratedPngResponse();
336+vi.stubEnv("AZURE_OPENAI_API_VERSION", "2025-01-01");
337+338+const provider = buildOpenAIImageGenerationProvider();
339+await provider.generateImage({
340+provider: "openai",
341+model: "gpt-image-2",
342+prompt: "Azure cat",
343+cfg: {
344+models: {
345+providers: {
346+openai: {
347+baseUrl: "https://myresource.openai.azure.com",
348+models: [],
349+},
350+},
351+},
352+},
353+});
354+355+expect(postJsonRequestMock).toHaveBeenCalledWith(
356+expect.objectContaining({
357+url: "https://myresource.openai.azure.com/openai/deployments/gpt-image-2/images/generations?api-version=2025-01-01",
358+}),
359+);
360+});
361+362+it("builds Azure edit URL with deployment and api-version", async () => {
363+mockGeneratedPngResponse();
364+365+const provider = buildOpenAIImageGenerationProvider();
366+await provider.generateImage({
367+provider: "openai",
368+model: "gpt-image-2",
369+prompt: "Change background",
370+cfg: {
371+models: {
372+providers: {
373+openai: {
374+baseUrl: "https://myresource.openai.azure.com",
375+models: [],
376+},
377+},
378+},
379+},
380+inputImages: [
381+{
382+buffer: Buffer.from("png-bytes"),
383+mimeType: "image/png",
384+fileName: "reference.png",
385+},
386+],
387+});
388+389+expect(postJsonRequestMock).toHaveBeenCalledWith(
390+expect.objectContaining({
391+url: "https://myresource.openai.azure.com/openai/deployments/gpt-image-2/images/edits?api-version=2024-12-01-preview",
392+}),
393+);
394+});
395+396+it("strips trailing /v1 from Azure base URL", async () => {
397+mockGeneratedPngResponse();
398+399+const provider = buildOpenAIImageGenerationProvider();
400+await provider.generateImage({
401+provider: "openai",
402+model: "gpt-image-2",
403+prompt: "Azure cat",
404+cfg: {
405+models: {
406+providers: {
407+openai: {
408+baseUrl: "https://myresource.openai.azure.com/v1",
409+models: [],
410+},
411+},
412+},
413+},
414+});
415+416+expect(postJsonRequestMock).toHaveBeenCalledWith(
417+expect.objectContaining({
418+url: "https://myresource.openai.azure.com/openai/deployments/gpt-image-2/images/generations?api-version=2024-12-01-preview",
419+}),
420+);
421+});
422+423+it("strips trailing /openai/v1 from Azure base URL", async () => {
424+mockGeneratedPngResponse();
425+426+const provider = buildOpenAIImageGenerationProvider();
427+await provider.generateImage({
428+provider: "openai",
429+model: "gpt-image-2",
430+prompt: "Azure cat",
431+cfg: {
432+models: {
433+providers: {
434+openai: {
435+baseUrl: "https://myresource.openai.azure.com/openai/v1",
436+models: [],
437+},
438+},
439+},
440+},
441+});
442+443+expect(postJsonRequestMock).toHaveBeenCalledWith(
444+expect.objectContaining({
445+url: "https://myresource.openai.azure.com/openai/deployments/gpt-image-2/images/generations?api-version=2024-12-01-preview",
446+}),
447+);
448+});
449+450+it("still uses Bearer auth for public OpenAI hosts", async () => {
451+mockGeneratedPngResponse();
452+453+const provider = buildOpenAIImageGenerationProvider();
454+await provider.generateImage({
455+provider: "openai",
456+model: "gpt-image-2",
457+prompt: "Public cat",
458+cfg: {},
459+});
460+461+expect(resolveProviderHttpRequestConfigMock).toHaveBeenCalledWith(
462+expect.objectContaining({
463+defaultHeaders: { Authorization: "Bearer openai-key" },
464+}),
465+);
466+expect(postJsonRequestMock).toHaveBeenCalledWith(
467+expect.objectContaining({
468+url: "https://api.openai.com/v1/images/generations",
469+}),
470+);
471+});
472+});
236473});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。