Registers the node, gives it a widget card and the shared preview panel with a FIND tool that runs the node alone, a readout of how many things matched and how sure SAM 3 was, and the stop message on the node's own face. A stopped run shows the plain picture, not the last find. Each name asks SAM 3 for up to 16 matches, and Sureness starts at 0.7.
49 lines
2.1 KiB
JavaScript
49 lines
2.1 KiB
JavaScript
// Resolving ComfyUI execution ids to graph nodes.
|
|
//
|
|
// Kept free of /scripts/app.js imports so node:test can cover it
|
|
// (tests/graph_ids.test.mjs); callers pass the root graph in.
|
|
|
|
// ComfyUI identifies a node inside a subgraph by its execution id: the chain
|
|
// of subgraph node ids that reaches it, colon-joined ("12:3" is node 3 inside
|
|
// the subgraph node 12 holds). Only the last segment is a real graph node id,
|
|
// and ids are numbered independently inside each subgraph, so looking the
|
|
// bare tail up on the root graph does not merely miss - it can return a
|
|
// completely unrelated top-level node that happens to share the number.
|
|
// Walking the chain is the only way to answer correctly; an id that does not
|
|
// resolve returns null, because acting on the wrong node is worse than doing
|
|
// nothing at all.
|
|
export function nodeByExecutionId(rootGraph, executionId) {
|
|
const parts = String(executionId ?? "")
|
|
.split(":")
|
|
.filter((part) => part !== "");
|
|
if (!parts.length) return null;
|
|
let graph = rootGraph ?? null;
|
|
for (const part of parts.slice(0, -1)) {
|
|
const holder = graph?.getNodeById?.(Number(part)) ?? graph?.getNodeById?.(part);
|
|
graph = holder?.subgraph ?? null;
|
|
if (!graph) return null;
|
|
}
|
|
const tail = parts[parts.length - 1];
|
|
return graph?.getNodeById?.(Number(tail)) ?? graph?.getNodeById?.(tail) ?? null;
|
|
}
|
|
|
|
// The other way round: a node's execution id, found by walking from the root
|
|
// graph down through the boxes (subgraph nodes) that hold it. This is what a
|
|
// run of one node alone has to name. A box that is used twice gives its first
|
|
// use; a node that is on no graph gives null.
|
|
export function executionIdOf(rootGraph, node) {
|
|
if (!rootGraph || !node) return null;
|
|
const walk = (graph, prefix, depth) => {
|
|
const nodes = graph?.nodes ?? graph?._nodes ?? [];
|
|
if (nodes.includes(node)) return `${prefix}${node.id}`;
|
|
if (depth > 16) return null;
|
|
for (const holder of nodes) {
|
|
if (!holder?.subgraph) continue;
|
|
const found = walk(holder.subgraph, `${prefix}${holder.id}:`, depth + 1);
|
|
if (found) return found;
|
|
}
|
|
return null;
|
|
};
|
|
return walk(rootGraph, "", 0);
|
|
}
|