comfyui-mcp 0.50.91 → 0.50.92

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.
@@ -3436,7 +3436,57 @@ async function waitForOpenReceipt(ctx, path, rid, timing) {
3436
3436
  * gave up (no tab reconnected within budget / an ambiguous multi-tab session). We
3437
3437
  * must NOT dispatch — firing into a dead binding is exactly the OUTCOME-UNKNOWN /
3438
3438
  * double-apply risk the pre-send wait exists to prevent (codex). */
3439
- function noReachableTabFail(cmd) {
3439
+ function noReachableTabFail(cmd, ctx) {
3440
+ // #971 — TWO CAUSES, OPPOSITE REMEDIES, and they were folded into one sentence
3441
+ // that sent the reporter in a circle:
3442
+ //
3443
+ // panel_open_workflow -> "no reachable tab … or rebind with
3444
+ // panel_set_workflow_target({mode:'current'})"
3445
+ // mode:"current" -> its only probe is a workflow_list call TO A TAB
3446
+ //
3447
+ // So the advice needed exactly the thing whose absence caused the failure. The
3448
+ // reporter had already run the rebind — it reported `bound` — and was sent back
3449
+ // to it.
3450
+ //
3451
+ // The two causes want different answers, and the bridge can tell them apart:
3452
+ // • nothing connected → there is nothing to rebind ONTO. Say so, and name the
3453
+ // thing that does help (the tab reconnecting, or the user opening/refreshing
3454
+ // one).
3455
+ // • tabs connected, none is ours → `mode:"current"` is exactly right: it
3456
+ // re-points the session at the active tab.
3457
+ let connected = null;
3458
+ try {
3459
+ const tabs = ctx?.bridge?.tabs?.();
3460
+ if (Array.isArray(tabs)) {
3461
+ connected = tabs.filter((t) => !(typeof ctx?.bridge?.isHeadless === "function" && ctx.bridge.isHeadless(t.tab_id))).length;
3462
+ }
3463
+ }
3464
+ catch {
3465
+ connected = null; // an unreadable bridge earns the neutral wording below
3466
+ }
3467
+ if (connected === 0) {
3468
+ // MEASURED, not assumed. An earlier draft of this said "rebinding CANNOT
3469
+ // help while nothing is connected". That is false: with zero tabs
3470
+ // `mode:"current"` returns `deferred: true`, CLEARS the stale binding, and
3471
+ // arms a bind onto the first tab that reconnects. It is worth doing — it
3472
+ // just does not make the command retryable NOW, which is what the caller is
3473
+ // actually asking. Saying which of those it does is the difference between
3474
+ // a useful instruction and the loop the reporter hit.
3475
+ return fail(`${cmd} — this session has no reachable panel tab, and NO panel tab is connected at all ` +
3476
+ `(still reconnecting after a restart/reload, or the ComfyUI browser tab is closed). ` +
3477
+ `Nothing was sent. A rebind will NOT make this retryable yet: with nothing connected, ` +
3478
+ `panel_set_workflow_target({mode:"current"}) clears the stale binding and DEFERS, taking ` +
3479
+ `effect on the first tab that reconnects — useful, but it does not bring a tab back. ` +
3480
+ `Wait for the reconnect and retry, or ask the user to open/refresh the ComfyUI browser tab.`);
3481
+ }
3482
+ if (connected !== null && connected > 0) {
3483
+ return fail(`${cmd} — this session has no reachable panel tab, though ${connected} panel tab(s) are ` +
3484
+ `connected — none of them is bound to this session (its tab was replaced, or several are ` +
3485
+ `open and the session's is gone). Nothing was sent. Rebind onto the live one with ` +
3486
+ `panel_set_workflow_target({mode:"current"}), then retry.`);
3487
+ }
3488
+ // Bridge could not enumerate tabs: keep the old, cause-neutral wording rather
3489
+ // than guessing which of the two it is.
3440
3490
  return fail(`${cmd} — this session has no reachable panel tab yet (still reconnecting after a ` +
3441
3491
  `restart/reload, or multiple tabs are open and none is this session's). Nothing was ` +
3442
3492
  `sent. Retry in a moment, or rebind with panel_set_workflow_target({mode:"current"}).`);
@@ -3449,7 +3499,7 @@ async function openWorkflowWithVerify(path, ctx) {
3449
3499
  // OUTCOME UNKNOWN. A healthy session returns from this instantly; if no tab
3450
3500
  // reconnects within budget we REFUSE rather than dispatch into a dead binding.
3451
3501
  if (ctx.awaitReachable && !(await ctx.awaitReachable())) {
3452
- return noReachableTabFail("workflow_open");
3502
+ return noReachableTabFail("workflow_open", ctx);
3453
3503
  }
3454
3504
  let dispatchedRid;
3455
3505
  const res = await ctx.call({ cmd: "workflow_open", path }, 15000, (rid) => {
@@ -7802,7 +7852,7 @@ export function buildPanelToolDefs() {
7802
7852
  // if no tab reconnects within budget we REFUSE rather than fire into a dead
7803
7853
  // binding.
7804
7854
  if (ctx.awaitReachable && !(await ctx.awaitReachable())) {
7805
- return noReachableTabFail(args.name ? "workflow_save_as" : "workflow_save");
7855
+ return noReachableTabFail(args.name ? "workflow_save_as" : "workflow_save", ctx);
7806
7856
  }
7807
7857
  const res = args.name
7808
7858
  ? await ctx.call({ cmd: "workflow_save_as", name: args.name }, 15000)