Download ComfyUI-MiniMaxH3-Context-Loop/web/h3_plan_upgrade_core.mjs from dzmdd/Fast_deploy: direct link, hf CLI and curl.
- Browser
- Download file 3.93 kB
-
https://huggingface.co/dzmdd/Fast_deploy/resolve/main/ComfyUI-MiniMaxH3-Context-Loop/web/h3_plan_upgrade_core.mjs
- Command line
-
hf download hf://dzmdd/Fast_deploy/ComfyUI-MiniMaxH3-Context-Loop/web/h3_plan_upgrade_core.mjs
-
curl -L -o h3_plan_upgrade_core.mjs https://huggingface.co/dzmdd/Fast_deploy/resolve/main/ComfyUI-MiniMaxH3-Context-Loop/web/h3_plan_upgrade_core.mjs
3.93 kB
| export const LEGACY_PLAN_NODE = "MiniMaxH3ChainPlan"; | |
| export const MODERN_PLAN_NODE = "MiniMaxH3ChainPlanModern"; | |
| export const MODERN_PLAN_WIDGET_NAMES = Object.freeze([ | |
| "plan_json", "run_name", "generation_fingerprint", "width", "height", | |
| "encode_mode", "crop", "default_duration_seconds", "default_steps", | |
| "base_seed", "segment_crf", "video_blend_frames", | |
| ]); | |
| function graphLink(graph, id) { | |
| if (id == null) return null; | |
| return graph?.links?.[id] ?? graph?.links?.get?.(id) ?? null; | |
| } | |
| function inputConnected(node, name) { | |
| const input = node?.inputs?.find((item) => item.name === name); | |
| return input?.link !== null && input?.link !== undefined; | |
| } | |
| function widgetValue(node, name) { | |
| return node?.widgets?.find((item) => item.name === name)?.value; | |
| } | |
| function cloneSerializable(value, fallback) { | |
| try { | |
| return typeof structuredClone === "function" | |
| ? structuredClone(value) : JSON.parse(JSON.stringify(value)); | |
| } catch (_error) { | |
| return fallback; | |
| } | |
| } | |
| /** Replace one legacy Plan without interpreting its positional widget array. | |
| * | |
| * Connections and supported values are resolved by name. The caller owns all | |
| * confirmation/error UI so this helper remains testable without ComfyUI's DOM. | |
| */ | |
| export function upgradeLegacyPlanNode(node, { | |
| createNode, | |
| confirmUpgrade = () => true, | |
| } = {}) { | |
| const graph = node?.graph; | |
| if (!graph || typeof createNode !== "function") { | |
| return {ok:false, reason:"create_unavailable"}; | |
| } | |
| if (!inputConnected(node, "chain_policy")) { | |
| return {ok:false, reason:"policy_required"}; | |
| } | |
| if (!confirmUpgrade()) return {ok:false, reason:"cancelled"}; | |
| const incoming = (node.inputs ?? []).map((input) => { | |
| const link = graphLink(graph, input.link); | |
| return link ? { | |
| name: input.name, | |
| originId: link.origin_id, | |
| originSlot: link.origin_slot, | |
| } : null; | |
| }).filter(Boolean); | |
| const outgoing = []; | |
| for (const output of node.outputs ?? []) { | |
| for (const linkId of output.links ?? []) { | |
| const link = graphLink(graph, linkId); | |
| if (link) outgoing.push({ | |
| name: output.name, | |
| targetId: link.target_id, | |
| targetSlot: link.target_slot, | |
| }); | |
| } | |
| } | |
| const replacement = createNode(MODERN_PLAN_NODE); | |
| if (!replacement) return {ok:false, reason:"modern_unregistered"}; | |
| for (const name of MODERN_PLAN_WIDGET_NAMES) { | |
| const value = widgetValue(node, name); | |
| if (value === undefined) continue; | |
| const widget = replacement.widgets?.find((item) => item.name === name); | |
| if (widget) widget.value = value; | |
| } | |
| replacement.pos = Array.isArray(node.pos) ? [...node.pos] : node.pos; | |
| replacement.properties = cloneSerializable(node.properties, {}); | |
| replacement.color = node.color; | |
| replacement.bgcolor = node.bgcolor; | |
| replacement.mode = node.mode; | |
| graph.add(replacement); | |
| if (node.size != null) { | |
| replacement.setSize?.( | |
| Array.isArray(node.size) ? [...node.size] : node.size); | |
| } | |
| graph.remove(node); | |
| for (const item of incoming) { | |
| const origin = graph.getNodeById?.(item.originId); | |
| const targetSlot = replacement.inputs?.findIndex( | |
| (input) => input.name === item.name); | |
| if (origin && targetSlot >= 0) { | |
| origin.connect?.(item.originSlot, replacement, targetSlot); | |
| } | |
| } | |
| for (const item of outgoing) { | |
| const target = graph.getNodeById?.(item.targetId); | |
| const originSlot = replacement.outputs?.findIndex( | |
| (output) => output.name === item.name); | |
| if (target && originSlot >= 0) { | |
| replacement.connect?.(originSlot, target, item.targetSlot); | |
| } | |
| } | |
| graph.setDirtyCanvas?.(true, true); | |
| return {ok:true, node:replacement}; | |
| } | |