diff --git a/src/agents/tools/image-generate-tool.ts b/src/agents/tools/image-generate-tool.ts index d4d552c5742..a6a9afccb66 100644 --- a/src/agents/tools/image-generate-tool.ts +++ b/src/agents/tools/image-generate-tool.ts @@ -573,6 +573,7 @@ export function createImageGenerateTool(options?: { cfg, agentDir: options?.agentDir, modelConfig: cfg.agents?.defaults?.imageGenerationModel, + providers: () => listRuntimeImageGenerationProviders({ config: cfg }), providerKey: "imageGenerationProviders", }) ) { diff --git a/src/agents/tools/media-tool-shared.test.ts b/src/agents/tools/media-tool-shared.test.ts index 0d229e6b54c..6297eee9048 100644 --- a/src/agents/tools/media-tool-shared.test.ts +++ b/src/agents/tools/media-tool-shared.test.ts @@ -1,7 +1,11 @@ import path from "node:path"; import { pathToFileURL } from "node:url"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { resolveMediaToolLocalRoots, resolveModelFromRegistry } from "./media-tool-shared.js"; +import { + hasGenerationToolAvailability, + resolveMediaToolLocalRoots, + resolveModelFromRegistry, +} from "./media-tool-shared.js"; function normalizeHostPath(value: string): string { return path.normalize(path.resolve(value)); @@ -98,3 +102,48 @@ describe("resolveModelFromRegistry", () => { expect(result).toBe(foundModel); }, 180_000); }); + +describe("hasGenerationToolAvailability", () => { + it("allows generation tools for runtime providers configured without auth", () => { + expect( + hasGenerationToolAvailability({ + providerKey: "imageGenerationProviders", + providers: [ + { + id: "local-image", + defaultModel: "workflow", + isConfigured: () => true, + }, + ], + }), + ).toBe(true); + }); + + it("omits generation tools when runtime providers are not configured", () => { + expect( + hasGenerationToolAvailability({ + providerKey: "imageGenerationProviders", + providers: [ + { + id: "local-image", + defaultModel: "workflow", + isConfigured: () => false, + }, + ], + }), + ).toBe(false); + }); + + it("keeps explicit model config sufficient for generation tool registration", () => { + const loadProviders = vi.fn(() => []); + + expect( + hasGenerationToolAvailability({ + providerKey: "imageGenerationProviders", + modelConfig: { primary: "local-image/workflow" }, + providers: loadProviders, + }), + ).toBe(true); + expect(loadProviders).not.toHaveBeenCalled(); + }); +}); diff --git a/src/agents/tools/media-tool-shared.ts b/src/agents/tools/media-tool-shared.ts index 1dd981fd43d..9fa414e0432 100644 --- a/src/agents/tools/media-tool-shared.ts +++ b/src/agents/tools/media-tool-shared.ts @@ -281,11 +281,23 @@ export function hasGenerationToolAvailability(params: { cfg?: OpenClawConfig; agentDir?: string; modelConfig?: AgentModelConfig; + providers?: CapabilityProvider[] | (() => CapabilityProvider[]); providerKey: GenerationCapabilityProviderKey; }): boolean { if (hasToolModelConfig(coerceToolModelConfig(params.modelConfig))) { return true; } + const providers = typeof params.providers === "function" ? params.providers() : params.providers; + if (providers) { + return providers.some((provider) => + isCapabilityProviderConfigured({ + providers, + provider, + cfg: params.cfg, + agentDir: params.agentDir, + }), + ); + } return resolveBundledCapabilityProviderIds({ key: params.providerKey, cfg: params.cfg, diff --git a/src/agents/tools/music-generate-tool.ts b/src/agents/tools/music-generate-tool.ts index 603f90f250e..f187d5fe3b1 100644 --- a/src/agents/tools/music-generate-tool.ts +++ b/src/agents/tools/music-generate-tool.ts @@ -501,6 +501,7 @@ export function createMusicGenerateTool(options?: { cfg, agentDir: options?.agentDir, modelConfig: cfg.agents?.defaults?.musicGenerationModel, + providers: () => listRuntimeMusicGenerationProviders({ config: cfg }), providerKey: "musicGenerationProviders", }) ) { diff --git a/src/agents/tools/video-generate-tool.ts b/src/agents/tools/video-generate-tool.ts index f59f8558d8e..3ba6dd4f390 100644 --- a/src/agents/tools/video-generate-tool.ts +++ b/src/agents/tools/video-generate-tool.ts @@ -808,6 +808,7 @@ export function createVideoGenerateTool(options?: { cfg, agentDir: options?.agentDir, modelConfig: cfg.agents?.defaults?.videoGenerationModel, + providers: () => listRuntimeVideoGenerationProviders({ config: cfg }), providerKey: "videoGenerationProviders", }) ) {