Files
DemonGatanjieu-Anomalous_Mo…/web/modules/sampler_inputs.js
T
DemonGatanjieuandClaude Opus 5.5 7a59068ebb A picture kept as a combo keeps its nodes, every value as it was
Keep -> Its combo now saves the nodes upstream of the picture's samplers' model and prompt
inputs (loaders, LoRA chains, CLIP skip, both prompts) as a node-structure combo, values
untouched; models are named by where they are here, missing ones kept by the picture's name.
A workflow without a sampler still gives the simple combo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:37:46 +08:00

47 lines
2.2 KiB
JavaScript

/**
* The part of a workflow that makes a sampler's model and prompts (what a combo kept from an
* output image holds): every node upstream of a sampler's model / positive / negative /
* conditioning inputs — model and CLIP loaders, LoRA chains, CLIP skip and model patches, the
* prompt nodes — but not the sampler itself, nor anything reached only through an image,
* latent or mask (image loaders, sizes, VAE decoding). A sampler is a node with a model input
* and a positive or conditioning input (KSampler, KSampler Advanced, CFG / Basic guiders).
* No DOM; `graph` is a LiteGraph graph (or anything with nodes and getLink / links).
*/
const FEEDS = new Set(['model', 'positive', 'negative', 'conditioning']);
const CUT = new Set(['IMAGE', 'LATENT', 'MASK']);
const inputNames = node => (node.inputs || []).map(input => input?.name);
/** Whether `node` is a sampler (or a guider) whose model and prompts a combo keeps. */
export function isSampler(node) {
const names = inputNames(node);
return names.includes('model') && (names.includes('positive') || names.includes('conditioning'));
}
/** The nodes upstream of the samplers' model and prompt inputs, in the graph's order. */
export function samplerSideNodes(graph) {
const nodes = graph?._nodes || graph?.nodes || [];
const byId = new Map(nodes.map(node => [node.id, node]));
const linkOf = id => graph.getLink?.(id) ?? graph.links?.[id] ?? null;
const samplers = new Set(nodes.filter(isSampler).map(node => node.id));
const kept = new Set();
const waiting = [];
const follow = (input) => {
if (input?.link == null) return;
const link = linkOf(input.link);
if (!link || CUT.has(String(link.type ?? input.type ?? '').toUpperCase())) return;
waiting.push(link.origin_id);
};
for (const id of samplers) {
for (const input of byId.get(id).inputs || []) if (FEEDS.has(input?.name)) follow(input);
}
while (waiting.length) {
const id = waiting.pop();
if (kept.has(id) || samplers.has(id) || !byId.has(id)) continue;
kept.add(id);
for (const input of byId.get(id).inputs || []) follow(input);
}
return nodes.filter(node => kept.has(node.id));
}