From 0836bfd57393f8fdc6c5ac4de31d041d310548b6 Mon Sep 17 00:00:00 2001 From: Maxed-Out-99 Date: Sat, 8 Aug 2026 05:58:03 -0700 Subject: [PATCH] Keep the three published latent node keys loadable Load Latent MXD, Load Latent Batch MXD and Save Latent MXD kept their display names through the VACE/I2V consolidation but changed mapping key (LoadLatent_WithParams -> LoadLatent_I2V_MXD, and so on). ComfyUI matches saved workflows by key, so on the next release a workflow built against the published version would show a red missing-node box despite a node of the same name shipping in the pack. Registers the three old keys as thin DEPRECATED subclasses of the current classes. Deprecated nodes are kept out of the frontend search menu, and the aliases get no display name, so old workflows load silently without adding duplicate entries to node search. 65 registered keys now = 62 real nodes + 3 hidden aliases. Re-baselined. Co-Authored-By: Claude Opus 5 --- nodes/wan22/latent_io.py | 37 +++++++ scripts/node_schema_baseline.json | 165 +++++++++++++++++++++++++++++- 2 files changed, 201 insertions(+), 1 deletion(-) diff --git a/nodes/wan22/latent_io.py b/nodes/wan22/latent_io.py index 1fdb54e..880d265 100644 --- a/nodes/wan22/latent_io.py +++ b/nodes/wan22/latent_io.py @@ -8,6 +8,10 @@ Registered nodes: LoadLatents_FromFolder_I2V_Pipe_MXD Load Latent Batch Pipe MXD LatentPipeUnpack_MXD Unpack Latent Pipe MXD +Plus three DEPRECATED legacy-key aliases (LoadLatent_WithParams, +LoadLatents_FromFolder_WithParams, SaveLatentMXD) so workflows saved against +the previously published keys still load. See the note above the mappings. + Route: GET /mxd/latents/files (fresh re-scan for the run_folder queuing loop). Latents are stored under /latents. Each .latent embeds the source @@ -1311,6 +1315,33 @@ class LatentPipeUnpack_MXD: ) +######################################################################################################################## +# Legacy key aliases +# +# These three nodes were published under different mapping keys before the +# VACE/I2V latent nodes were consolidated. ComfyUI matches saved workflows by +# MAPPING KEY, not display name, so without these a workflow built against the +# released version shows a red missing-node box even though a node with the +# identical name ships right here. +# +# Thin subclasses rather than extra entries pointing at the same class, so +# DEPRECATED lands only on the alias: the frontend keeps deprecated nodes out +# of the search menu (there is a setting to show them), which means old +# workflows load silently without cluttering search with duplicates. +# +# Do not "clean these up" — deleting one re-breaks every workflow using it. +class LoadLatent_WithParams(LoadLatent_I2V_MXD): + DEPRECATED = True + + +class LoadLatents_FromFolder_WithParams(LoadLatents_FromFolder_I2V_MXD): + DEPRECATED = True + + +class SaveLatentMXD(SaveLatent_I2V_MXD): + DEPRECATED = True + + NODE_CLASS_MAPPINGS = { "SaveLatent_I2V_MXD": SaveLatent_I2V_MXD, "LoadLatent_I2V_MXD": LoadLatent_I2V_MXD, @@ -1318,8 +1349,14 @@ NODE_CLASS_MAPPINGS = { "LoadLatent_I2V_Pipe_MXD": LoadLatent_I2V_Pipe_MXD, "LoadLatents_FromFolder_I2V_Pipe_MXD": LoadLatents_FromFolder_I2V_Pipe_MXD, "LatentPipeUnpack_MXD": LatentPipeUnpack_MXD, + # Legacy keys — see the note above. + "LoadLatent_WithParams": LoadLatent_WithParams, + "LoadLatents_FromFolder_WithParams": LoadLatents_FromFolder_WithParams, + "SaveLatentMXD": SaveLatentMXD, } +# The legacy aliases deliberately get NO display name — an unnamed, DEPRECATED +# node stays out of the search menu entirely. NODE_DISPLAY_NAME_MAPPINGS = { "SaveLatent_I2V_MXD": "Save Latent MXD", "LoadLatent_I2V_MXD": "Load Latent MXD", diff --git a/scripts/node_schema_baseline.json b/scripts/node_schema_baseline.json index df69546..6d73ca3 100644 --- a/scripts/node_schema_baseline.json +++ b/scripts/node_schema_baseline.json @@ -1,5 +1,5 @@ { - "node_count": 62, + "node_count": 65, "nodes": { "BboxDetectorCombinedBatchMXD": { "category": "MXD/Detector", @@ -1327,6 +1327,65 @@ "MXD_LATENT_PIPE" ] }, + "LoadLatent_WithParams": { + "category": "MXD/Latents", + "class": "LoadLatent_WithParams", + "display_name": null, + "function": "load", + "input_types": { + "required": { + "latent": { + "type": { + "combo": "empty", + "dynamic": true + } + }, + "refresh_before_run": { + "config": { + "default": false, + "tooltip": "When run_folder is on, re-scan the latents folder for new files right before the queuing loop starts, instead of using the dropdown list as of whenever it was last populated. Use this when another workflow is still writing latents into this folder as you queue this one." + }, + "type": "BOOLEAN" + }, + "run_folder": { + "config": { + "default": false, + "tooltip": "When enabled, hitting Queue Prompt auto-queues every latent in this file's folder, one after another, instead of just the selected file." + }, + "type": "BOOLEAN" + } + } + }, + "output_node": false, + "return_names": [ + "shift", + "positive", + "negative", + "samples", + "steps", + "cfg", + "sampler_name", + "scheduler", + "end_at_step", + "filename_prefix", + "trim_latent", + "high_workflow" + ], + "return_types": [ + "FLOAT", + "CONDITIONING", + "CONDITIONING", + "LATENT", + "INT", + "FLOAT", + "['euler', 'euler_cfg_pp', 'euler_ancestral', 'euler_ancestral_cfg_pp', 'heun', 'heunpp2', 'exp_heun_2_x0', 'exp_heun_2_x0_sde', 'dpm_2', 'dpm_2_ancestral', 'lms', 'dpm_fast', 'dpm_adaptive', 'dpmpp_2s_ancestral', 'dpmpp_2s_ancestral_cfg_pp', 'dpmpp_sde', 'dpmpp_sde_gpu', 'dpmpp_2m', 'dpmpp_2m_cfg_pp', 'dpmpp_2m_sde', 'dpmpp_2m_sde_gpu', 'dpmpp_2m_sde_heun', 'dpmpp_2m_sde_heun_gpu', 'dpmpp_3m_sde', 'dpmpp_3m_sde_gpu', 'ddpm', 'lcm', 'ipndm', 'ipndm_v', 'deis', 'res_multistep', 'res_multistep_cfg_pp', 'res_multistep_ancestral', 'res_multistep_ancestral_cfg_pp', 'gradient_estimation', 'gradient_estimation_cfg_pp', 'er_sde', 'seeds_2', 'seeds_3', 'sa_solver', 'sa_solver_pece', 'ddim', 'uni_pc', 'uni_pc_bh2']", + "['simple', 'sgm_uniform', 'karras', 'exponential', 'ddim_uniform', 'beta', 'normal', 'linear_quadratic', 'kl_optimal']", + "INT", + "STRING", + "INT", + "STRING" + ] + }, "LoadLatents_FromFolder_I2V_MXD": { "category": "MXD/Latents", "class": "LoadLatents_FromFolder_I2V_MXD", @@ -1393,6 +1452,49 @@ "MXD_LATENT_PIPE" ] }, + "LoadLatents_FromFolder_WithParams": { + "category": "MXD/Latents", + "class": "LoadLatents_FromFolder_WithParams", + "display_name": null, + "function": "load_batch_i2v", + "input_types": { + "required": { + "subfolder": { + "type": { + "combo": "nonempty", + "dynamic": true + } + } + } + }, + "output_node": false, + "return_names": [ + "shift", + "positive", + "negative", + "samples", + "steps", + "cfg", + "sampler_name", + "scheduler", + "end_at_step", + "filename_prefix", + "trim_latent" + ], + "return_types": [ + "FLOAT", + "CONDITIONING", + "CONDITIONING", + "LATENT", + "INT", + "FLOAT", + "['euler', 'euler_cfg_pp', 'euler_ancestral', 'euler_ancestral_cfg_pp', 'heun', 'heunpp2', 'exp_heun_2_x0', 'exp_heun_2_x0_sde', 'dpm_2', 'dpm_2_ancestral', 'lms', 'dpm_fast', 'dpm_adaptive', 'dpmpp_2s_ancestral', 'dpmpp_2s_ancestral_cfg_pp', 'dpmpp_sde', 'dpmpp_sde_gpu', 'dpmpp_2m', 'dpmpp_2m_cfg_pp', 'dpmpp_2m_sde', 'dpmpp_2m_sde_gpu', 'dpmpp_2m_sde_heun', 'dpmpp_2m_sde_heun_gpu', 'dpmpp_3m_sde', 'dpmpp_3m_sde_gpu', 'ddpm', 'lcm', 'ipndm', 'ipndm_v', 'deis', 'res_multistep', 'res_multistep_cfg_pp', 'res_multistep_ancestral', 'res_multistep_ancestral_cfg_pp', 'gradient_estimation', 'gradient_estimation_cfg_pp', 'er_sde', 'seeds_2', 'seeds_3', 'sa_solver', 'sa_solver_pece', 'ddim', 'uni_pc', 'uni_pc_bh2']", + "['simple', 'sgm_uniform', 'karras', 'exponential', 'ddim_uniform', 'beta', 'normal', 'linear_quadratic', 'kl_optimal']", + "INT", + "STRING", + "INT" + ] + }, "LoadVideoFromFolderMXD": { "category": "MXD/Video", "class": "LoadVideoFromFolderMXD", @@ -2076,6 +2178,67 @@ "STRING" ] }, + "SaveLatentMXD": { + "category": "MXD/Latents", + "class": "SaveLatentMXD", + "display_name": null, + "function": "save_only", + "input_types": { + "hidden": { + "extra_pnginfo": { + "type": "EXTRA_PNGINFO" + }, + "prompt": { + "type": "PROMPT" + }, + "unique_id": { + "type": "UNIQUE_ID" + } + }, + "optional": { + "trim_latent": { + "config": { + "default": 0, + "max": 10000, + "min": 0, + "step": 1, + "tooltip": "VACE 2.2 trim_latent value to preserve with this latent. Usually 0 or 1. Ignored for t2v/i2v." + }, + "type": "INT" + } + }, + "required": { + "filename_prefix": { + "config": { + "default": "ComfyUI", + "tooltip": "Prefix for saved files" + }, + "type": "STRING" + }, + "negative": { + "config": { + "tooltip": "Negative CONDITIONING to save alongside the latent." + }, + "type": "CONDITIONING" + }, + "positive": { + "config": { + "tooltip": "Positive CONDITIONING to save alongside the latent." + }, + "type": "CONDITIONING" + }, + "samples": { + "config": { + "tooltip": "Latent to save." + }, + "type": "LATENT" + } + } + }, + "output_node": true, + "return_names": null, + "return_types": [] + }, "SaveLatent_I2V_MXD": { "category": "MXD/Latents", "class": "SaveLatent_I2V_MXD",