comfyui-mcp 0.52.68 → 0.52.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -16381,7 +16381,7 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
16381
16381
|
// and refuse to report freed:true when a device is still pinned.
|
|
16382
16382
|
return annotateFreeVramAck(ctx, res);
|
|
16383
16383
|
}),
|
|
16384
|
-
def("panel_show_media", "Display one or more images or
|
|
16384
|
+
def("panel_show_media", "Display one or more images, videos or AUDIO files directly in the panel chat. Use this whenever the user asks to SEE, SHOW, PLAY or HEAR a file — a disk path you composited/downloaded/generated (absolute path on the orchestrator host) OR a ComfyUI output ref ({ filename, subfolder?, type? }). Items are rendered as media cards in the agent chat area — audio gets a real player (.wav/.mp3/.flac/.ogg/.oga/.opus/.m4a/.aac), so a generated TTS or voice take is played back with this tool, not described; supply optional captions. You are never sent the audio yourself and cannot hear it. Max 8 items per call. A path item OVER the 20 MB inline cap that is not under any directory ComfyUI serves can still be shown by passing stage:true on that item — the orchestrator COPIES it into <output>/_panel_staged (an opt-in, persistent disk write; 512 MB per-file and 2 GB total caps) and displays the copy by reference. NEVER describe an image with emoji or text placeholders — call this tool instead.", {
|
|
16385
16385
|
items: z
|
|
16386
16386
|
.array(z.object({
|
|
16387
16387
|
// #1968 — OPTIONAL in the shape, required by normalizeShowMediaItem
|
|
@@ -16472,14 +16472,97 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
16472
16472
|
".m4v": "video/x-m4v",
|
|
16473
16473
|
".avi": "video/x-msvideo",
|
|
16474
16474
|
};
|
|
16475
|
-
// #
|
|
16476
|
-
//
|
|
16477
|
-
//
|
|
16478
|
-
//
|
|
16479
|
-
//
|
|
16480
|
-
//
|
|
16481
|
-
|
|
16475
|
+
// #1572 — audio was refused outright ("unsupported file type \".wav\""),
|
|
16476
|
+
// so a TTS/voice-clone session could not play a generated take back to
|
|
16477
|
+
// the user at all. Nothing else was missing: the panel has shipped a
|
|
16478
|
+
// real `<audio controls>` card since #710 (paintAudio, its own
|
|
16479
|
+
// AUDIO_EXTENSIONS allowlist, an "audible" disclosure in the reply, and
|
|
16480
|
+
// media persistence under mkind:"audio"), and composeShowMediaReply
|
|
16481
|
+
// already routes kind:"audio" to it and skips the video storyboard for
|
|
16482
|
+
// it. THIS gate was the only closed door.
|
|
16483
|
+
//
|
|
16484
|
+
// The set is the panel renderer's own AUDIO_EXTENSIONS, verbatim —
|
|
16485
|
+
// the gate's job is to refuse what the card cannot present, so the
|
|
16486
|
+
// card's allowlist is the authoritative answer. It is a superset of
|
|
16487
|
+
// what this codebase already calls audio elsewhere (upload_image
|
|
16488
|
+
// action:"audio" and services/image-management's AUDIO_MIME:
|
|
16489
|
+
// .wav/.mp3/.flac/.ogg/.m4a/.aac) and of what ComfyUI's own save nodes
|
|
16490
|
+
// actually write (comfy_api AudioSaveHelper._FORMATS is
|
|
16491
|
+
// {flac, mp3, opus} and it names the file `…_00001.<format>`, so
|
|
16492
|
+
// SaveAudio/SaveAudioMP3/SaveAudioOpus/SaveAudioAdvanced emit exactly
|
|
16493
|
+
// .flac/.mp3/.opus; .wav is what VHS and the TTS packs write).
|
|
16494
|
+
//
|
|
16495
|
+
// Deliberately NARROWER than the orchestrator's own AUDIO_MIME_BY_EXT
|
|
16496
|
+
// (audio-attachment.ts), which additionally lists webm/weba/wave/m4b/
|
|
16497
|
+
// mpga/mp2: `.webm` is ALREADY in VIDEO_EXTS above and claiming it as
|
|
16498
|
+
// audio here would demote an existing video card, and the rest are not
|
|
16499
|
+
// in the panel's renderer set — admitting them would pass this gate only
|
|
16500
|
+
// to reach a link card, i.e. widen the allowlist without widening what
|
|
16501
|
+
// can be shown.
|
|
16502
|
+
const AUDIO_EXTS = new Set([
|
|
16503
|
+
".wav",
|
|
16504
|
+
".mp3",
|
|
16505
|
+
".flac",
|
|
16506
|
+
".ogg",
|
|
16507
|
+
".oga",
|
|
16508
|
+
".opus",
|
|
16509
|
+
".m4a",
|
|
16510
|
+
".aac",
|
|
16511
|
+
]);
|
|
16512
|
+
// MEASURED in Chromium against real ffmpeg-encoded files served as
|
|
16513
|
+
// `data:` URLs, not derived from a table — the same failure #811 fixed
|
|
16514
|
+
// for video bites harder here, because a data URL's declared type is
|
|
16515
|
+
// the ONLY type the browser gets and a wrong one is refused before any
|
|
16516
|
+
// decoder runs ("MEDIA_ELEMENT_ERROR: Unable to load URL due to content
|
|
16517
|
+
// type"). Two entries would have been wrong if copied from elsewhere in
|
|
16518
|
+
// this codebase:
|
|
16519
|
+
// - `.opus` → `audio/opus` (what audio-attachment.ts uses, and the
|
|
16520
|
+
// natural guess) is REFUSED by Chromium; `audio/ogg` decodes. That
|
|
16521
|
+
// matters because .opus is a core ComfyUI SaveAudio output.
|
|
16522
|
+
// - `.flac` → `audio/x-flac` is REFUSED; `audio/flac` decodes.
|
|
16523
|
+
const AUDIO_MIME = {
|
|
16524
|
+
".wav": "audio/wav",
|
|
16525
|
+
".mp3": "audio/mpeg",
|
|
16526
|
+
".flac": "audio/flac",
|
|
16527
|
+
".ogg": "audio/ogg",
|
|
16528
|
+
".oga": "audio/ogg",
|
|
16529
|
+
".opus": "audio/ogg",
|
|
16530
|
+
".m4a": "audio/mp4",
|
|
16531
|
+
".aac": "audio/aac",
|
|
16532
|
+
};
|
|
16482
16533
|
const MAX_BYTES = 20 * 1024 * 1024; // 20 MB
|
|
16534
|
+
// Capability refusal must be a preflight, before the loop can perform
|
|
16535
|
+
// the opt-in stage:true filesystem write. A mixed batch such as a
|
|
16536
|
+
// staged image followed by audio must not leave a persistent copy when
|
|
16537
|
+
// a proven-old panel will refuse the audio item. The same preflight also
|
|
16538
|
+
// keeps local audio out of the known headless clients: they have no
|
|
16539
|
+
// audio painter, and #2018's honest accounting cannot make an absent
|
|
16540
|
+
// player render the item.
|
|
16541
|
+
const panelCompatibility = {
|
|
16542
|
+
reading: tabPanelVersionReading(ctx),
|
|
16543
|
+
advertisedKinds: tabAdvertisedShowMediaKinds(ctx),
|
|
16544
|
+
};
|
|
16545
|
+
const knownAudioItems = [];
|
|
16546
|
+
const knownAudioPaths = [];
|
|
16547
|
+
for (const item of items) {
|
|
16548
|
+
const src = item.source;
|
|
16549
|
+
const filename = "path" in src ? src.path : src.filename;
|
|
16550
|
+
if (AUDIO_EXTS.has(extname(filename).toLowerCase())) {
|
|
16551
|
+
knownAudioItems.push({ kind: "audio", filename });
|
|
16552
|
+
if ("path" in src)
|
|
16553
|
+
knownAudioPaths.push(filename);
|
|
16554
|
+
}
|
|
16555
|
+
}
|
|
16556
|
+
if (knownAudioItems.length > 0) {
|
|
16557
|
+
const blocked = showMediaItemsPanelCannotPaint(knownAudioItems, panelCompatibility);
|
|
16558
|
+
if (blocked.length > 0) {
|
|
16559
|
+
return fail(formatShowMediaKindUnsupported(blocked));
|
|
16560
|
+
}
|
|
16561
|
+
if (knownAudioPaths.length > 0 && resolveClientKind(ctx).kind === "headless") {
|
|
16562
|
+
return fail("panel_show_media cannot send audio to this headless client: it has no audio player. " +
|
|
16563
|
+
"Use an interactive ComfyUI browser panel tab to play the audio instead.");
|
|
16564
|
+
}
|
|
16565
|
+
}
|
|
16483
16566
|
const resolved = [];
|
|
16484
16567
|
/** Oversized items that took the /view reference route instead (#648). */
|
|
16485
16568
|
const forwarded = [];
|
|
@@ -16537,8 +16620,16 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
16537
16620
|
mime = VIDEO_MIME[ext];
|
|
16538
16621
|
kind = "video";
|
|
16539
16622
|
}
|
|
16623
|
+
else if (AUDIO_EXTS.has(ext)) {
|
|
16624
|
+
mime = AUDIO_MIME[ext];
|
|
16625
|
+
kind = "audio";
|
|
16626
|
+
}
|
|
16540
16627
|
else {
|
|
16541
|
-
|
|
16628
|
+
// Still an explicit ALLOWLIST, and still the whole gate: anything
|
|
16629
|
+
// not named in one of the three sets above is refused here, before
|
|
16630
|
+
// its bytes are read. Widening it by three more extensions is not
|
|
16631
|
+
// a licence to sniff or to fall back to a denylist.
|
|
16632
|
+
return fail("unsupported file type \"" + ext + "\" (allowed: " + [...IMAGE_EXTS, ...VIDEO_EXTS, ...AUDIO_EXTS].join(", ") + "): " + p);
|
|
16542
16633
|
}
|
|
16543
16634
|
if (stat.size > MAX_BYTES) {
|
|
16544
16635
|
// Too big to INLINE is not the same as too big to SHOW. When the
|
|
@@ -16696,8 +16787,7 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
16696
16787
|
// panel that omitted the field is never told to update. Image/video
|
|
16697
16788
|
// skip the check entirely.
|
|
16698
16789
|
const blocked = showMediaItemsPanelCannotPaint(resolved, {
|
|
16699
|
-
|
|
16700
|
-
advertisedKinds: tabAdvertisedShowMediaKinds(ctx),
|
|
16790
|
+
...panelCompatibility,
|
|
16701
16791
|
});
|
|
16702
16792
|
if (blocked.length > 0) {
|
|
16703
16793
|
return fail(formatShowMediaKindUnsupported(blocked));
|