fix(media): expose generation tools for configured runtime providers

Co-authored-by: openclaw-clawsweeper[bot] <280122609+openclaw-clawsweeper[bot]@users.noreply.github.com>
This commit is contained in:
clawsweeper[bot]
2026-04-30 22:46:55 -07:00
committed by GitHub
parent 9931603adb
commit e5fd9c0582
5 changed files with 65 additions and 1 deletions

View File

@@ -573,6 +573,7 @@ export function createImageGenerateTool(options?: {
cfg,
agentDir: options?.agentDir,
modelConfig: cfg.agents?.defaults?.imageGenerationModel,
providers: () => listRuntimeImageGenerationProviders({ config: cfg }),
providerKey: "imageGenerationProviders",
})
) {

View File

@@ -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();
});
});

View File

@@ -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,

View File

@@ -501,6 +501,7 @@ export function createMusicGenerateTool(options?: {
cfg,
agentDir: options?.agentDir,
modelConfig: cfg.agents?.defaults?.musicGenerationModel,
providers: () => listRuntimeMusicGenerationProviders({ config: cfg }),
providerKey: "musicGenerationProviders",
})
) {

View File

@@ -808,6 +808,7 @@ export function createVideoGenerateTool(options?: {
cfg,
agentDir: options?.agentDir,
modelConfig: cfg.agents?.defaults?.videoGenerationModel,
providers: () => listRuntimeVideoGenerationProviders({ config: cfg }),
providerKey: "videoGenerationProviders",
})
) {