comfyui-mcp 0.50.104 → 0.50.106
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.
|
@@ -1099,6 +1099,60 @@ export function restartTimeoutFallbackAdvice({ headlessBase, panelBase, observed
|
|
|
1099
1099
|
"card — check that this is the same ComfyUI you have been working on, since I " +
|
|
1100
1100
|
"could not confirm which one this panel is running inside.");
|
|
1101
1101
|
}
|
|
1102
|
+
/**
|
|
1103
|
+
* #1359 — an /object_info failure that names WHICH host it asked, and why that host.
|
|
1104
|
+
*
|
|
1105
|
+
* `panel_strip_workflow` reads the graph from the connected panel and then fetches node
|
|
1106
|
+
* definitions through the global headless client, which resolves COMFYUI_URL. For a
|
|
1107
|
+
* local session those are one machine. For a connected REMOTE panel they are two, and
|
|
1108
|
+
* the tool fails with a bare
|
|
1109
|
+
*
|
|
1110
|
+
* fetch failed: connect ECONNREFUSED 127.0.0.1:8188 — while requesting
|
|
1111
|
+
* http://127.0.0.1:8188/object_info
|
|
1112
|
+
*
|
|
1113
|
+
* which says nothing about the canvas being on a different host. The reporter of #1359
|
|
1114
|
+
* had to read the compiled orchestrator to find that out.
|
|
1115
|
+
*
|
|
1116
|
+
* This does NOT fix the split authority — that needs the panel to serve its own
|
|
1117
|
+
* /object_info, a protocol change tracked separately. It makes the existing failure
|
|
1118
|
+
* diagnosable, and names the workaround that works today.
|
|
1119
|
+
*
|
|
1120
|
+
* The panel's origin is the SERVER-OBSERVED handshake Origin where available: the
|
|
1121
|
+
* browser sets it on the WS upgrade and page JS cannot forge it. It is only being
|
|
1122
|
+
* PRINTED here, never fetched from, so an unreadable one costs a detail rather than a
|
|
1123
|
+
* wrong conclusion.
|
|
1124
|
+
*/
|
|
1125
|
+
function objectInfoHostMismatchMessage(ctx, err, liveCanvasSource) {
|
|
1126
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
1127
|
+
let panelOrigin = null;
|
|
1128
|
+
try {
|
|
1129
|
+
panelOrigin = ctx.bridge?.tabServerOrigin?.(ctx.tabId) ?? null;
|
|
1130
|
+
}
|
|
1131
|
+
catch {
|
|
1132
|
+
/* best effort — the message stands without it */
|
|
1133
|
+
}
|
|
1134
|
+
const configured = getComfyUIBaseUrl();
|
|
1135
|
+
if (!liveCanvasSource) {
|
|
1136
|
+
// pack / path / inline: COMFYUI_URL is the right authority, so the bare failure is
|
|
1137
|
+
// already about the host the caller asked for. Say only what is true.
|
|
1138
|
+
return `${raw}\n\nNode definitions are read from COMFYUI_URL (${configured}) for a pack/path/inline source. That host did not answer /object_info.`;
|
|
1139
|
+
}
|
|
1140
|
+
const differs = panelOrigin != null && configured != null && !sameHttpBase(panelOrigin, configured);
|
|
1141
|
+
return (`${raw}\n\nTHE GRAPH AND ITS NODE DEFINITIONS CAME FROM DIFFERENT PLACES. The workflow was ` +
|
|
1142
|
+
`captured from the connected panel` +
|
|
1143
|
+
(panelOrigin ? ` (ComfyUI at ${panelOrigin})` : "") +
|
|
1144
|
+
`, but node definitions are fetched over COMFYUI_URL (${configured}) — and that is the ` +
|
|
1145
|
+
`request that failed` +
|
|
1146
|
+
(differs
|
|
1147
|
+
? `. Those are two different hosts, which is why this could not work: the orchestrator ` +
|
|
1148
|
+
`has no route to the panel's ComfyUI for /object_info.`
|
|
1149
|
+
: `.`) +
|
|
1150
|
+
`\n\nWORKAROUND: point COMFYUI_URL at the same ComfyUI the panel is connected to` +
|
|
1151
|
+
(panelOrigin ? ` (${panelOrigin})` : "") +
|
|
1152
|
+
` and retry, or pass an explicit \`graph\`/\`pack\`/\`path\` source instead of the live ` +
|
|
1153
|
+
`canvas. This is a known split of authority (#1359): stripping the LIVE canvas needs ` +
|
|
1154
|
+
`the definitions to come from the panel's own ComfyUI, which needs a panel-side change.`);
|
|
1155
|
+
}
|
|
1102
1156
|
function captureRebootHealthBase(ctx) {
|
|
1103
1157
|
if (isCloudMode() || isRemoteMode())
|
|
1104
1158
|
return null;
|
|
@@ -6848,7 +6902,26 @@ export function buildPanelToolDefs() {
|
|
|
6848
6902
|
const captureNotes = [];
|
|
6849
6903
|
const raw = await resolveWorkflowInput(args, ctx, true, captureNotes);
|
|
6850
6904
|
const ui = raw;
|
|
6851
|
-
|
|
6905
|
+
// #1359 — the graph came from the PANEL; the node definitions come from
|
|
6906
|
+
// COMFYUI_URL. Those are the same machine for a local session and different
|
|
6907
|
+
// ones for a connected REMOTE panel, and when they differ this fails with a
|
|
6908
|
+
// bare `ECONNREFUSED 127.0.0.1:8188` that never mentions the canvas host. The
|
|
6909
|
+
// reporter had to read dist/ to discover that the two halves have different
|
|
6910
|
+
// authorities.
|
|
6911
|
+
//
|
|
6912
|
+
// Only the live-canvas source is affected: a pack/path/inline graph is
|
|
6913
|
+
// deliberately tied to COMFYUI_URL, so its definitions belong there.
|
|
6914
|
+
const liveCanvasSource = args.pack == null && args.path == null && args.graph == null;
|
|
6915
|
+
let bulk;
|
|
6916
|
+
try {
|
|
6917
|
+
bulk = await getObjectInfo();
|
|
6918
|
+
}
|
|
6919
|
+
catch (err) {
|
|
6920
|
+
// Returned as a tool ERROR rather than thrown: a throw here escapes the
|
|
6921
|
+
// handler and reaches the caller as a transport-shaped failure, which is how
|
|
6922
|
+
// the bare ECONNREFUSED got to the reporter in the first place.
|
|
6923
|
+
return fail(objectInfoHostMismatchMessage(ctx, err, liveCanvasSource));
|
|
6924
|
+
}
|
|
6852
6925
|
const objectInfo = await backfillObjectInfo(bulk, collectNodeTypes(ui));
|
|
6853
6926
|
const converted = convertUiToApi(ui, objectInfo);
|
|
6854
6927
|
const workflow = converted.workflow;
|
|
@@ -7763,6 +7836,34 @@ export function buildPanelToolDefs() {
|
|
|
7763
7836
|
return ok(`🔒 Token saved to MCP server "${server}" (${args.target_kind} "${args.key}"). Call panel_reload to load it.`);
|
|
7764
7837
|
}
|
|
7765
7838
|
catch (err) {
|
|
7839
|
+
// #1352 — A TIMED-OUT SECRET CARD IS NOT A FROZEN TAB.
|
|
7840
|
+
//
|
|
7841
|
+
// The bridge's generic no-reply message ("the ComfyUI tab may be backgrounded
|
|
7842
|
+
// or frozen") is right for every other command and wrong here. This card
|
|
7843
|
+
// blocks up to 300s on a MASKED INPUT, and the overwhelmingly likely reason it
|
|
7844
|
+
// went unanswered is that a human is still typing — off finding the key in a
|
|
7845
|
+
// password manager or a billing console. Nothing is wrong with the tab, and
|
|
7846
|
+
// sending someone to fix one is the #1332 defect in a new place.
|
|
7847
|
+
//
|
|
7848
|
+
// It also has to say what happens to a value entered LATE, because that is the
|
|
7849
|
+
// question the caller will actually have. MEASURED: this card is sent as a raw
|
|
7850
|
+
// `request_secret` command with NO ask_id, and the late-reply buffer
|
|
7851
|
+
// (takeLateAskReply) is keyed BY ask id — so a value typed after the timeout
|
|
7852
|
+
// has no path back to this call. It is discarded, and the tool must be called
|
|
7853
|
+
// again. "It may still arrive" would be a guess, and an expensive one: the
|
|
7854
|
+
// user would wait for a save that cannot happen.
|
|
7855
|
+
if (isReplyTimeoutError(err)) {
|
|
7856
|
+
return fail(`The secret card was not answered within 300s, so NOTHING was saved and no ` +
|
|
7857
|
+
`credential was read. That is very likely just time — the card asks for a ` +
|
|
7858
|
+
`token, and finding one in a password manager or a billing console can take ` +
|
|
7859
|
+
`longer than that. It does NOT mean the tab is frozen, and it does NOT mean ` +
|
|
7860
|
+
`the user declined.\n\n` +
|
|
7861
|
+
`A value typed into that card NOW cannot reach this call: it carries no id ` +
|
|
7862
|
+
`this reply could be matched to, so a late answer is discarded rather than ` +
|
|
7863
|
+
`saved. Ask whether they still want to set it and call panel_request_secret ` +
|
|
7864
|
+
`again when they are ready to paste — the value goes straight from the masked ` +
|
|
7865
|
+
`field into storage, and must never be typed into the conversation.`);
|
|
7866
|
+
}
|
|
7766
7867
|
return fail(err);
|
|
7767
7868
|
}
|
|
7768
7869
|
}),
|