From 1117964ed6e74c052d8ade0709892606db5d50aa Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 11 May 2026 17:45:28 +0100 Subject: [PATCH] fix: keep music reference fetch timeout scoped --- src/agents/tools/music-generate-tool.test.ts | 20 +++++++++++++++++++- src/agents/tools/music-generate-tool.ts | 10 ++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/agents/tools/music-generate-tool.test.ts b/src/agents/tools/music-generate-tool.test.ts index 5b716cabf03..62f6e2db56e 100644 --- a/src/agents/tools/music-generate-tool.test.ts +++ b/src/agents/tools/music-generate-tool.test.ts @@ -3,6 +3,7 @@ import type { OpenClawConfig } from "../../config/config.js"; import * as mediaStore from "../../media/store.js"; import * as webMedia from "../../media/web-media.js"; import * as musicGenerationRuntime from "../../music-generation/runtime.js"; +import * as fetchTimeout from "../../utils/fetch-timeout.js"; import * as musicGenerateBackground from "./music-generate-background.js"; import { createMusicGenerateTool } from "./music-generate-tool.js"; @@ -103,6 +104,15 @@ vi.mock("../../media/web-media.js", async () => { }; }); vi.mock("../../music-generation/runtime.js", () => musicGenerationRuntimeMocks); +vi.mock("../../utils/fetch-timeout.js", async () => { + const actual = await vi.importActual( + "../../utils/fetch-timeout.js", + ); + return { + ...actual, + buildTimeoutAbortSignal: vi.fn(actual.buildTimeoutAbortSignal), + }; +}); vi.mock("./music-generate-background.js", () => musicGenerateBackgroundMocks); vi.mock("../../tasks/runtime-internal.js", () => taskRuntimeInternalMocks); vi.mock("../../tasks/detached-task-runtime.js", () => taskExecutorMocks); @@ -128,6 +138,7 @@ function resetMusicGenerateMocks() { mediaStoreMocks.saveMediaBuffer.mockReset(); taskRuntimeInternalMocks.listTasksForOwnerKey.mockReset(); taskRuntimeInternalMocks.listTasksForOwnerKey.mockReturnValue([]); + vi.mocked(fetchTimeout.buildTimeoutAbortSignal).mockClear(); taskExecutorMocks.createRunningTaskRun.mockReset(); taskExecutorMocks.completeTaskRunByRunId.mockReset(); taskExecutorMocks.failTaskRunByRunId.mockReset(); @@ -778,7 +789,7 @@ describe("createMusicGenerateTool", () => { config: asConfig({ agents: { defaults: { - musicGenerationModel: { primary: "minimax/music-2.6" }, + musicGenerationModel: { primary: "minimax/music-2.6", timeoutMs: 180_000 }, }, }, tools: { web: { fetch: { ssrfPolicy: { allowRfc2544BenchmarkRange: true } } } }, @@ -802,5 +813,12 @@ describe("createMusicGenerateTool", () => { }; expect(loadOptions.requestInit?.signal).toBeInstanceOf(AbortSignal); expect(loadOptions.ssrfPolicy).toEqual({ allowRfc2544BenchmarkRange: true }); + expect(generateMusicOptions().timeoutMs).toBe(180_000); + expect(fetchTimeout.buildTimeoutAbortSignal).toHaveBeenCalledTimes(1); + expect(vi.mocked(fetchTimeout.buildTimeoutAbortSignal).mock.calls[0]?.[0]).toMatchObject({ + operation: "music-generate.reference-fetch", + timeoutMs: 30_000, + url: "http://198.18.0.153/reference.png", + }); }); }); diff --git a/src/agents/tools/music-generate-tool.ts b/src/agents/tools/music-generate-tool.ts index d3a97e14ac6..022fa267768 100644 --- a/src/agents/tools/music-generate-tool.ts +++ b/src/agents/tools/music-generate-tool.ts @@ -638,10 +638,12 @@ export function createMusicGenerateTool(options?: { }); const format = normalizeOutputFormat(readStringParam(args, "format")); const filename = readStringParam(args, "filename"); - const requestedTimeoutMs = - readGenerationTimeoutMs(args) ?? musicGenerationModelConfig.timeoutMs; - const timeout = normalizeMusicGenerationTimeoutMs(requestedTimeoutMs); + const requestedTimeoutMs = readGenerationTimeoutMs(args); + const requestedGenerationTimeoutMs = + requestedTimeoutMs ?? musicGenerationModelConfig.timeoutMs; + const timeout = normalizeMusicGenerationTimeoutMs(requestedGenerationTimeoutMs); const timeoutMs = timeout.timeoutMs; + const referenceFetchTimeoutMs = requestedTimeoutMs === undefined ? undefined : timeoutMs; const imageInputs = normalizeReferenceImageInputs(args); const selectedModelRef = parseMusicGenerationModelRef(model) ?? @@ -660,7 +662,7 @@ export function createMusicGenerateTool(options?: { workspaceDir: options?.workspaceDir, sandboxConfig, ssrfPolicy: remoteMediaSsrfPolicy, - timeoutMs, + timeoutMs: referenceFetchTimeoutMs, }); validateMusicGenerationCapabilities({ provider: selectedProvider,