comfyui-mcp 0.51.54 → 0.51.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/orchestrator/panel-tools.js +170 -32
- package/dist/orchestrator/panel-tools.js.map +1 -1
- package/dist/services/manifest.js +42 -13
- package/dist/services/manifest.js.map +1 -1
- package/dist/services/model-resolver.js +28 -12
- package/dist/services/model-resolver.js.map +1 -1
- package/package.json +7 -3
- package/packs/qwen-image-edit/pack.yaml +1 -1
- package/packs/wan-longer-videos-i2v/manifest.yaml +1 -1
- package/packs/wan-longer-videos-i2v/pack.yaml +8 -6
- package/packs/wan-longer-videos-i2v-96gb/install-runpod.sh +1 -1
- package/packs/wan-longer-videos-i2v-96gb/install-windows.bat +1 -1
- package/packs/wan-longer-videos-i2v-96gb/pack.yaml +13 -10
- package/packs/wan-longer-videos-t2v/manifest.yaml +1 -1
- package/packs/wan-longer-videos-t2v/pack.yaml +8 -6
- package/packs/wan-longer-videos-t2v-96gb/install-runpod.sh +1 -1
- package/packs/wan-longer-videos-t2v-96gb/install-windows.bat +1 -1
- package/packs/wan-longer-videos-t2v-96gb/pack.yaml +17 -13
- package/packs/wan-longer-videos-v2v/manifest.yaml +1 -1
- package/packs/wan-longer-videos-v2v/pack.yaml +7 -5
- package/packs/wan-longer-videos-v2v-96gb/install-runpod.sh +1 -1
- package/packs/wan-longer-videos-v2v-96gb/install-windows.bat +1 -1
- package/packs/wan-longer-videos-v2v-96gb/pack.yaml +13 -10
- package/packs/wan-transparent-img2vid/pack.yaml +3 -3
- package/packs/wan-transparent-img2vid-96gb/install-runpod.sh +1 -1
- package/packs/wan-transparent-img2vid-96gb/install-windows.bat +1 -1
- package/packs/wan-transparent-img2vid-96gb/pack.yaml +12 -8
- package/scripts/asset-counts.mjs +15 -0
- package/scripts/check-blog-boilerplate.mjs +222 -0
- package/scripts/check-blog-packs.mjs +243 -0
- package/scripts/check-blog-staleness.mjs +242 -0
- package/scripts/check-blog-structure.mjs +139 -0
- package/scripts/check-docs-deployed.mjs +145 -0
- package/scripts/check-docs-locale.mjs +57 -2
|
@@ -1154,8 +1154,52 @@ export function classifyTabReconnect({ serverReady, baselineCaptured, tabBack, }
|
|
|
1154
1154
|
return "unknown"; // never watched — the server never came back
|
|
1155
1155
|
return baselineCaptured ? false : "unknown";
|
|
1156
1156
|
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Is `restart_comfyui` aimed at the same ComfyUI this panel is on? (#851, #1233)
|
|
1159
|
+
*
|
|
1160
|
+
* Extracted from restartTimeoutFallbackAdvice for #1593, which needs the same
|
|
1161
|
+
* DECISION with different wording. The alternative was a second comparison
|
|
1162
|
+
* somewhere else, and two readers of the same evidence that can disagree is the
|
|
1163
|
+
* defect #851 itself was: a call that recommends another tool without checking
|
|
1164
|
+
* which machine that tool points at.
|
|
1165
|
+
*
|
|
1166
|
+
* - `same` — provably one instance. Recommending the headless tool is safe.
|
|
1167
|
+
* - `different`— PROVEN two. `proven` names the panel's side. Recommending the
|
|
1168
|
+
* headless tool would aim a restart at the wrong server, which on
|
|
1169
|
+
* a shared instance is worse than doing nothing.
|
|
1170
|
+
* - `unproven` — no proof either way. Recommend it, and say what was not checked.
|
|
1171
|
+
*
|
|
1172
|
+
* Nothing here is new logic; the branches and their reasons are documented at
|
|
1173
|
+
* their original site below and are unchanged.
|
|
1174
|
+
*/
|
|
1175
|
+
export function classifyRestartFallbackTarget({ headlessBase, panelBase, observedOrigin = null, }) {
|
|
1176
|
+
if (panelBase != null && sameHttpBase(headlessBase, panelBase))
|
|
1177
|
+
return { kind: "same" };
|
|
1178
|
+
const dnsAmbiguous = (u) => {
|
|
1179
|
+
if (!u)
|
|
1180
|
+
return false;
|
|
1181
|
+
try {
|
|
1182
|
+
return new URL(u).hostname.toLowerCase().replace(/^\[|\]$/g, "") === "localhost";
|
|
1183
|
+
}
|
|
1184
|
+
catch {
|
|
1185
|
+
return false;
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
const originMismatch = observedOrigin != null &&
|
|
1189
|
+
!dnsAmbiguous(observedOrigin) &&
|
|
1190
|
+
!dnsAmbiguous(headlessBase) &&
|
|
1191
|
+
!sameHttpOrigin(headlessBase, observedOrigin)
|
|
1192
|
+
? observedOrigin
|
|
1193
|
+
: null;
|
|
1194
|
+
const proven = panelBase ?? originMismatch;
|
|
1195
|
+
return proven != null ? { kind: "different", proven } : { kind: "unproven" };
|
|
1196
|
+
}
|
|
1157
1197
|
export function restartTimeoutFallbackAdvice({ headlessBase, panelBase, observedOrigin = null, }) {
|
|
1158
|
-
|
|
1198
|
+
// The DECISION lives in classifyRestartFallbackTarget (above) so #1593's refusal
|
|
1199
|
+
// reaches the same verdict rather than re-deriving it. The prose below, and the
|
|
1200
|
+
// reasoning attached to each branch, is unchanged.
|
|
1201
|
+
const verdict = classifyRestartFallbackTarget({ headlessBase, panelBase, observedOrigin });
|
|
1202
|
+
if (verdict.kind === "same") {
|
|
1159
1203
|
return "or use restart_comfyui to restart the server directly without a panel card.";
|
|
1160
1204
|
}
|
|
1161
1205
|
// Proven different: either the proof resolved a base that differs, or the observed
|
|
@@ -1175,26 +1219,9 @@ export function restartTimeoutFallbackAdvice({ headlessBase, panelBase, observed
|
|
|
1175
1219
|
// is very likely the same instance. Absence of proof is not proof of difference, so
|
|
1176
1220
|
// an ambiguous host degrades to UNPROVEN — the same direction captureRebootHealthBase
|
|
1177
1221
|
// takes for the same input.
|
|
1178
|
-
|
|
1179
|
-
if (!u)
|
|
1180
|
-
return false;
|
|
1181
|
-
try {
|
|
1182
|
-
return new URL(u).hostname.toLowerCase().replace(/^\[|\]$/g, "") === "localhost";
|
|
1183
|
-
}
|
|
1184
|
-
catch {
|
|
1185
|
-
return false;
|
|
1186
|
-
}
|
|
1187
|
-
};
|
|
1188
|
-
const originMismatch = observedOrigin != null &&
|
|
1189
|
-
!dnsAmbiguous(observedOrigin) &&
|
|
1190
|
-
!dnsAmbiguous(headlessBase) &&
|
|
1191
|
-
!sameHttpOrigin(headlessBase, observedOrigin)
|
|
1192
|
-
? observedOrigin
|
|
1193
|
-
: null;
|
|
1194
|
-
const proven = panelBase ?? originMismatch;
|
|
1195
|
-
if (proven != null) {
|
|
1222
|
+
if (verdict.kind === "different") {
|
|
1196
1223
|
return (`Do NOT reach for restart_comfyui here without checking: it targets ${headlessBase}, ` +
|
|
1197
|
-
`while this panel is running inside ${proven}. Restarting the first would hit a ` +
|
|
1224
|
+
`while this panel is running inside ${verdict.proven}. Restarting the first would hit a ` +
|
|
1198
1225
|
"different server than the one you have been working on. That may find nothing there " +
|
|
1199
1226
|
"at all — or it may SUCCEED and take down a ComfyUI you did not mean to touch, which " +
|
|
1200
1227
|
"on a shared instance is the worse outcome.");
|
|
@@ -1203,6 +1230,63 @@ export function restartTimeoutFallbackAdvice({ headlessBase, panelBase, observed
|
|
|
1203
1230
|
"card — check that this is the same ComfyUI you have been working on, since I " +
|
|
1204
1231
|
"could not confirm which one this panel is running inside.");
|
|
1205
1232
|
}
|
|
1233
|
+
/**
|
|
1234
|
+
* #1593 — WHAT TO TELL A CALLER WHOSE PANEL RESTART WAS REFUSED.
|
|
1235
|
+
*
|
|
1236
|
+
* The #814 refusal ends "USE restart_comfyui INSTEAD", unconditionally. #851 is
|
|
1237
|
+
* the record of why an unconditional recommendation is a defect: `restart_comfyui`
|
|
1238
|
+
* targets COMFYUI_URL, not the ComfyUI the panel is running inside, and a reporter
|
|
1239
|
+
* who followed exactly that advice aimed a restart at a different machine.
|
|
1240
|
+
*
|
|
1241
|
+
* #851 fixed the branch it was filed against — the confirmation-card timeout — and
|
|
1242
|
+
* that fix has been sitting next door ever since, never consulted here. This is
|
|
1243
|
+
* the same evidence reaching the branch a user is far more likely to hit, because
|
|
1244
|
+
* the refusal fires whenever the panel's instance cannot be accounted for, which is
|
|
1245
|
+
* precisely when the two addresses are most likely to differ.
|
|
1246
|
+
*
|
|
1247
|
+
* The three answers are not cosmetic variations:
|
|
1248
|
+
*
|
|
1249
|
+
* different — the handoff is PROVEN bad, and the old text recommended it anyway.
|
|
1250
|
+
* This is the case that matters: on a shared instance, aiming a
|
|
1251
|
+
* restart at the wrong server is worse than doing nothing.
|
|
1252
|
+
* unproven — recommend it, and NAME what was not established, rather than
|
|
1253
|
+
* implying a check that did not happen.
|
|
1254
|
+
* same — NOT REACHABLE FROM EITHER REFUSAL, and deliberately kept anyway.
|
|
1255
|
+
* Both call sites are guarded by `!bound`, and `bound` is the same
|
|
1256
|
+
* predicate as this verdict (panelBase != null && sameHttpBase(...)),
|
|
1257
|
+
* so a refusal that fires has already excluded `same`. It is not a
|
|
1258
|
+
* user-visible branch and must not be described as one. It stays
|
|
1259
|
+
* because this function is TOTAL over the classifier's three
|
|
1260
|
+
* verdicts: a future caller whose boundness test is not that exact
|
|
1261
|
+
* predicate would otherwise fall through to the "unproven" text and
|
|
1262
|
+
* claim a check failed that in fact succeeded. A tripwire in this
|
|
1263
|
+
* branch is not hit by any of the handler-driven tests.
|
|
1264
|
+
*
|
|
1265
|
+
* Both addresses are named in every branch. The refusal previously named neither,
|
|
1266
|
+
* so the reader could not tell which two things had failed to be shown equal —
|
|
1267
|
+
* #1593's reporter had to paraphrase the address back to us.
|
|
1268
|
+
*/
|
|
1269
|
+
export function restartRefusalHandoffAdvice(args) {
|
|
1270
|
+
const verdict = classifyRestartFallbackTarget(args);
|
|
1271
|
+
if (verdict.kind === "same") {
|
|
1272
|
+
return (`USE restart_comfyui INSTEAD: it is not tied to a browser tab — it acts on ` +
|
|
1273
|
+
`${args.headlessBase}, which this panel is PROVABLY on, and which it CAN identify and ` +
|
|
1274
|
+
`check before stopping. That handoff is verified here, not assumed.`);
|
|
1275
|
+
}
|
|
1276
|
+
if (verdict.kind === "different") {
|
|
1277
|
+
return (`Do NOT reach for restart_comfyui here: it targets ${args.headlessBase}, while this ` +
|
|
1278
|
+
`panel is running inside ${verdict.proven} — a DIFFERENT server, so it would restart ` +
|
|
1279
|
+
`something you have not been working on. That may find nothing there at all, or it may ` +
|
|
1280
|
+
`SUCCEED and take down a ComfyUI you did not mean to touch. Restart this one from ` +
|
|
1281
|
+
`whatever launches it (its own launcher, the Desktop app, or your terminal).`);
|
|
1282
|
+
}
|
|
1283
|
+
return (`USE restart_comfyui INSTEAD: unlike this panel-scoped restart, it is not tied to a ` +
|
|
1284
|
+
`browser tab — it acts on the ComfyUI this server is configured for ` +
|
|
1285
|
+
`(${args.headlessBase}), which it CAN identify and check before stopping. I could NOT ` +
|
|
1286
|
+
`confirm that this is the same ComfyUI this panel is running inside, so check that ` +
|
|
1287
|
+
`before you run it. Or restart ComfyUI from whatever launches it (its own launcher, ` +
|
|
1288
|
+
`the Desktop app, or your terminal).`);
|
|
1289
|
+
}
|
|
1206
1290
|
/**
|
|
1207
1291
|
* Node definitions from the ComfyUI the PANEL is connected to (#1359 / #1006).
|
|
1208
1292
|
*
|
|
@@ -7710,7 +7794,10 @@ export function buildPanelToolDefs() {
|
|
|
7710
7794
|
"plus a node-type summary for INSPECTION / EXECUTION / REBUILD — it does NOT and CANNOT load the " +
|
|
7711
7795
|
"result back onto the canvas (the canvas only loads UI-format graphs). Use it to understand an " +
|
|
7712
7796
|
"expert workflow's real wiring, run the resolved graph headless, or rebuild connections with the " +
|
|
7713
|
-
"graph edit tools. The resolved graph is much smaller than the raw UI JSON."
|
|
7797
|
+
"graph edit tools. The resolved graph is much smaller than the raw UI JSON. The reply is TWO " +
|
|
7798
|
+
"blocks — the summary and any conversion notes first, then the graph alone as a whole JSON " +
|
|
7799
|
+
"document — and the same graph is returned as structuredContent.graph, so nothing has to be " +
|
|
7800
|
+
"sliced out of prose to parse it.", {
|
|
7714
7801
|
pack: z
|
|
7715
7802
|
.string()
|
|
7716
7803
|
.optional()
|
|
@@ -7803,7 +7890,25 @@ export function buildPanelToolDefs() {
|
|
|
7803
7890
|
.sort((a, b) => b[1] - a[1])
|
|
7804
7891
|
.map(([t, c]) => `${c}× ${t}`)
|
|
7805
7892
|
.join(", ");
|
|
7806
|
-
|
|
7893
|
+
// #1589 — THE GRAPH IS NOW ITS OWN CONTENT BLOCK, and its own
|
|
7894
|
+
// `structuredContent.graph`.
|
|
7895
|
+
//
|
|
7896
|
+
// It used to be string-concatenated onto the end of the summary, so the
|
|
7897
|
+
// single text block began "Stripped to N nodes" and `JSON.parse` of it
|
|
7898
|
+
// failed on the first character. Every programmatic caller had to find the
|
|
7899
|
+
// first `{` and slice — a heuristic that is wrong the moment a conversion
|
|
7900
|
+
// note quotes a brace, which the warning lines can and do (they name
|
|
7901
|
+
// widget values).
|
|
7902
|
+
//
|
|
7903
|
+
// The PROSE ORDER IS UNCHANGED on purpose. #361 put the conversion notes
|
|
7904
|
+
// ahead of the graph so a model reads "this differs from the source"
|
|
7905
|
+
// before the thing it differs from; moving the JSON first to make
|
|
7906
|
+
// `content[0]` parse would have traded a script's convenience for the
|
|
7907
|
+
// reader's warning. Splitting instead keeps both: block 0 is the same
|
|
7908
|
+
// sentence it always was, block 1 is a whole JSON document with nothing
|
|
7909
|
+
// before or after it, and `structuredContent` is the parsed form for
|
|
7910
|
+
// callers that read it.
|
|
7911
|
+
const proseSummary = `Stripped to ${Object.keys(workflow).length} nodes` +
|
|
7807
7912
|
(warnings.length ? ` · ⚠ ${warnings.length} conversion note(s)` : "") +
|
|
7808
7913
|
`\nNode types: ${summary}` +
|
|
7809
7914
|
// #361: a strip that quietly loses a Set/Get link or substitutes a
|
|
@@ -7814,8 +7919,26 @@ export function buildPanelToolDefs() {
|
|
|
7814
7919
|
? `\nThe stripped graph DIFFERS from the source workflow where listed below — read these before running or rebuilding from it:\n${warnings
|
|
7815
7920
|
.map((w) => `- ${w}`)
|
|
7816
7921
|
.join("\n")}`
|
|
7817
|
-
: "")
|
|
7818
|
-
|
|
7922
|
+
: "");
|
|
7923
|
+
// Annotated, not inferred. `def()`'s handler type is enough for TS to accept
|
|
7924
|
+
// this object but NOT to reject a key ToolResult does not declare — excess-
|
|
7925
|
+
// property checking does not survive the inferred return type (measured: with
|
|
7926
|
+
// `structuredContent` deleted from ToolResult, `tsc --noEmit` still exited 0).
|
|
7927
|
+
// A typed local restores it, so the field is a contract the compiler enforces
|
|
7928
|
+
// rather than a comment.
|
|
7929
|
+
const reply = {
|
|
7930
|
+
content: [
|
|
7931
|
+
{ type: "text", text: proseSummary },
|
|
7932
|
+
{ type: "text", text: JSON.stringify(workflow, null, 2) },
|
|
7933
|
+
],
|
|
7934
|
+
structuredContent: {
|
|
7935
|
+
graph: workflow,
|
|
7936
|
+
node_count: Object.keys(workflow).length,
|
|
7937
|
+
node_types: hist,
|
|
7938
|
+
warnings,
|
|
7939
|
+
},
|
|
7940
|
+
};
|
|
7941
|
+
return reply;
|
|
7819
7942
|
}),
|
|
7820
7943
|
def("panel_flatten_workflow", "Flatten the user's workflow IN PLACE, preserving their layout: every Get/Set bus, Reroute, and " +
|
|
7821
7944
|
"cg-use-everywhere (UE) broadcast is resolved into a direct real link, and the virtual nodes are " +
|
|
@@ -10331,17 +10454,25 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
10331
10454
|
// A claim about what I DID, not about a server I have just said I cannot
|
|
10332
10455
|
// identify: "it is still running" would be exactly the unvalidated
|
|
10333
10456
|
// assertion the stale-target rule forbids (r8).
|
|
10334
|
-
"again. Nothing was dispatched, so nothing was stopped.
|
|
10457
|
+
"again. Nothing was dispatched, so nothing was stopped. " +
|
|
10335
10458
|
// The alternative is NAMED and the difference EXPLAINED (coordinator
|
|
10336
10459
|
// ruling): this tool restarts whatever the calling TAB fronts, which is
|
|
10337
10460
|
// exactly the thing that could not be identified here. restart_comfyui is
|
|
10338
10461
|
// not tab-scoped — it acts on the ComfyUI this server is configured for,
|
|
10339
10462
|
// which it can identify and assess — so it remains available. A user who
|
|
10340
10463
|
// loses one entry point must be told the other one works, and why.
|
|
10341
|
-
|
|
10342
|
-
|
|
10343
|
-
|
|
10344
|
-
|
|
10464
|
+
//
|
|
10465
|
+
// #1593 — but only when it is actually the other one. This line used to
|
|
10466
|
+
// recommend restart_comfyui unconditionally, which is #851's defect
|
|
10467
|
+
// exactly: it targets COMFYUI_URL, not the ComfyUI the panel is inside,
|
|
10468
|
+
// and this branch fires precisely when those are most likely to differ.
|
|
10469
|
+
// The discriminator #851 built has been next door ever since and was
|
|
10470
|
+
// never consulted here; now it is, and both addresses are named.
|
|
10471
|
+
restartRefusalHandoffAdvice({
|
|
10472
|
+
headlessBase: getComfyUIBaseUrl(),
|
|
10473
|
+
panelBase: preflightHealthBase,
|
|
10474
|
+
observedOrigin: ctx.bridge?.tabServerOrigin?.(ctx.tabId) ?? null,
|
|
10475
|
+
}) +
|
|
10345
10476
|
// artokun/comfyui-mcp-panel#769 — a REMOTE ComfyUI reached over a
|
|
10346
10477
|
// tunnel or port-forward has a LOOPBACK host, and remoteUrlActive is
|
|
10347
10478
|
// derived from exactly that (`forceRemote || !isLoopbackHost(host)`).
|
|
@@ -10488,9 +10619,16 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
10488
10619
|
"fronts — a restart STOPS a server, so it is never sent to one I cannot " +
|
|
10489
10620
|
// Again: what I did, not what an unidentified instance is doing.
|
|
10490
10621
|
"identify. Nothing was dispatched, so nothing was stopped. Retry once the " +
|
|
10491
|
-
|
|
10492
|
-
|
|
10493
|
-
|
|
10622
|
+
// #1593 — the SAME unconditional recommendation, in the second refusal.
|
|
10623
|
+
// Fixing only the first would leave half the door open, and this branch
|
|
10624
|
+
// fires on a connection that just CHANGED, which is if anything a
|
|
10625
|
+
// stronger reason to check which server the other tool would hit.
|
|
10626
|
+
"panel has settled. " +
|
|
10627
|
+
restartRefusalHandoffAdvice({
|
|
10628
|
+
headlessBase: getComfyUIBaseUrl(),
|
|
10629
|
+
panelBase: healthBase,
|
|
10630
|
+
observedOrigin: ctx.bridge?.tabServerOrigin?.(ctx.tabId) ?? null,
|
|
10631
|
+
}),
|
|
10494
10632
|
});
|
|
10495
10633
|
}
|
|
10496
10634
|
const timing = getPanelRebootTiming();
|