Download ComfyUI-MiniMaxH3-Context-Loop/web/h3_kj_preview_bridge.js from dzmdd/Fast_deploy: direct link, hf CLI and curl.
- Browser
- Download file 2.95 kB
-
https://huggingface.co/dzmdd/Fast_deploy/resolve/main/ComfyUI-MiniMaxH3-Context-Loop/web/h3_kj_preview_bridge.js
- Command line
-
hf download hf://dzmdd/Fast_deploy/ComfyUI-MiniMaxH3-Context-Loop/web/h3_kj_preview_bridge.js
-
curl -L -o h3_kj_preview_bridge.js https://huggingface.co/dzmdd/Fast_deploy/resolve/main/ComfyUI-MiniMaxH3-Context-Loop/web/h3_kj_preview_bridge.js
2.95 kB
| import { app } from "../../scripts/app.js"; | |
| import { api } from "../../scripts/api.js"; | |
| import { | |
| H3_LOOP_END_TYPE, | |
| KJ_PREVIEW_TYPE, | |
| fallbackDisplayIds, | |
| recursiveRootId, | |
| } from "./h3_kj_preview_bridge_core.mjs?v=0.6.2"; | |
| const executionToDisplay = new Map(); | |
| // Mirrors ComfyUI's qualified-id lookup for nodes inside subgraphs. | |
| function findNodeByDisplayId(qid) { | |
| if (!app.graph || qid == null) return null; | |
| const parts = String(qid).split(":"); | |
| let graph = app.graph; | |
| for (let i = 0; i < parts.length - 1; i++) { | |
| const parentId = Number(parts[i]); | |
| if (!Number.isFinite(parentId)) return null; | |
| const parent = graph?.getNodeById?.(parentId); | |
| if (!parent?.subgraph) return null; | |
| graph = parent.subgraph; | |
| } | |
| const leafId = Number(parts.at(-1)); | |
| return Number.isFinite(leafId) ? graph?.getNodeById?.(leafId) ?? null : null; | |
| } | |
| function nodeType(node) { | |
| return node?.comfyClass ?? node?.type ?? null; | |
| } | |
| function belongsToH3Loop(executionId) { | |
| const rootId = recursiveRootId(executionId); | |
| return rootId != null && nodeType(findNodeByDisplayId(rootId)) === H3_LOOP_END_TYPE; | |
| } | |
| function rememberDisplayMapping(data) { | |
| if (data?.node == null || data?.display_node == null) return; | |
| const executionId = String(data.node); | |
| const displayId = String(data.display_node); | |
| if (executionId === displayId || !belongsToH3Loop(executionId)) return; | |
| if (nodeType(findNodeByDisplayId(displayId)) === KJ_PREVIEW_TYPE) { | |
| executionToDisplay.set(executionId, displayId); | |
| } | |
| } | |
| function resolvePreviewNode(executionId) { | |
| if (!belongsToH3Loop(executionId)) return null; | |
| const candidates = []; | |
| const mapped = executionToDisplay.get(executionId); | |
| if (mapped != null) candidates.push(mapped); | |
| candidates.push(...fallbackDisplayIds(executionId)); | |
| for (const displayId of candidates) { | |
| const node = findNodeByDisplayId(displayId); | |
| if (nodeType(node) === KJ_PREVIEW_TYPE) return node; | |
| } | |
| return null; | |
| } | |
| app.registerExtension({ | |
| name: "minimax_h3_context_loop.kj_preview_loop_bridge", | |
| setup() { | |
| api.addEventListener("execution_start", () => executionToDisplay.clear()); | |
| api.addEventListener("executing", (event) => rememberDisplayMapping(event.detail)); | |
| api.addEventListener("kj_preview_override", (event) => { | |
| const data = event.detail; | |
| if (data?.node_id == null) return; | |
| const executionId = String(data.node_id); | |
| // KJ handles ordinary canvas ids itself. We intervene only when its | |
| // source is a generated H3 recursion id that has no canvas node. | |
| if (findNodeByDisplayId(executionId)) return; | |
| const node = resolvePreviewNode(executionId); | |
| if (typeof node?._kjPreviewHandler === "function") { | |
| node._kjPreviewHandler(data); | |
| } | |
| }); | |
| }, | |
| }); | |