Files
jaidaken f09734b0ee
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Add custom nodes, Civitai loras (LFS), and vast.ai setup script
Includes 30 custom nodes committed directly, 7 Civitai-exclusive
loras stored via Git LFS, and a setup script that installs all
dependencies and downloads HuggingFace-hosted models on vast.ai.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:56:42 +00:00

124 lines
3.4 KiB
JavaScript

import { app } from "../../../scripts/app.js";
const REPEATER = "Repeater|pysssss";
app.registerExtension({
name: "pysssss.Repeater",
init() {
const graphToPrompt = app.graphToPrompt;
app.graphToPrompt = async function () {
const res = await graphToPrompt.apply(this, arguments);
const id = Date.now() + "_";
let u = 0;
let newNodes = {};
const newRepeaters = {};
for (const nodeId in res.output) {
let output = res.output[nodeId];
if (output.class_type === REPEATER) {
const isMulti = output.inputs.output === "multi";
if (output.inputs.node_mode === "create") {
// We need to clone the input for every repeat
const orig = res.output[output.inputs.source[0]];
if (isMulti) {
if (!newRepeaters[nodeId]) {
newRepeaters[nodeId] = [];
newRepeaters[nodeId][output.inputs.repeats - 1] = nodeId;
}
}
for (let i = 0; i < output.inputs.repeats - 1; i++) {
const clonedInputId = id + ++u;
if (isMulti) {
// If multi create we need to clone the repeater too
newNodes[clonedInputId] = structuredClone(orig);
output = structuredClone(output);
const clonedRepeaterId = id + ++u;
newNodes[clonedRepeaterId] = output;
output.inputs["source"][0] = clonedInputId;
newRepeaters[nodeId][i] = clonedRepeaterId;
} else {
newNodes[clonedInputId] = orig;
}
output.inputs[clonedInputId] = [clonedInputId, output.inputs.source[1]];
}
} else if (isMulti) {
newRepeaters[nodeId] = Array(output.inputs.repeats).fill(nodeId);
}
}
}
Object.assign(res.output, newNodes);
newNodes = {};
for (const nodeId in res.output) {
const output = res.output[nodeId];
for (const k in output.inputs) {
const v = output.inputs[k];
if (v instanceof Array) {
const repeaterId = v[0];
const source = newRepeaters[repeaterId];
if (source) {
v[0] = source.pop();
v[1] = 0;
}
}
}
}
// Object.assign(res.output, newNodes);
return res;
};
},
beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === REPEATER) {
const SETUP_OUTPUTS = Symbol();
nodeType.prototype[SETUP_OUTPUTS] = function (repeats) {
if (repeats == null) {
repeats = this.widgets[0].value;
}
while (this.outputs.length > repeats) {
this.removeOutput(repeats);
}
const id = Date.now() + "_";
let u = 0;
while (this.outputs.length < repeats) {
this.addOutput(id + ++u, "*", { label: "*" });
}
};
const onAdded = nodeType.prototype.onAdded;
nodeType.prototype.onAdded = function () {
const self = this;
const repeatsCb = this.widgets[0].callback;
this.widgets[0].callback = async function () {
const v = (await repeatsCb?.apply(this, arguments)) ?? this.value;
if (self.widgets[1].value === "multi") {
self[SETUP_OUTPUTS](v);
}
return v;
};
const outputCb = this.widgets[1].callback;
this.widgets[1].callback = async function () {
const v = (await outputCb?.apply(this, arguments)) ?? this.value;
if (v === "single") {
self.outputs[0].shape = 6;
self[SETUP_OUTPUTS](1);
} else {
delete self.outputs[0].shape;
self[SETUP_OUTPUTS]();
}
return v;
};
return onAdded?.apply(this, arguments);
};
}
},
});