import { beforeAll, describe, expect, it } from "vitest"; import { resolveOpenClawAgentDir } from "../../src/agents/agent-paths.js"; import { isLiveTestEnabled } from "../../src/agents/live-test-helpers.js"; import { loadConfig } from "../../src/config/config.js"; import { createTestPluginApi } from "../../test/helpers/plugins/plugin-api.js"; import plugin from "./index.js"; import { getComfyConfig, isComfyCapabilityConfigured } from "./workflow-runtime.js"; const LIVE = isLiveTestEnabled(["COMFY_LIVE_TEST"]) && (process.env.COMFY_LIVE_TEST ?? "").trim() === "1"; const describeLive = LIVE ? describe : describe.skip; type RegisteredMusicProvider = { id: string; generateMusic: Function; isConfigured?: Function; }; function withPluginsEnabled(cfg: T): T { if (!cfg || typeof cfg !== "object") { return cfg; } const record = cfg as Record; return { ...record, plugins: { ...(record.plugins && typeof record.plugins === "object" ? record.plugins : {}), enabled: true, }, } as T; } describeLive("comfy live", () => { let cfg = {} as ReturnType; let agentDir = ""; const imageProviders: Array<{ id: string; generateImage: Function; isConfigured?: Function }> = []; const musicProviders: RegisteredMusicProvider[] = []; const videoProviders: Array<{ id: string; generateVideo: Function; isConfigured?: Function }> = []; beforeAll(async () => { cfg = withPluginsEnabled(loadConfig()); agentDir = resolveOpenClawAgentDir(); await plugin.register( createTestPluginApi({ config: cfg as never, registerImageGenerationProvider(provider) { imageProviders.push(provider as never); }, registerMusicGenerationProvider(provider) { musicProviders.push(provider as never); }, registerVideoGenerationProvider(provider) { videoProviders.push(provider as never); }, }), ); }); it.skipIf(!isComfyCapabilityConfigured({ cfg: cfg as never, agentDir, capability: "image" }))( "runs an image workflow", async () => { const provider = imageProviders.find((entry) => entry.id === "comfy"); expect(provider).toBeDefined(); const result = await provider!.generateImage({ provider: "comfy", model: "workflow", prompt: "A tiny orange lobster icon on a clean background.", cfg: cfg as never, agentDir, }); expect(result.images.length).toBeGreaterThan(0); expect(result.images[0]?.mimeType.startsWith("image/")).toBe(true); expect(result.images[0]?.buffer.byteLength).toBeGreaterThan(128); }, 120_000, ); it.skipIf(!isComfyCapabilityConfigured({ cfg: cfg as never, agentDir, capability: "video" }))( "runs a video workflow", async () => { const provider = videoProviders.find((entry) => entry.id === "comfy"); expect(provider).toBeDefined(); const result = await provider!.generateVideo({ provider: "comfy", model: "workflow", prompt: "A tiny paper lobster gently waving, cinematic motion.", cfg: cfg as never, agentDir, }); expect(result.videos.length).toBeGreaterThan(0); expect(result.videos[0]?.mimeType.startsWith("video/")).toBe(true); expect(result.videos[0]?.buffer.byteLength).toBeGreaterThan(512); }, 180_000, ); it.skipIf(!isComfyCapabilityConfigured({ cfg: cfg as never, agentDir, capability: "music" }))( "runs a music workflow", async () => { const provider = musicProviders.find((entry) => entry.id === "comfy"); expect(provider).toBeDefined(); const result = await provider!.generateMusic({ provider: "comfy", model: "workflow", prompt: "A gentle ambient synth loop with warm analog pads.", cfg: cfg as never, agentDir, }); expect(result.tracks.length).toBeGreaterThan(0); expect(result.tracks[0]?.mimeType.startsWith("audio/")).toBe(true); expect(result.tracks[0]?.buffer.byteLength).toBeGreaterThan(512); }, 180_000, ); it("documents the effective comfy config shape for live debugging", () => { const comfyConfig = getComfyConfig(cfg as never); expect(typeof comfyConfig).toBe("object"); }); });