Files
ComfyUI-Tenaciousload/web/tenaciousload.js
T
Ethanfel ed322c9ec2 feat: disabled mode (TENACIOUSLOAD_DISABLED=1) — no-op but keep the loading bar
A one-flag kill-switch: when set, the pack installs no middleware, registers no
refresh routes, computes no fingerprint and exposes no graph node — ComfyUI runs
exactly as if it weren't installed. Only the read-only /tenaciousload/status
route stays so the loading-screen overlay still shows (a generic 'Loading node
definitions…' bar, since there's no build to track). The refresh menu buttons
hide themselves when status reports enabled:false.

Useful for A/B testing or as a safety kill-switch. Requires a restart (the
middleware is installed at startup). Unit-tested both modes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 20:52:43 +02:00

104 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
let busy = false;
function notify(severity, detail, life = 6000) {
const toast = app.extensionManager?.toast;
if (toast?.add) {
toast.add({ severity, summary: "Tenaciousload", detail, life });
} else if (severity === "error") {
alert("Tenaciousload: " + detail);
}
console[severity === "error" ? "error" : "log"]("[Tenaciousload]", detail);
}
async function runRefresh(mode, extra) {
if (busy) {
notify("warn", "A refresh is already running…");
return;
}
busy = true;
const label =
mode === "quick" ? "Quick refresh (changed folders)" :
mode === "register" ? "Registering file(s)" : "Full refresh (rescan all)";
notify("info", `${label} — rebuilding model lists… this can take a moment.`, 10000);
try {
// 1) run the chosen refresh mode on the server
const res = await api.fetchApi("/tenaciousload/refresh", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ mode, ...(extra || {}) }),
});
const data = await res.json().catch(() => ({}));
// 2) rebuild + re-cache object_info (the slow build, if any)
await api.fetchApi("/object_info?nocache=1").then((r) => r.arrayBuffer());
// 3) update open dropdowns live if supported
try { await app.refreshComboInNodes?.(); } catch (e) { /* non-fatal */ }
let detail = "Done — new models are available (reload the page if a dropdown still looks stale).";
if (mode === "register") {
detail = `Registered ${data.added || 0} file(s)` +
(data.skipped ? `, ${data.skipped} not found on disk` : "") + ". " + detail;
} else if (mode === "quick") {
const dirs = (data.folders || []).reduce((a, f) => a + (f.scanned || 0), 0);
detail = `Quick scan: ${dirs} folder(s) rescanned. ` + detail;
}
notify("success", detail, 8000);
} catch (e) {
notify("error", "Refresh failed: " + (e?.message || e), 10000);
} finally {
busy = false;
}
}
async function doRegister() {
const folder = (prompt("Model folder type (loras, checkpoints, vae, …):", "loras") || "").trim();
if (!folder) return;
const raw = prompt(
`New file path(s) relative to the '${folder}' folder\n(comma- or newline-separated, e.g. mypack/newlora.safetensors):`,
"",
);
if (!raw) return;
const files = raw.split(/[\n,]+/).map((s) => s.trim()).filter(Boolean);
if (!files.length) return;
await runRefresh("register", { folder, files });
}
// Skip the refresh buttons entirely when Tenaciousload is disabled.
let _tlEnabled = true;
try {
const r = await api.fetchApi("/tenaciousload/status");
if (r.ok) _tlEnabled = (await r.json()).enabled !== false;
} catch (e) { /* assume enabled */ }
if (_tlEnabled) app.registerExtension({
name: "Tenaciousload.Refresh",
commands: [
{
id: "Tenaciousload.quick",
label: "⚡ Quick refresh (changed folders)",
icon: "pi pi-bolt",
function: () => runRefresh("quick"),
},
{
id: "Tenaciousload.full",
label: "🔄 Full refresh (rescan all models/LoRAs)",
icon: "pi pi-refresh",
function: () => runRefresh("full"),
},
{
id: "Tenaciousload.register",
label: " Register new model file…",
icon: "pi pi-plus",
function: doRegister,
},
],
menuCommands: [
{
path: ["Extensions"],
commands: ["Tenaciousload.quick", "Tenaciousload.full", "Tenaciousload.register"],
},
],
});