diff --git a/extensions/openai/video-generation-provider.test.ts b/extensions/openai/video-generation-provider.test.ts index 1fc7dab48a8f..c9eedea0662d 100644 --- a/extensions/openai/video-generation-provider.test.ts +++ b/extensions/openai/video-generation-provider.test.ts @@ -104,6 +104,12 @@ function streamedVideoResponse(bytes: string): Response { ); } +// Response.json keeps object fixtures on the standard Response body path so the +// create read exercises the byte-bounded reader instead of an unbounded res.json(). +function streamedJsonResponse(payload: unknown): Response { + return Response.json(payload); +} + describe("openai video generation provider", () => { it("declares explicit mode capabilities", () => { expectExplicitVideoGenerationCapabilities(buildOpenAIVideoGenerationProvider()); @@ -178,13 +184,11 @@ describe("openai video generation provider", () => { it("uses JSON for text-only Sora requests", async () => { postJsonRequestMock.mockResolvedValue({ - response: { - json: async () => ({ - id: "vid_123", - model: "sora-2", - status: "queued", - }), - }, + response: streamedJsonResponse({ + id: "vid_123", + model: "sora-2", + status: "queued", + }), release: vi.fn(async () => {}), }); fetchWithTimeoutMock @@ -226,13 +230,11 @@ describe("openai video generation provider", () => { it("rejects generated video downloads that exceed the configured media cap", async () => { postJsonRequestMock.mockResolvedValue({ - response: { - json: async () => ({ - id: "vid_too_large", - model: "sora-2", - status: "queued", - }), - }, + response: streamedJsonResponse({ + id: "vid_too_large", + model: "sora-2", + status: "queued", + }), release: vi.fn(async () => {}), }); fetchWithTimeoutMock @@ -258,13 +260,11 @@ describe("openai video generation provider", () => { it("uses JSON input_reference.image_url for image-to-video requests", async () => { postJsonRequestMock.mockResolvedValue({ - response: { - json: async () => ({ - id: "vid_456", - model: "sora-2", - status: "queued", - }), - }, + response: streamedJsonResponse({ + id: "vid_456", + model: "sora-2", + status: "queued", + }), release: vi.fn(async () => {}), }); fetchWithTimeoutMock @@ -303,13 +303,11 @@ describe("openai video generation provider", () => { it("keeps configured local baseUrl private-network blocked unless explicitly enabled", async () => { postJsonRequestMock.mockResolvedValue({ - response: { - json: async () => ({ - id: "vid_local", - model: "sora-2", - status: "queued", - }), - }, + response: streamedJsonResponse({ + id: "vid_local", + model: "sora-2", + status: "queued", + }), release: vi.fn(async () => {}), }); fetchWithTimeoutMock @@ -351,13 +349,11 @@ describe("openai video generation provider", () => { it("honors configured request allowPrivateNetwork for local video providers", async () => { postJsonRequestMock.mockResolvedValue({ - response: { - json: async () => ({ - id: "vid_local", - model: "sora-2", - status: "queued", - }), - }, + response: streamedJsonResponse({ + id: "vid_local", + model: "sora-2", + status: "queued", + }), release: vi.fn(async () => {}), }); fetchWithTimeoutMock @@ -426,13 +422,11 @@ describe("openai video generation provider", () => { }) .mockImplementationOnce(async () => {}); postJsonRequestMock.mockResolvedValue({ - response: { - json: async () => ({ - id: "vid_local", - model: "sora-2", - status: "queued", - }), - }, + response: streamedJsonResponse({ + id: "vid_local", + model: "sora-2", + status: "queued", + }), release: vi.fn(async () => {}), }); fetchWithTimeoutMock.mockResolvedValueOnce({ @@ -497,13 +491,11 @@ describe("openai video generation provider", () => { throw new Error(label); }); postJsonRequestMock.mockResolvedValue({ - response: { - json: async () => ({ - id: "vid_local", - model: "sora-2", - status: "queued", - }), - }, + response: streamedJsonResponse({ + id: "vid_local", + model: "sora-2", + status: "queued", + }), release: vi.fn(async () => {}), }); fetchWithTimeoutMock.mockResolvedValueOnce({ @@ -552,21 +544,20 @@ describe("openai video generation provider", () => { it("uses the video edits endpoint for video-to-video uploads", async () => { fetchWithTimeoutMock - .mockResolvedValueOnce({ - ok: true, - json: async () => ({ + .mockResolvedValueOnce( + streamedJsonResponse({ id: "vid_789", model: "sora-2", status: "queued", }), - }) - .mockResolvedValueOnce({ - json: async () => ({ + ) + .mockResolvedValueOnce( + streamedJsonResponse({ id: "vid_789", model: "sora-2", status: "completed", }), - }) + ) .mockResolvedValueOnce({ headers: new Headers({ "content-type": "video/mp4" }), arrayBuffer: async () => Buffer.from("mp4-bytes"), @@ -597,21 +588,20 @@ describe("openai video generation provider", () => { it("honors configured request allowPrivateNetwork for multipart video uploads", async () => { fetchWithTimeoutMock - .mockResolvedValueOnce({ - ok: true, - json: async () => ({ + .mockResolvedValueOnce( + streamedJsonResponse({ id: "vid_789", model: "sora-2", status: "queued", }), - }) - .mockResolvedValueOnce({ - json: async () => ({ + ) + .mockResolvedValueOnce( + streamedJsonResponse({ id: "vid_789", model: "sora-2", status: "completed", }), - }) + ) .mockResolvedValueOnce({ headers: new Headers({ "content-type": "video/mp4" }), arrayBuffer: async () => Buffer.from("mp4-bytes"), diff --git a/extensions/openai/video-generation-provider.ts b/extensions/openai/video-generation-provider.ts index 88684631da44..74627710ccbd 100644 --- a/extensions/openai/video-generation-provider.ts +++ b/extensions/openai/video-generation-provider.ts @@ -12,6 +12,7 @@ import { pollProviderOperationJson, postJsonRequest, postMultipartRequest, + readProviderJsonResponse, resolveProviderOperationTimeoutMs, resolveProviderHttpRequestConfig, sanitizeConfiguredModelProviderRequest, @@ -424,7 +425,10 @@ export function buildOpenAIVideoGenerationProvider(): VideoGenerationProvider { try { await assertOkOrThrowHttpError(response, "OpenAI video generation failed"); - const submitted = (await response.json()) as OpenAIVideoResponse; + const submitted = await readProviderJsonResponse( + response, + "OpenAI video generation failed", + ); const videoId = normalizeOptionalString(submitted.id); if (!videoId) { throw new Error("OpenAI video generation response missing video id");