comfyui-mcp
Version:
Local-first, agent-native control plane for ComfyUI — MCP server + autonomous sidebar agent that drives your live graph in natural language on ANY LLM: Claude/ChatGPT/Gemini on your subscription (no API key), free local models via Ollama (fully offline),
124 lines • 4.48 kB
JavaScript
import { createWorkflow } from "./workflow-composer.js";
import { DefaultsManager } from "./defaults-manager.js";
import { ValidationError } from "../utils/errors.js";
const DEFAULTABLE_KEYS = [
"seed",
"steps",
"cfg",
"sampler",
"scheduler",
"filename_prefix",
"unet",
"vae",
"clip_a",
"clip_b",
"lyrics",
"language",
"musical_key",
"shift",
"guidance_scale",
"bpm",
"timesignature",
"temperature",
"top_p",
"top_k",
"min_p",
"generate_audio_codes",
"audio_quality",
"checkpoint",
"clip",
"negative_prompt",
];
export async function generateAudio(args, deps) {
if (!args.prompt) {
throw new ValidationError("prompt is required for audio generation");
}
if (!args.duration || args.duration <= 0) {
throw new ValidationError("duration must be a positive number (in seconds)");
}
const seed = {};
for (const key of DEFAULTABLE_KEYS) {
const v = args[key];
if (v !== undefined)
seed[key] = v;
}
const resolved = DefaultsManager.apply(seed);
let checkpoint = resolved.checkpoint;
let unet = resolved.unet;
let vae = resolved.vae;
let clip = resolved.clip;
let clipA = resolved.clip_a;
let clipB = resolved.clip_b;
if (args.model_family === "ace_step_1.5") {
if (!unet)
unet = await deps.resolveFirstModel("diffusion_models");
if (!vae)
vae = await deps.resolveFirstModel("vae");
if (!clipA)
clipA = await deps.resolveFirstModel("text_encoders");
if (!unet) {
throw new ValidationError("No UNet model specified or found locally for ACE Step 1.5. " +
"Pass `unet` or download one via download_model.");
}
const workflow = createWorkflow("ace_step_15", {
unet,
vae: vae ?? "ace_1.5_vae.safetensors",
clip_a: clipA ?? "qwen_0.6b_ace15.safetensors",
clip_b: clipB ?? "qwen_4b_ace15.safetensors",
prompt: args.prompt,
lyrics: resolved.lyrics,
duration: args.duration,
seed: resolved.seed,
steps: resolved.steps,
cfg: resolved.cfg,
sampler_name: resolved.sampler,
scheduler: resolved.scheduler,
shift: resolved.shift,
language: resolved.language,
musical_key: resolved.musical_key,
guidance_scale: resolved.guidance_scale,
bpm: resolved.bpm,
timesignature: resolved.timesignature,
temperature: resolved.temperature,
top_p: resolved.top_p,
top_k: resolved.top_k,
min_p: resolved.min_p,
generate_audio_codes: resolved.generate_audio_codes,
audio_quality: resolved.audio_quality,
filename_prefix: resolved.filename_prefix,
});
const { prompt_id, queue_remaining, rejectedOutputs } = await deps.enqueue(workflow);
return { prompt_id, queue_remaining, rejectedOutputs, model_family: "ace_step_1.5" };
}
// Stable Audio 3
if (!checkpoint) {
const models = await deps.resolveFirstModel("checkpoints");
if (models)
checkpoint = models;
}
if (!clip)
clip = await deps.resolveFirstModel("text_encoders");
if (!checkpoint) {
throw new ValidationError("No checkpoint specified or found locally for Stable Audio 3. " +
"Pass `checkpoint` or download one via download_model.");
}
const workflow = createWorkflow("stable_audio_3", {
checkpoint,
clip: clip ?? "t5gemma_b_b_ul2.safetensors",
prompt: args.prompt,
negative_prompt: resolved.negative_prompt,
duration: args.duration,
seed: resolved.seed,
steps: resolved.steps,
cfg: resolved.cfg,
sampler_name: resolved.sampler,
scheduler: resolved.scheduler,
filename_prefix: resolved.filename_prefix,
// #1458 — passed through like the ace_step path. The audio generation tool
// ACCEPTS audio_quality; this family dropped it on the floor.
audio_quality: resolved.audio_quality,
});
const { prompt_id, queue_remaining, rejectedOutputs } = await deps.enqueue(workflow);
return { prompt_id, queue_remaining, rejectedOutputs, model_family: "stable_audio_3" };
}
//# sourceMappingURL=generate-audio.js.map