comfyui-mcp 0.51.46 → 0.51.48

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.
@@ -34,6 +34,7 @@ import { fileURLToPath } from "node:url";
34
34
  import { comfyuiFetch } from "../comfyui/fetch.js";
35
35
  import { assertPanelNotTargetedUnverifiable } from "../services/panel-pin-guard.js";
36
36
  import { nodesInstallCommandArgs } from "../services/node-management.js";
37
+ import { isPreExecutorRefusal } from "../services/panel-refusal.js";
37
38
  import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
38
39
  import { parse as parseYaml } from "yaml";
39
40
  import { conversationOfScopeAddress, isScopeAddress, shortTabId } from "../services/session-scope.js";
@@ -3494,6 +3495,37 @@ async function unreadableOrHealed(ctx, before, detail) {
3494
3495
  function panelTooOldNote(ctx) {
3495
3496
  try {
3496
3497
  const v = ctx.bridge?.panelTooOldForReplyUuid?.(ctx.tabId);
3498
+ // #1560 — A PANEL TOO OLD TO HELP IS ALSO TOO OLD TO SAY SO.
3499
+ //
3500
+ // The note below needs an advertised version, and `panel_version` has only
3501
+ // ridden the hello since panel v0.11.83. So the panels most likely to be
3502
+ // causing this deadlock — anything below 0.11.45 — cannot report it, and the
3503
+ // reporter of #1560 (on 0.11.37, after two Manager self-updates of the pack
3504
+ // crashed) got a bare "the panel did not answer" with nothing to act on.
3505
+ //
3506
+ // Deliberately WEAKER than the version case, and weaker still after review: an
3507
+ // absent version proves only "below 0.11.83", NOT "below the minimum". Panels
3508
+ // in 0.11.45–0.11.82 publish the reply uuid and simply predate version
3509
+ // advertisement, so this must read as SOMETHING TO CHECK and never as a finding
3510
+ // — naming a cause that is not theirs is the failure this whole cluster exists
3511
+ // to avoid.
3512
+ if (v?.neverAdvertised) {
3513
+ return (`
3514
+
3515
+ WORTH CHECKING — THE PANEL'S VERSION IS UNKNOWN HERE: this session's panel has never ` +
3516
+ `reported its version, and panels have advertised one on connect since 0.11.83, so ` +
3517
+ `this one is older than that. That does NOT by itself mean it is too old: a panel ` +
3518
+ `reports the new workflow's identity ON THE REPLY from ${v.needed} onwards, and ` +
3519
+ `0.11.45–0.11.82 do that while still not advertising a version. But if it IS below ` +
3520
+ `${v.needed}, that is the whole cause of this failure rather than anything about this ` +
3521
+ `workflow — on ${v.needed}+ the command that re-pointed the canvas repairs the fence ` +
3522
+ `from its own reply and never makes the read that just failed. ` +
3523
+ `Find out with install_comfyui (action:"panel", panel_action:"status"). If it is ` +
3524
+ `older, update with install_comfyui (action:"panel", panel_action:"sync"), restart ` +
3525
+ `ComfyUI, and HARD-REFRESH the browser tab (Ctrl+Shift+R) — a pack update that ` +
3526
+ `ComfyUI-Manager reported as FAILED leaves the old panel JS running in the open tab, ` +
3527
+ `so a restart alone does not pick it up.`);
3528
+ }
3497
3529
  if (!v?.tooOld)
3498
3530
  return "";
3499
3531
  return (`
@@ -5694,7 +5726,22 @@ export function makePanelToolCtx(bridge, tabId, workflowTargets) {
5694
5726
  // for a retry in a moment; the section lasts a fraction of a second, which
5695
5727
  // is what retrySettleMs already waits. Still gated on RETRY-SAFE commands,
5696
5728
  // so a mutation is never re-issued on our own initiative.
5697
- if (isRetrySafeCmd(cmd) && (isTransientReconnectError(err) || isWorkflowSwitchGuardRefusal(err))) {
5729
+ // #1529 a PRE-EXECUTOR refusal is retryable even for a MUTATION.
5730
+ //
5731
+ // Every other branch here is gated on RETRY_SAFE_CMDS precisely because a
5732
+ // mutation might have landed before the failure, and re-issuing it would
5733
+ // double-apply. That reasoning does not hold for this one: the panel's
5734
+ // reconnect gate runs BEFORE its executor, and says so in a structured field
5735
+ // (`applied:false, stage:"pre-executor"`) rather than in prose. Nothing ran,
5736
+ // so there is nothing to double-apply — which is the entire point of the
5737
+ // channel, and why it is keyed on the FIELD and never on the message text.
5738
+ //
5739
+ // The refusal is the panel's own claim about its own execution, validated on
5740
+ // arrival; an older panel sends no field, `preExecutorRefusal` is null, and
5741
+ // this branch simply never fires.
5742
+ const preExecutorRefusal = isPreExecutorRefusal(err);
5743
+ if (preExecutorRefusal ||
5744
+ (isRetrySafeCmd(cmd) && (isTransientReconnectError(err) || isWorkflowSwitchGuardRefusal(err)))) {
5698
5745
  // panel#1097 — declared out here so the refusal branch below can see it,
5699
5746
  // and REASSIGNED after ensureReachable so it names the tab the command is
5700
5747
  // actually dispatched on. Reading it before the rebind attributed a refusal