comfyui-mcp 0.50.81 → 0.50.83

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.
@@ -227,7 +227,7 @@ export class AskAnswerJournalImpl {
227
227
  /**
228
228
  * Which browser-tab INCARNATION currently holds a panel tab (#486).
229
229
  *
230
- * A `wf:<hash>` tab id names a saved workflow, so it recurs: a second browser
230
+ * A `wf:` route tab id names a saved workflow, so it recurs: a second browser
231
231
  * tab opening that workflow takes the key over. Anything that holds or settles
232
232
  * per-tab state must therefore be scoped to (tab, incarnation) — otherwise the
233
233
  * newcomer reads, reports and ACKS the departed tab's bookkeeping, and the
@@ -2256,7 +2256,7 @@ export async function runPanelOrchestrator() {
2256
2256
  // receipt for the ordinary path and must treat every answer as possibly lost;
2257
2257
  // with it, "the model read this" is a fact and only the genuinely unconfirmed
2258
2258
  // ones are held open (#486).
2259
- // #486 — a `wf:<hash>` tab id names a WORKFLOW, so a second browser tab can
2259
+ // #486 — a `wf:` route tab id names a WORKFLOW, so a second browser tab can
2260
2260
  // take it over. The journal scopes every per-tab debt to whoever is actually
2261
2261
  // holding the key, so the newcomer can neither be told nor settle the
2262
2262
  // departed tab's owed disclosure.
@@ -2266,7 +2266,7 @@ export async function runPanelOrchestrator() {
2266
2266
  // warning is owed), so it needs a LIFECYCLE end instead: a tab leaving the
2267
2267
  // bridge's connection map surfaces whatever it is still owed and retires it.
2268
2268
  // Journal entries survive — a disconnect is usually a reload.
2269
- // #486 — a DIFFERENT browser tab taking over a recurring `wf:<hash>` key is a
2269
+ // #486 — a DIFFERENT browser tab taking over a recurring `wf:` route key is a
2270
2270
  // CONVERSATION BOUNDARY, exactly like New chat or a provider switch: the
2271
2271
  // newcomer never asked the previous occupant's questions, so its answers must
2272
2272
  // stop being recoverable and stop being pushed. closeAsks downgrades and
@@ -960,51 +960,13 @@ async function probeDeclineRecovery(base, windowMs, intervalMs, probeTimeoutMs,
960
960
  waited_ms: Date.now() - start,
961
961
  };
962
962
  }
963
- /**
964
- * The FIXED ComfyUI base URL to health-probe during a reboot readiness wait, or
965
- * null when we must fall back to the panel round-trip (as before #509). Captured by
966
- * the handler BEFORE it dispatches comfy_reboot and held for the whole wait.
967
- *
968
- * SECURITY (coordinator codex P1): the probe TARGET is the orchestrator's own
969
- * PROCESS-START local ComfyUI endpoint (getBootLocalComfyUIBaseUrl) — captured at
970
- * boot and IMMUTABLE. It is deliberately NOT getComfyUIBaseUrl(): that reflects the
971
- * mutable runtime config a panel `hello` can retarget (applyComfyuiUrl →
972
- * setComfyuiTarget), so a client could steer it. And it is NEVER the client-advertised
973
- * `hello.comfyui_url` (spoofable; comfyuiFetch would leak the configured ComfyUI auth
974
- * headers to an attacker-chosen origin). The tab origin is used ONLY as a gate, and the
975
- * gate reads the SERVER-OBSERVED handshake Origin (tabServerOrigin) — which the browser
976
- * sets and blocks page JS from forging — NOT the spoofable hello.comfyui_url: we
977
- * self-probe our OWN boot endpoint solely when the rebooted tab PROVABLY (by its
978
- * handshake) fronts THAT SAME instance, so a socket that merely CLAIMS the boot URL can't
979
- * ride an unrelated boot-instance cycle to a false certification (codex High). Null
980
- * (→ honest dispatched-unconfirmed) when:
981
- * - cloud OR remote mode; or
982
- * - the orchestrator didn't boot against a LOCAL loopback ComfyUI; or
983
- * - the tab isn't SERVER-TRUSTED-local (tabIsLocal — arrived on the token-less
984
- * loopback primary listener; relay/tunnel/LAN/pairing → false); or
985
- * - the tab's HANDSHAKE origin is absent, ambiguous (`localhost`), or does NOT match our
986
- * boot endpoint by scheme+host+port (concrete-family loopback-canonicalized) — i.e. it
987
- * drives a DIFFERENT instance / family, or one we can't verify; AND, because a handshake
988
- * Origin carries NO path, a boot target mounted under a basePath fails path-aware
989
- * identity and is (soundly) fail-closed to dispatched-unconfirmed.
990
- */
991
- /**
992
- * #851 — what to tell the caller about `restart_comfyui` when the panel's confirmation
993
- * card timed out.
994
- *
995
- * The old text recommended it unconditionally. It targets COMFYUI_URL, not the ComfyUI
996
- * the panel runs inside, so a reporter who followed that advice aimed a restart at a
997
- * different server than the one they had been working on — and got "No ComfyUI process
998
- * found on port 8188" while the panel was working fine on the live canvas.
999
- *
1000
- * `panelBase` comes from captureRebootHealthBase(), which is a PROOF rather than a
1001
- * comparison: null in remote/cloud mode, and whenever the tab's origin cannot be shown
1002
- * to front the local boot instance. "Unproven" is deliberately NOT folded into
1003
- * "different" — that would fire the warning on ordinary remote installs where the two
1004
- * ARE the same server, trading a wrong recommendation for a wrong alarm.
1005
- *
1006
- * Pure, so the three-way decision is testable without a live panel.
1007
- */
963
+ export function classifyTabReconnect({ serverReady, baselineCaptured, tabBack, }) {
964
+ if (tabBack === true)
965
+ return true; // a newer hello from the same tab was seen
966
+ if (!serverReady)
967
+ return "unknown"; // never watched — the server never came back
968
+ return baselineCaptured ? false : "unknown";
969
+ }
1008
970
  export function restartTimeoutFallbackAdvice({ headlessBase, panelBase, observedOrigin = null, }) {
1009
971
  if (panelBase != null && sameHttpBase(headlessBase, panelBase)) {
1010
972
  return "or use restart_comfyui to restart the server directly without a panel card.";
@@ -9036,12 +8998,20 @@ export function buildPanelToolDefs() {
9036
8998
  : true
9037
8999
  : false;
9038
9000
  const graphToolsReady = tabBack && (ctx.tabCanMutateGraph ? ctx.tabCanMutateGraph() : true);
9001
+ // #654 — `ready`/`graph_tools_ready` still come from the BOOLEAN, so an
9002
+ // undetermined reconnect withholds graph tools exactly as before. Only
9003
+ // the reported observation changes.
9004
+ const tabReconnect = classifyTabReconnect({
9005
+ serverReady: recovery.ready,
9006
+ baselineCaptured: preRestartPanelIdentity != null,
9007
+ tabBack,
9008
+ });
9039
9009
  return ok({
9040
9010
  rebooting: true,
9041
9011
  ready: graphToolsReady,
9042
9012
  graph_tools_ready: graphToolsReady,
9043
9013
  server_ready: recovery.ready,
9044
- panel_tab_reconnected: tabBack,
9014
+ panel_tab_reconnected: tabReconnect,
9045
9015
  confirmed_cycle: observed, // true = we directly observed the down→up cycle
9046
9016
  recovered_ms: recovery.waited_ms,
9047
9017
  probes: recovery.attempts,
@@ -9051,8 +9021,20 @@ export function buildPanelToolDefs() {
9051
9021
  ? "ComfyUI-Manager (legacy 3.x) had no reboot endpoint; the headless managed restart " +
9052
9022
  `came back healthy in ${(recovery.waited_ms / 1000).toFixed(1)}s, but ` +
9053
9023
  (!tabBack
9054
- ? "the panel tab has NOT reconnected yet (ready:false). Wait a moment then retry, or " +
9055
- 'rebind with panel_set_workflow_target({mode:"current"}) before issuing graph tools.'
9024
+ ? tabReconnect === "unknown"
9025
+ ? "whether the panel tab reconnected could NOT be determined — no pre-restart " +
9026
+ "baseline was captured for it, so nothing was watched. WHY is not established " +
9027
+ "here, and it is one of: the tab's socket was not open at the instant the " +
9028
+ "restart was dispatched; the panel advertised no tab session id (an older " +
9029
+ "build, or its browser-tab lease was refused because a duplicate tab holds " +
9030
+ "it); or the tab did not resolve at all. The tab may well be back. Graph " +
9031
+ "tools are withheld (ready:false) because that is unproven, NOT because the " +
9032
+ 'tab is known to be gone: call panel_list_workflows or panel_set_workflow_target({mode:"current"}) ' +
9033
+ "to find out, and only refresh the browser if those also fail. If this " +
9034
+ "repeats on every restart, the panel is probably too old to advertise a tab " +
9035
+ "session id — update it."
9036
+ : "the panel tab has NOT reconnected yet (ready:false). Wait a moment then retry, or " +
9037
+ 'rebind with panel_set_workflow_target({mode:"current"}) before issuing graph tools.'
9056
9038
  : "the panel tab reconnected but cannot safely run graph mutations (ready:false), usually " +
9057
9039
  "because it is still running a stale panel bundle. Hard-refresh the ComfyUI browser tab " +
9058
9040
  "(Ctrl+Shift+R) before issuing graph tools; if that does not restore it, update the panel " +
@@ -9171,6 +9153,14 @@ export function buildPanelToolDefs() {
9171
9153
  // Old/lightweight contexts have no capability accessor, so preserve their historical
9172
9154
  // contract rather than claiming a production tab passed a check it never ran.
9173
9155
  const graphToolsReady = tabBack && (ctx.tabCanMutateGraph ? ctx.tabCanMutateGraph() : true);
9156
+ // #654 — same split as the legacy path above. The gate is unchanged:
9157
+ // `ready`/`graph_tools_ready` still key off the boolean, so an undetermined
9158
+ // reconnect still withholds graph tools. Only the reported observation changes.
9159
+ const tabReconnect = classifyTabReconnect({
9160
+ serverReady: true, // this branch only runs on a confirmed healthy cycle
9161
+ baselineCaptured: preRestartPanelIdentity != null,
9162
+ tabBack,
9163
+ });
9174
9164
  // #848: WHAT THIS RESTART DID NOT DO. "It came back healthy" answers a
9175
9165
  // different question from "did it come back with the launch arguments I just
9176
9166
  // configured?", and a user who had edited ComfyUI Desktop's saved launch args
@@ -9207,7 +9197,7 @@ export function buildPanelToolDefs() {
9207
9197
  probes: recovery.attempts,
9208
9198
  saw_down: recovery.sawDown,
9209
9199
  via: recovery.via,
9210
- panel_tab_reconnected: tabBack,
9200
+ panel_tab_reconnected: tabReconnect,
9211
9201
  note: (tabBack && !graphToolsReady
9212
9202
  ? `ComfyUI restart accepted and it is healthy again in ${(recovery.waited_ms / 1000).toFixed(1)}s` +
9213
9203
  " (observed it go down then come back); the panel tab reconnected but cannot safely run " +
@@ -9219,9 +9209,20 @@ export function buildPanelToolDefs() {
9219
9209
  (dropped ? "; connection dropped as expected while it went down" : "") +
9220
9210
  (tabBack
9221
9211
  ? "; the panel tab reconnected — graph tools are ready."
9222
- : "; ComfyUI is back but the panel tab has NOT reconnected yet (ready:false) — " +
9223
- 'wait a moment then retry, or rebind with panel_set_workflow_target({mode:"current"}) ' +
9224
- "before issuing graph tools.") +
9212
+ : tabReconnect === "unknown"
9213
+ ? "; ComfyUI is back, but whether the panel tab reconnected could NOT be determined — no " +
9214
+ "pre-restart baseline was captured for it, so nothing was watched. WHY is not " +
9215
+ "established here, and it is one of: its socket was not open at the instant the " +
9216
+ "restart was dispatched; the panel advertised no tab session id (an older build, or " +
9217
+ "a refused browser-tab lease); or the tab did not resolve at all. The tab may well " +
9218
+ "be back. Graph tools are withheld (ready:false) because that is UNPROVEN, not " +
9219
+ "because the tab is known to be gone: call panel_list_workflows or " +
9220
+ 'panel_set_workflow_target({mode:"current"}) to find out, and refresh the browser only ' +
9221
+ "if those also fail. If this repeats on every restart, the panel is probably too old " +
9222
+ "to advertise a tab session id — update it."
9223
+ : "; ComfyUI is back but the panel tab has NOT reconnected yet (ready:false) — " +
9224
+ 'wait a moment then retry, or rebind with panel_set_workflow_target({mode:"current"}) ' +
9225
+ "before issuing graph tools.") +
9225
9226
  ".") + argvNote,
9226
9227
  });
9227
9228
  }),