mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-09 15:59:30 +00:00
fix(fal): bound music/video generation response reads
Reviewed and accepted after live preflight: mergeable clean, checks passing, no unresolved review threads.
This commit is contained in:
parent
ca1bc58759
commit
ce1217a49c
4 changed files with 54 additions and 54 deletions
|
|
@ -58,6 +58,13 @@ function streamedAudioResponse(bytes: string): Response {
|
|||
);
|
||||
}
|
||||
|
||||
function falMusicJsonResponse(value: unknown) {
|
||||
return {
|
||||
response: Response.json(value),
|
||||
release: vi.fn(async () => {}),
|
||||
};
|
||||
}
|
||||
|
||||
describe("fal music generation provider", () => {
|
||||
afterEach(() => {
|
||||
assertOkOrThrowHttpErrorMock.mockClear();
|
||||
|
|
@ -72,18 +79,15 @@ describe("fal music generation provider", () => {
|
|||
});
|
||||
|
||||
it("submits MiniMax music through fal and downloads the generated track", async () => {
|
||||
postJsonRequestMock.mockResolvedValue({
|
||||
response: {
|
||||
json: async () => ({
|
||||
audio: {
|
||||
url: "https://v3b.fal.media/files/b/kangaroo/out.mp3",
|
||||
content_type: "audio/mpeg",
|
||||
file_name: "out.mp3",
|
||||
},
|
||||
}),
|
||||
},
|
||||
release: vi.fn(async () => {}),
|
||||
});
|
||||
postJsonRequestMock.mockResolvedValue(
|
||||
falMusicJsonResponse({
|
||||
audio: {
|
||||
url: "https://v3b.fal.media/files/b/kangaroo/out.mp3",
|
||||
content_type: "audio/mpeg",
|
||||
file_name: "out.mp3",
|
||||
},
|
||||
}),
|
||||
);
|
||||
const fetchMock = vi.fn(
|
||||
async () =>
|
||||
new Response(Buffer.from("mp3-bytes"), {
|
||||
|
|
@ -125,17 +129,14 @@ describe("fal music generation provider", () => {
|
|||
});
|
||||
|
||||
it("rejects generated music downloads that exceed the configured media cap", async () => {
|
||||
postJsonRequestMock.mockResolvedValue({
|
||||
response: {
|
||||
json: async () => ({
|
||||
audio: {
|
||||
url: "https://v3b.fal.media/files/b/out.mp3",
|
||||
content_type: "audio/mpeg",
|
||||
},
|
||||
}),
|
||||
},
|
||||
release: vi.fn(async () => {}),
|
||||
});
|
||||
postJsonRequestMock.mockResolvedValue(
|
||||
falMusicJsonResponse({
|
||||
audio: {
|
||||
url: "https://v3b.fal.media/files/b/out.mp3",
|
||||
content_type: "audio/mpeg",
|
||||
},
|
||||
}),
|
||||
);
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
vi.fn(async () => streamedAudioResponse("too-large")),
|
||||
|
|
@ -167,16 +168,13 @@ describe("fal music generation provider", () => {
|
|||
});
|
||||
|
||||
it("maps ACE-Step duration and instrumental controls", async () => {
|
||||
postJsonRequestMock.mockResolvedValue({
|
||||
response: {
|
||||
json: async () => ({
|
||||
audio: { url: "https://example.com/out.wav", content_type: "audio/wav" },
|
||||
seed: 42,
|
||||
tags: "lofi, chill",
|
||||
}),
|
||||
},
|
||||
release: vi.fn(async () => {}),
|
||||
});
|
||||
postJsonRequestMock.mockResolvedValue(
|
||||
falMusicJsonResponse({
|
||||
audio: { url: "https://example.com/out.wav", content_type: "audio/wav" },
|
||||
seed: 42,
|
||||
tags: "lofi, chill",
|
||||
}),
|
||||
);
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
vi.fn(
|
||||
|
|
@ -205,14 +203,11 @@ describe("fal music generation provider", () => {
|
|||
});
|
||||
|
||||
it("maps Stable Audio duration controls", async () => {
|
||||
postJsonRequestMock.mockResolvedValue({
|
||||
response: {
|
||||
json: async () => ({
|
||||
audio: "https://example.com/stable.wav",
|
||||
}),
|
||||
},
|
||||
release: vi.fn(async () => {}),
|
||||
});
|
||||
postJsonRequestMock.mockResolvedValue(
|
||||
falMusicJsonResponse({
|
||||
audio: "https://example.com/stable.wav",
|
||||
}),
|
||||
);
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
vi.fn(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,11 @@ import {
|
|||
type MusicGenerationRequest,
|
||||
} from "openclaw/plugin-sdk/music-generation";
|
||||
import { isProviderApiKeyConfigured } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { assertOkOrThrowHttpError, postJsonRequest } from "openclaw/plugin-sdk/provider-http";
|
||||
import {
|
||||
assertOkOrThrowHttpError,
|
||||
postJsonRequest,
|
||||
readProviderJsonResponse,
|
||||
} from "openclaw/plugin-sdk/provider-http";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import { resolveFalHttpRequestConfig } from "./http-config.js";
|
||||
|
||||
|
|
@ -161,7 +165,7 @@ export function buildFalMusicGenerationProvider(): MusicGenerationProvider {
|
|||
|
||||
try {
|
||||
await assertOkOrThrowHttpError(response, "fal music generation failed");
|
||||
const payload = await response.json();
|
||||
const payload = await readProviderJsonResponse<unknown>(response, "fal music generation");
|
||||
const [candidate] = extractGeneratedMusicFileCandidates(payload);
|
||||
if (!candidate) {
|
||||
throw new Error("fal music generation response missing audio output");
|
||||
|
|
|
|||
|
|
@ -37,9 +37,7 @@ describe("fal video generation provider", () => {
|
|||
|
||||
function releasedJson(value: unknown) {
|
||||
return {
|
||||
response: {
|
||||
json: async () => value,
|
||||
},
|
||||
response: Response.json(value),
|
||||
release: vi.fn(async () => {}),
|
||||
};
|
||||
}
|
||||
|
|
@ -254,11 +252,10 @@ describe("fal video generation provider", () => {
|
|||
it("wraps non-JSON successful fal submit responses", async () => {
|
||||
mockFalProviderRuntime();
|
||||
fetchGuardMock.mockResolvedValueOnce({
|
||||
response: {
|
||||
json: async () => {
|
||||
throw new SyntaxError("Unexpected token < in JSON");
|
||||
},
|
||||
},
|
||||
response: new Response("<html><body>Bad Gateway</body></html>", {
|
||||
status: 200,
|
||||
headers: { "content-type": "text/html" },
|
||||
}),
|
||||
release: vi.fn(async () => {}),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { isProviderApiKeyConfigured } from "openclaw/plugin-sdk/provider-auth";
|
|||
import {
|
||||
assertOkOrThrowHttpError,
|
||||
createProviderOperationDeadline,
|
||||
readProviderJsonResponse,
|
||||
type ProviderOperationDeadline,
|
||||
} from "openclaw/plugin-sdk/provider-http";
|
||||
import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
||||
|
|
@ -480,9 +481,12 @@ async function fetchFalJson(params: {
|
|||
try {
|
||||
await assertOkOrThrowHttpError(response, params.errorContext);
|
||||
try {
|
||||
return await response.json();
|
||||
} catch {
|
||||
throw new Error(FAL_VIDEO_MALFORMED_RESPONSE);
|
||||
return await readProviderJsonResponse<unknown>(response, params.errorContext);
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.message.endsWith(": malformed JSON response")) {
|
||||
throw new Error(FAL_VIDEO_MALFORMED_RESPONSE, { cause: error });
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
} finally {
|
||||
await release();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue