mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(openai): bound video create-submit response reads
Reviewed and accepted after live preflight: mergeable clean, checks passing, no unresolved review threads.
This commit is contained in:
@@ -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"),
|
||||
|
||||
@@ -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<OpenAIVideoResponse>(
|
||||
response,
|
||||
"OpenAI video generation failed",
|
||||
);
|
||||
const videoId = normalizeOptionalString(submitted.id);
|
||||
if (!videoId) {
|
||||
throw new Error("OpenAI video generation response missing video id");
|
||||
|
||||
Reference in New Issue
Block a user