fix: validate music duration option · openclaw/openclaw@365f551
steipete
·
2026-05-29
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -1044,6 +1044,43 @@ describe("createMusicGenerateTool", () => {
|
1044 | 1044 | }); |
1045 | 1045 | }); |
1046 | 1046 | |
| 1047 | +it("rejects fractional duration seconds before generation", async () => { |
| 1048 | +const generateMusic = vi.spyOn(musicGenerationRuntime, "generateMusic").mockResolvedValue({ |
| 1049 | +provider: "minimax", |
| 1050 | +model: "music-2.6", |
| 1051 | +attempts: [], |
| 1052 | +ignoredOverrides: [], |
| 1053 | +tracks: [ |
| 1054 | +{ |
| 1055 | +buffer: Buffer.from("music-bytes"), |
| 1056 | +mimeType: "audio/mpeg", |
| 1057 | +fileName: "night-drive.mp3", |
| 1058 | +}, |
| 1059 | +], |
| 1060 | +}); |
| 1061 | + |
| 1062 | +const tool = createMusicGenerateTool({ |
| 1063 | +config: asConfig({ |
| 1064 | +agents: { |
| 1065 | +defaults: { |
| 1066 | +musicGenerationModel: { primary: "minimax/music-2.6" }, |
| 1067 | +}, |
| 1068 | +}, |
| 1069 | +}), |
| 1070 | +}); |
| 1071 | +if (!tool) { |
| 1072 | +throw new Error("expected music_generate tool"); |
| 1073 | +} |
| 1074 | + |
| 1075 | +await expect( |
| 1076 | +tool.execute("call-1", { |
| 1077 | +prompt: "night-drive synthwave", |
| 1078 | +durationSeconds: 45.5, |
| 1079 | +}), |
| 1080 | +).rejects.toThrow("durationSeconds must be a positive integer"); |
| 1081 | +expect(generateMusic).not.toHaveBeenCalled(); |
| 1082 | +}); |
| 1083 | + |
1047 | 1084 | it("passes web_fetch SSRF policy when loading reference images", async () => { |
1048 | 1085 | vi.spyOn(musicGenerationRuntime, "listRuntimeMusicGenerationProviders").mockReturnValue([ |
1049 | 1086 | { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -21,6 +21,7 @@ import type {
|
21 | 21 | MusicGenerationProvider, |
22 | 22 | MusicGenerationSourceImage, |
23 | 23 | } from "../../music-generation/types.js"; |
| 24 | +import { readSnakeCaseParamRaw } from "../../param-key.js"; |
24 | 25 | import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js"; |
25 | 26 | import { resolveUserPath } from "../../utils.js"; |
26 | 27 | import type { DeliveryContext } from "../../utils/delivery-context.js"; |
@@ -124,7 +125,7 @@ const MusicGenerateToolSchema = Type.Object({
|
124 | 125 | }), |
125 | 126 | ), |
126 | 127 | durationSeconds: Type.Optional( |
127 | | -Type.Number({ |
| 128 | +Type.Integer({ |
128 | 129 | description: "Target seconds; provider may clamp.", |
129 | 130 | minimum: 1, |
130 | 131 | }), |
@@ -651,9 +652,15 @@ export function createMusicGenerateTool(options?: {
|
651 | 652 | const instrumental = readBooleanToolParam(args, "instrumental"); |
652 | 653 | const model = readStringParam(args, "model"); |
653 | 654 | const durationSeconds = readNumberParam(args, "durationSeconds", { |
654 | | -integer: true, |
| 655 | +positiveInteger: true, |
655 | 656 | strict: true, |
656 | 657 | }); |
| 658 | +if ( |
| 659 | +durationSeconds === undefined && |
| 660 | +readSnakeCaseParamRaw(args, "durationSeconds") !== undefined |
| 661 | +) { |
| 662 | +throw new ToolInputError("durationSeconds must be a positive integer"); |
| 663 | +} |
657 | 664 | const format = normalizeOutputFormat(readStringParam(args, "format")); |
658 | 665 | const filename = readStringParam(args, "filename"); |
659 | 666 | const timeout = normalizeMusicGenerationTimeoutMs(musicGenerationModelConfig.timeoutMs); |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。