comfyui-mcp 0.52.82 → 0.52.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.
@@ -190,7 +190,7 @@ import { RunCompletions } from "./run-completion-journal.js";
190
190
  import { AskAnswers, askFingerprint, PANEL_ASK_ID_PREFIX, } from "./ask-answer-journal.js";
191
191
  import { getQueueVerified, resetClient, resetObjectInfoCache, } from "../comfyui/client.js";
192
192
  import { convertUiToApi, collectNodeTypes } from "../services/workflow-converter.js";
193
- import { restartComfyUI, preflightLocalRestart, readServingArgv, describeArgvDrift, recordRestartDispatch, clearRestartDispatch, getRestartDispatchRecord, RESTART_DISPATCH_CAUSATION_WINDOW_MS, PROCESS_WIDE_RESTART_DISPATCH_TOKEN, __processControlTestHooks, } from "../services/process-control.js";
193
+ import { restartComfyUI, preflightLocalRestart, readServingArgv, resolveVerifiedProxyRestartTarget, describeArgvDrift, recordRestartDispatch, clearRestartDispatch, getRestartDispatchRecord, RESTART_DISPATCH_CAUSATION_WINDOW_MS, PROCESS_WIDE_RESTART_DISPATCH_TOKEN, __processControlTestHooks, } from "../services/process-control.js";
194
194
  import { resetManagerApiCache } from "../services/manager-api-cache.js";
195
195
  import { desktopSavedLaunchArgs, describeSavedLaunchArgDrift, } from "../services/desktop-launch-args.js";
196
196
  import { config, isRemoteMode, isCloudMode, getBootLocalComfyUIBaseUrl, getComfyUIBaseUrl, getComfyuiTargetGeneration, } from "../config.js";
