Files
2026-04-21 02:50:43 -04:00

124 lines
5.0 KiB
JavaScript

import { app } from "/scripts/app.js";
function generateRandomUuidV4() {
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
return crypto.randomUUID();
}
const randomBytes = new Uint8Array(16);
crypto.getRandomValues(randomBytes);
randomBytes[6] = (randomBytes[6] & 0x0f) | 0x40;
randomBytes[8] = (randomBytes[8] & 0x3f) | 0x80;
const hexByteStrings = Array.from(randomBytes, (byte) => byte.toString(16).padStart(2, "0"));
return (
hexByteStrings.slice(0, 4).join("") + "-" +
hexByteStrings.slice(4, 6).join("") + "-" +
hexByteStrings.slice(6, 8).join("") + "-" +
hexByteStrings.slice(8, 10).join("") + "-" +
hexByteStrings.slice(10, 16).join("")
);
}
// Non-serializable visual-only widget. Uses every marker ComfyUI versions
// inspect so it never contributes to widgets_values on save/load, which would
// otherwise scramble field values on reload.
function makeReadOnlyTextWidget(displayText, fontColorCss, fontStyleCss) {
return {
type: "info",
name: `__readonly__${displayText}`,
value: "",
options: { serialize: false },
serialize: false,
serializeValue() { return undefined; },
computeSize() { return [0, 18]; },
draw(ctx, node, widgetWidth, widgetYPosition, widgetHeight) {
ctx.save();
ctx.fillStyle = fontColorCss;
ctx.font = `${fontStyleCss} 12px sans-serif`;
ctx.textBaseline = "middle";
ctx.fillText(displayText, 10, widgetYPosition + widgetHeight * 0.5);
ctx.restore();
},
};
}
app.registerExtension({
name: "ClaudeCliVisionText.UuidAndHeaders",
async beforeRegisterNodeDef(nodeType, nodeData) {
if (nodeData?.name !== "ClaudeCliVisionText") {
return;
}
const originalOnNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function onNodeCreatedAppendOnly() {
const result = originalOnNodeCreated?.apply(this, arguments);
// We only APPEND widgets here (never splice into this.widgets at
// specific positions) so the widget order stays aligned with
// widgets_values on save/load. Defer UUID auto-fill to after
// onConfigure may have restored a saved value.
if (!this.__claudeCliEnhanced) {
this.__claudeCliEnhanced = true;
this.addWidget(
"button",
"Regenerate Session UUID",
null,
() => {
const sessionIdWidget = this.widgets?.find((w) => w.name === "session_id");
if (sessionIdWidget) {
sessionIdWidget.value = generateRandomUuidV4();
this.setDirtyCanvas(true, true);
}
},
{ serialize: false }
);
this.widgets.push(makeReadOnlyTextWidget(
"⚠ Regenerating creates a NEW session (~30k tokens cold-start).",
"#f6ad55",
"italic"
));
this.widgets.push(makeReadOnlyTextWidget(
"API Key — leave blank to use system OAuth credentials",
"#cbd5e0",
"bold"
));
}
// UUID auto-fill is deferred so any saved value from onConfigure
// is already applied by the time we look.
setTimeout(() => {
const sessionIdWidget = this.widgets?.find((w) => w.name === "session_id");
if (sessionIdWidget) {
sessionIdWidget.label = "Session UUID";
const currentValue = typeof sessionIdWidget.value === "string" ? sessionIdWidget.value.trim() : "";
if (!currentValue) {
sessionIdWidget.value = generateRandomUuidV4();
this.setDirtyCanvas(true, true);
}
}
}, 0);
return result;
};
},
});
app.registerExtension({
name: "SplitImageBatchToListOfImageBatches.StrideHint",
async beforeRegisterNodeDef(nodeType, nodeData) {
if (nodeData?.name !== "SplitImageBatchToListOfImageBatches") {
return;
}
const originalOnNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function onNodeCreatedAddStrideHint() {
const result = originalOnNodeCreated?.apply(this, arguments);
if (!this.__subBatchListStrideHintAdded) {
this.__subBatchListStrideHintAdded = true;
this.widgets.push(makeReadOnlyTextWidget(
"stride 0: stride = sub-batch size",
"#cbd5e0",
"italic"
));
}
return result;
};
},
});