fix: build disable payload from getlist state, not commit hash
Publish to Comfy registry / Publish Custom Node to registry (push) Has been cancelled
Publish to Comfy registry / Publish Custom Node to registry (push) Has been cancelled
The disable action failed for git/nightly-installed packs (e.g.
masquerade-nodes-comfyui): /customnode/installed reports a git commit hash
as the version and the cnr_id as id, but ComfyUI Manager's disable endpoint
needs the install *state version* ("nightly"/semver/"unknown") and the
directory name as id.
Switch fetchManagerInfo to /customnode/getlist (the unified list Manager's
own UI uses), key by directory name, and build the payload as
{id: dirname, version: state, files?: repo}. Eligibility/reconciliation now
key off pack state instead of an enabled flag.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+35
-21
@@ -257,11 +257,11 @@ function renderSection(title, subtitle, status, packages, managerInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A package can be disabled only if ComfyUI Manager knows it (by directory
|
// A package can be disabled only if ComfyUI Manager knows it (by directory
|
||||||
// name) and it is currently enabled (active on disk).
|
// name) and it is currently active (any state other than already-disabled).
|
||||||
function isDisableEligible(pkg, managerInfo) {
|
function isDisableEligible(pkg, managerInfo) {
|
||||||
if (!managerInfo || !pkg.installed) return false;
|
if (!managerInfo || !pkg.installed) return false;
|
||||||
const info = managerInfo[pkg.package];
|
const info = managerInfo[pkg.package];
|
||||||
return !!(info && info.enabled);
|
return !!(info && info.state && info.state !== "disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildModelsTabContent(modelData) {
|
function buildModelsTabContent(modelData) {
|
||||||
@@ -380,29 +380,43 @@ function buildTable(packages, status, withActions, managerInfo) {
|
|||||||
// ComfyUI Manager integration: disable unused node packages
|
// ComfyUI Manager integration: disable unused node packages
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Map of installed packages from ComfyUI Manager:
|
// Map of installed packages from ComfyUI Manager, keyed by directory name:
|
||||||
// { <dir name>: { ver, cnr_id, aux_id, enabled }, ... }
|
// { <dir name>: { id, version, files, state }, ... }
|
||||||
// Returns null when the Manager is not installed/reachable, in which case the
|
// We read the unified list (/customnode/getlist) rather than /customnode/installed
|
||||||
// disable UI is omitted entirely.
|
// because only the unified list reports the install *state version* the disable
|
||||||
|
// endpoint needs: "nightly" for git installs, the semver for registry installs,
|
||||||
|
// or "unknown". (/customnode/installed returns a raw git commit hash instead,
|
||||||
|
// which the disable endpoint rejects.) This mirrors what Manager's own UI sends.
|
||||||
|
// Returns null when the Manager is not installed/reachable, so the disable UI is
|
||||||
|
// omitted entirely.
|
||||||
async function fetchManagerInfo() {
|
async function fetchManagerInfo() {
|
||||||
try {
|
try {
|
||||||
const resp = await fetch("/customnode/installed");
|
const resp = await fetch("/customnode/getlist?mode=local&skip_update=true");
|
||||||
if (!resp.ok) return null;
|
if (!resp.ok) return null;
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
return data && typeof data === "object" ? data : null;
|
const packs = data && data.node_packs;
|
||||||
|
if (!packs || typeof packs !== "object") return null;
|
||||||
|
const info = {};
|
||||||
|
for (const [key, v] of Object.entries(packs)) {
|
||||||
|
if (!v || v.state === "not-installed") continue;
|
||||||
|
// For installed packs the key is the directory name — matches our package names.
|
||||||
|
info[key] = { id: v.id || key, version: v.version, files: v.files, state: v.state };
|
||||||
|
}
|
||||||
|
return info;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the payload ComfyUI Manager's /manager/queue/disable expects. CNR
|
// Build the payload ComfyUI Manager's /manager/queue/disable expects, mirroring
|
||||||
// (registry) packages are keyed by their cnr_id; everything else is treated as
|
// Manager's own frontend: id = directory name, version = install state
|
||||||
// "unknown" and keyed by directory name.
|
// ("nightly" / semver / "unknown"), and files (repo URL) only for "unknown".
|
||||||
function disablePayload(dirName, info) {
|
function disablePayload(dirName, info) {
|
||||||
if (info && info.cnr_id && info.ver && info.ver !== "unknown") {
|
const payload = { id: info.id || dirName, version: info.version, ui_id: dirName };
|
||||||
return { id: info.cnr_id, version: info.ver, ui_id: dirName };
|
if (info.version === "unknown") {
|
||||||
|
payload.files = info.files && info.files.length ? info.files : [dirName];
|
||||||
}
|
}
|
||||||
return { id: dirName, version: "unknown", files: [dirName], ui_id: dirName };
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
function wireDisableButtons(dialog, managerInfo) {
|
function wireDisableButtons(dialog, managerInfo) {
|
||||||
@@ -426,9 +440,9 @@ function wireDisableButtons(dialog, managerInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleDisable(pkgNames, dialog, managerInfo) {
|
async function handleDisable(pkgNames, dialog, managerInfo) {
|
||||||
// Only act on packages Manager still reports as enabled (guards against
|
// Only act on packages Manager still reports as active (guards against
|
||||||
// double-clicks and stale buttons after a partial batch).
|
// double-clicks and stale buttons after a partial batch).
|
||||||
pkgNames = pkgNames.filter((n) => managerInfo[n] && managerInfo[n].enabled);
|
pkgNames = pkgNames.filter((n) => managerInfo[n] && managerInfo[n].state !== "disabled");
|
||||||
if (pkgNames.length === 0) return;
|
if (pkgNames.length === 0) return;
|
||||||
|
|
||||||
const what = pkgNames.length === 1 ? `"${pkgNames[0]}"` : `${pkgNames.length} packages`;
|
const what = pkgNames.length === 1 ? `"${pkgNames[0]}"` : `${pkgNames.length} packages`;
|
||||||
@@ -451,13 +465,13 @@ async function handleDisable(pkgNames, dialog, managerInfo) {
|
|||||||
await runManagerDisable(payloads);
|
await runManagerDisable(payloads);
|
||||||
|
|
||||||
// Reconcile against Manager's actual state: a package is considered
|
// Reconcile against Manager's actual state: a package is considered
|
||||||
// disabled only if it's no longer reported as enabled on disk.
|
// disabled only if it's no longer reported as active on disk.
|
||||||
const after = await fetchManagerInfo();
|
const after = await fetchManagerInfo();
|
||||||
const isStillEnabled = (n) => after && after[n] && after[n].enabled;
|
const isStillActive = (n) => after && after[n] && after[n].state !== "disabled";
|
||||||
const succeeded = after ? pkgNames.filter((n) => !isStillEnabled(n)) : pkgNames;
|
const succeeded = after ? pkgNames.filter((n) => !isStillActive(n)) : pkgNames;
|
||||||
const failed = pkgNames.filter((n) => !succeeded.includes(n));
|
const failed = pkgNames.filter((n) => !succeeded.includes(n));
|
||||||
|
|
||||||
succeeded.forEach((n) => { if (managerInfo[n]) managerInfo[n].enabled = false; });
|
succeeded.forEach((n) => { if (managerInfo[n]) managerInfo[n].state = "disabled"; });
|
||||||
markPackagesDisabled(dialog, succeeded);
|
markPackagesDisabled(dialog, succeeded);
|
||||||
updateBulkButtons(dialog, managerInfo);
|
updateBulkButtons(dialog, managerInfo);
|
||||||
|
|
||||||
@@ -534,7 +548,7 @@ function updateBulkButtons(dialog, managerInfo) {
|
|||||||
dialog.querySelectorAll(".ns-disable-all-btn").forEach((btn) => {
|
dialog.querySelectorAll(".ns-disable-all-btn").forEach((btn) => {
|
||||||
let names = [];
|
let names = [];
|
||||||
try { names = JSON.parse(btn.dataset.pkgs); } catch { names = []; }
|
try { names = JSON.parse(btn.dataset.pkgs); } catch { names = []; }
|
||||||
const remaining = names.filter((n) => managerInfo[n] && managerInfo[n].enabled);
|
const remaining = names.filter((n) => managerInfo[n] && managerInfo[n].state !== "disabled");
|
||||||
if (remaining.length === 0) {
|
if (remaining.length === 0) {
|
||||||
btn.style.display = "none";
|
btn.style.display = "none";
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "comfyui-nodes-stats"
|
name = "comfyui-nodes-stats"
|
||||||
description = "Track usage statistics for all ComfyUI nodes and packages"
|
description = "Track usage statistics for all ComfyUI nodes and packages"
|
||||||
version = "1.2.0"
|
version = "1.2.1"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
|||||||
Reference in New Issue
Block a user