@@ -735,6 +735,10 @@ export const __panelToolsTestHooks = {
735
735
  setLocalRestartPreflight(fn) {
736
736
  localRestartPreflightOverride = fn;
737
737
  },
738
+ /** Inject the narrow EZi/CEI proxy proof; null restores the live resolver. */
739
+ setVerifiedProxyRestartTarget(fn) {
740
+ verifiedProxyRestartTargetOverride = fn;
741
+ },
738
742
  /** Inject a fast #742 decline-probe recheck window so decline-path tests
739
743
  * don't wait the real ~6s. null restores the DECLINE_PROBE_* constants. */
740
744
  setDeclineProbeTiming(timing) {
@@ -2221,6 +2225,16 @@ let healthProbeOverride = null;
2221
2225
  /** Test injection for the #742 refuse-safe restart preflight (the real one is
2222
2226
  * preflightLocalRestart in process-control). null → the live preflight. */
2223
2227
  let localRestartPreflightOverride = null;
2228
+ let verifiedProxyRestartTargetOverride = null;
2229
+ function panelVerifiedProxyRestartTarget() {
2230
+ return (verifiedProxyRestartTargetOverride ?? resolveVerifiedProxyRestartTarget)();
2231
+ }
2232
+ function proxyTargetBindsPanel(ctx, target) {
2233
+ return (target != null &&
2234
+ sameHttpBase(getComfyUIBaseUrl(), target.proxyBase) &&
2235
+ ctx.bridge?.tabIsLocal?.(ctx.tabId) === true &&
2236
+ sameHttpBase(ctx.bridge?.tabServerOrigin?.(ctx.tabId), target.proxyBase));
2237
+ }
2224
2238
  /** Test injection for the #742 decline-probe recheck window, so tests don't
2225
2239
  * wait the real ~6s. null → the DECLINE_PROBE_* constants. */
2226
2240
  let declineProbeTimingOverride = null;
@@ -15561,6 +15575,10 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
15561
15575
  return fail(surfaceErr +
15562
15576
  " To restart the server without a panel confirmation card, use restart_comfyui.");
15563
15577
  }
15578
+ // #2118: keep the proxy proof alive across the confirmation/preflight
15579
+ // awaits. The proxy is never treated as a ComfyUI process; it only lets
15580
+ // the tab-scoped Manager request be observed against the immutable backend.
15581
+ let proxyRestartTarget;
15564
15582
  // #1819: resolve instance identity BEFORE the confirmation card. Asking the
15565
15583
  // user to confirm a restart, then refusing because we cannot tell which
15566
15584
  // ComfyUI this tab fronts, is two contradictory outcomes (timeout vs refuse)
@@ -15575,10 +15593,14 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
15575
15593
  const identityBound = identityHealthBase != null &&
15576
15594
  sameHttpBase(getComfyUIBaseUrl(), identityHealthBase);
15577
15595
  if (!identityBound) {
15596
+ const candidate = await panelVerifiedProxyRestartTarget();
15597
+ if (proxyTargetBindsPanel(ctx, candidate)) {
15598
+ proxyRestartTarget = candidate;
15599
+ }
15578
15600
  const tabStillHere = typeof ctx.bridge?.canReach === "function"
15579
15601
  ? ctx.bridge.canReach(ctx.tabId) === true
15580
15602
  : true;
15581
- if (tabStillHere) {
15603
+ if (tabStillHere && proxyRestartTarget == null) {
15582
15604
  return restartRefusedPreservingBinding(ctx, unboundLocalRestartRefusalNote(ctx, identityHealthBase, identityBinding.blocker));
15583
15605
  }
15584
15606
  // Tab is gone: confirm will be unreachable and #1671 crash-recovery
@@ -16151,8 +16173,16 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
16151
16173
  // "idle" and a restart aborts whatever is running.
16152
16174
  const configuredRestartCommand = config.comfyuiRestartCommand;
16153
16175
  if (configuredRestartCommand && !isRemoteMode() && !isCloudMode()) {
16154
- const commandHealthBase = captureRebootHealthBase(ctx);
16155
- if (commandHealthBase != null && sameHttpBase(getComfyUIBaseUrl(), commandHealthBase)) {
16176
+ if (proxyRestartTarget != null) {
16177
+ const refreshedProxy = await panelVerifiedProxyRestartTarget();
16178
+ proxyRestartTarget = proxyTargetBindsPanel(ctx, refreshedProxy)
16179
+ ? refreshedProxy
16180
+ : undefined;
16181
+ }
16182
+ const commandHealthBase = proxyRestartTarget?.backendBase ?? captureRebootHealthBase(ctx);
16183
+ const commandBound = proxyRestartTarget != null ||
16184
+ (commandHealthBase != null && sameHttpBase(getComfyUIBaseUrl(), commandHealthBase));
16185
+ if (commandHealthBase != null && commandBound) {
16156
16186
  if (force !== true) {
16157
16187
  let busyCount = null;
16158
16188
  try {
@@ -16191,7 +16221,13 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
16191
16221
  // Re-heal and re-verify at the point of action, exactly as the
16192
16222
  // dispatch path below does.
16193
16223
  ctx.ensureReachable?.();
16194
- const postCheckHealthBase = captureRebootHealthBase(ctx);
16224
+ if (proxyRestartTarget != null) {
16225
+ const postProxy = await panelVerifiedProxyRestartTarget();
16226
+ proxyRestartTarget = proxyTargetBindsPanel(ctx, postProxy)
16227
+ ? postProxy
16228
+ : undefined;
16229
+ }
16230
+ const postCheckHealthBase = proxyRestartTarget?.backendBase ?? captureRebootHealthBase(ctx);
16195
16231
  if (postCheckHealthBase == null ||
16196
16232
  !sameHttpBase(commandHealthBase, postCheckHealthBase)) {
16197
16233
  return ok({
@@ -16271,10 +16307,20 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
16271
16307
  // can be proven. They keep restart_comfyui, and the note says so. Weighed
16272
16308
  // against #814 — where exactly such a user's server was stopped and never came
16273
16309
  // back — declining is the recoverable side.
16310
+ // Re-resolve after the confirmation await. A proxy proof is an endpoint
16311
+ // identity claim, not a durable permission; a retarget or tab rebind makes
16312
+ // it unusable and returns to the existing refusal path.
16313
+ if (proxyRestartTarget != null) {
16314
+ const refreshedProxy = await panelVerifiedProxyRestartTarget();
16315
+ proxyRestartTarget = proxyTargetBindsPanel(ctx, refreshedProxy)
16316
+ ? refreshedProxy
16317
+ : undefined;
16318
+ }
16274
16319
  const preflightBinding = resolveRebootHealthBinding(ctx);
16275
- const preflightHealthBase = preflightBinding.base;
16276
- const preflightBound = preflightHealthBase != null &&
16277
- sameHttpBase(getComfyUIBaseUrl(), preflightHealthBase);
16320
+ const preflightHealthBase = proxyRestartTarget?.backendBase ?? preflightBinding.base;
16321
+ const preflightBound = proxyRestartTarget != null ||
16322
+ (preflightHealthBase != null &&
16323
+ sameHttpBase(getComfyUIBaseUrl(), preflightHealthBase));
16278
16324
  // #848: what the instance was OBSERVED running with, taken from the preflight
16279
16325
  // that already had to resolve it. Nothing new is probed before the dispatch —
16280
16326
  // the no-await invariant between the binding capture and the reboot stands.
@@ -16308,7 +16354,9 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
16308
16354
  // EVERY retarget — any mutation, including a round trip back to the
16309
16355
  // same base, is caught.
16310
16356
  const preflightTargetGeneration = getComfyuiTargetGeneration();
16311
- const preflight = await (localRestartPreflightOverride ?? preflightLocalRestart)();
16357
+ const preflight = proxyRestartTarget
16358
+ ? { ok: true, observedArgv: proxyRestartTarget.argv }
16359
+ : await (localRestartPreflightOverride ?? preflightLocalRestart)();
16312
16360
  // #848: keep the observed launch arguments. Recorded here and spent ONLY on
16313
16361
  // the success path far below, where the reboot has been proven to have
16314
16362
  // cycled THIS instance — it never influences any decision above.
@@ -16327,11 +16375,19 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
16327
16375
  // re-capture BEFORE trusting the result either way. The guarantee
16328
16376
  // that must hold: a stop/reboot is only ever sent when the preflight
16329
16377
  // validated THE instance the dispatch will cycle.
16378
+ if (proxyRestartTarget) {
16379
+ // The proxy branch performs no local stop/preflight. Its direct
16380
+ // backend proof is rechecked immediately before dispatch below.
16381
+ preflightArgvGeneration = proxyRestartTarget.generation;
16382
+ }
16330
16383
  ctx.ensureReachable?.();
16331
16384
  const postPreflightHealthBase = captureRebootHealthBase(ctx);
16332
- const tabFrontsSameInstance = postPreflightHealthBase != null &&
16333
- sameHttpBase(preflightHealthBase, postPreflightHealthBase);
16334
- const configStable = getComfyuiTargetGeneration() === preflightTargetGeneration;
16385
+ const tabFrontsSameInstance = proxyRestartTarget != null ||
16386
+ (postPreflightHealthBase != null &&
16387
+ sameHttpBase(preflightHealthBase, postPreflightHealthBase));
16388
+ const configStable = proxyRestartTarget != null
16389
+ ? getComfyuiTargetGeneration() === proxyRestartTarget.generation
16390
+ : getComfyuiTargetGeneration() === preflightTargetGeneration;
16335
16391
  if (!configStable && tabFrontsSameInstance) {
16336
16392
  // r10: the target config moved MID-CHECK, so the preflight result
16337
16393
  // — pass OR fail — cannot vouch for the tab-fronted instance (a
@@ -16409,7 +16465,17 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
16409
16465
  // this SAME browser tab; a different tab can reuse the same saved-workflow
16410
16466
  // routing id while the original is still reconnecting.
16411
16467
  const preRestartPanelIdentity = ctx.panelConnectionIdentity?.();
16412
- const healthBase = captureRebootHealthBase(ctx);
16468
+ if (proxyRestartTarget != null) {
16469
+ const dispatchProxy = await panelVerifiedProxyRestartTarget();
16470
+ proxyRestartTarget = proxyTargetBindsPanel(ctx, dispatchProxy)
16471
+ ? dispatchProxy
16472
+ : undefined;
16473
+ if (proxyRestartTarget) {
16474
+ preflightArgv = [...proxyRestartTarget.argv];
16475
+ preflightArgvGeneration = proxyRestartTarget.generation;
16476
+ }
16477
+ }
16478
+ const healthBase = proxyRestartTarget?.backendBase ?? captureRebootHealthBase(ctx);
16413
16479
  // THE BINDING RULE APPLIES AT THE DISPATCH POINT, NOT ONLY BEFORE THE AWAIT.
16414
16480
  //
16415
16481
  // The check above happens before the preflight; a tab or connection rebind
@@ -16422,7 +16488,8 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
16422
16488
  //
16423
16489
  // Same rule, same exclusions: only a LOCAL target we cannot tie to the
16424
16490
  // instance this server accounts for is refused.
16425
- const dispatchBound = healthBase != null && sameHttpBase(getComfyUIBaseUrl(), healthBase);
16491
+ const dispatchBound = proxyRestartTarget != null ||
16492
+ (healthBase != null && sameHttpBase(getComfyUIBaseUrl(), healthBase));
16426
16493
  if (!dispatchBound && !isRemoteMode() && !isCloudMode()) {
16427
16494
  return restartRefusedPreservingBinding(ctx, "Refusing to restart ComfyUI: the panel connection changed while the restart " +
16428
16495
  "was being prepared, and I can no longer confirm which ComfyUI this tab " +
@@ -16614,6 +16681,7 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
16614
16681
  // server replaced at the same URL between the reboot and here. That gap is real
16615
16682
  // and tracked in #871; this gate narrows the window, it does not close it.
16616
16683
  healthBase != null &&
16684
+ proxyRestartTarget == null &&
16617
16685
  sameHttpBase(getComfyUIBaseUrl(), healthBase)) {
16618
16686
  return runHeadlessManagedRestart({
16619
16687
  healthBase,