comfyui-mcp 0.52.52 → 0.52.53
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.
|
@@ -2250,16 +2250,17 @@ function clearSessionRestartDispatchIfSame(ctx, token) {
|
|
|
2250
2250
|
* against the fixed `deadline`.
|
|
2251
2251
|
*/
|
|
2252
2252
|
async function observeRecovery(timing, deadline, opts) {
|
|
2253
|
-
const
|
|
2253
|
+
const prior = opts.continueFrom;
|
|
2254
|
+
const start = prior ? Date.now() - prior.waited_ms : Date.now();
|
|
2254
2255
|
const gate = opts.gate;
|
|
2255
2256
|
const intervalMs = panelRebootTimingOverride
|
|
2256
2257
|
? Math.max(1, timing.intervalMs)
|
|
2257
2258
|
: Math.max(50, timing.intervalMs);
|
|
2258
2259
|
const probe = healthProbeOverride ?? probeComfyEndpoint;
|
|
2259
2260
|
const currentDeadline = () => gate?.deadline ?? deadline;
|
|
2260
|
-
let sawDown = false;
|
|
2261
|
-
let lastStatus;
|
|
2262
|
-
let attempts = 0;
|
|
2261
|
+
let sawDown = prior?.sawDown ?? false;
|
|
2262
|
+
let lastStatus = prior?.lastStatus;
|
|
2263
|
+
let attempts = prior?.attempts ?? 0;
|
|
2263
2264
|
for (;;) {
|
|
2264
2265
|
if (gate?.cancelled)
|
|
2265
2266
|
break;
|
|
@@ -2319,6 +2320,63 @@ async function observeRecovery(timing, deadline, opts) {
|
|
|
2319
2320
|
}
|
|
2320
2321
|
return { ready: false, waited_ms: Date.now() - start, attempts, sawDown, lastStatus };
|
|
2321
2322
|
}
|
|
2323
|
+
function startPostRestartTabWait(ctx, preRestartPanelIdentity, overallDeadline) {
|
|
2324
|
+
const budgetMs = Math.max(0, overallDeadline - Date.now());
|
|
2325
|
+
if (ctx.awaitPostRestartReachable) {
|
|
2326
|
+
return ctx.awaitPostRestartReachable(preRestartPanelIdentity, budgetMs);
|
|
2327
|
+
}
|
|
2328
|
+
if (ctx.awaitReachable)
|
|
2329
|
+
return ctx.awaitReachable(budgetMs);
|
|
2330
|
+
return Promise.resolve(true);
|
|
2331
|
+
}
|
|
2332
|
+
/**
|
|
2333
|
+
* #1996 r2 — keep watching /system_stats during the post-restart tab wait.
|
|
2334
|
+
*
|
|
2335
|
+
* The dedicated readiness budget still expires first (so a dead server is not
|
|
2336
|
+
* held until the whole-handler cap). The reconnect wait after it used to look
|
|
2337
|
+
* ONLY at the tab, so a server that started listening in that reserved window
|
|
2338
|
+
* was reported `server_ready:false` while the handler was still running — the
|
|
2339
|
+
* 0.52.51 recurrence (`recovered_ms:184461`, ComfyUI already listening, then
|
|
2340
|
+
* `panel_graph_outline` succeeded). Continue the SAME down→up observation in
|
|
2341
|
+
* parallel; abort it when the tab wait finishes so an instant wait cannot
|
|
2342
|
+
* stretch to `overallDeadline`.
|
|
2343
|
+
*
|
|
2344
|
+
* A later healthy sample still requires the earlier down (carried via
|
|
2345
|
+
* `continueFrom`). A tab coming back still does not certify the boot.
|
|
2346
|
+
*/
|
|
2347
|
+
async function awaitTabWhileContinuingRecovery(args) {
|
|
2348
|
+
const tabWait = startPostRestartTabWait(args.ctx, args.preRestartPanelIdentity, args.overallDeadline);
|
|
2349
|
+
if (args.recovery.ready) {
|
|
2350
|
+
return { recovery: args.recovery, tabBack: await tabWait };
|
|
2351
|
+
}
|
|
2352
|
+
const gate = {
|
|
2353
|
+
dispatched: true,
|
|
2354
|
+
dispatchedAt: 0,
|
|
2355
|
+
cancelled: false,
|
|
2356
|
+
deadline: args.overallDeadline,
|
|
2357
|
+
waitDispatched: Promise.resolve(),
|
|
2358
|
+
};
|
|
2359
|
+
const extraPromise = observeRecovery(args.timing, args.overallDeadline, {
|
|
2360
|
+
healthBase: args.healthBase,
|
|
2361
|
+
gate,
|
|
2362
|
+
continueFrom: args.recovery,
|
|
2363
|
+
});
|
|
2364
|
+
const tabBack = await tabWait;
|
|
2365
|
+
gate.cancelled = true;
|
|
2366
|
+
const extra = await extraPromise;
|
|
2367
|
+
if (extra.ready)
|
|
2368
|
+
return { recovery: extra, tabBack };
|
|
2369
|
+
return {
|
|
2370
|
+
recovery: {
|
|
2371
|
+
ready: false,
|
|
2372
|
+
waited_ms: extra.waited_ms,
|
|
2373
|
+
attempts: extra.attempts,
|
|
2374
|
+
sawDown: args.recovery.sawDown || extra.sawDown,
|
|
2375
|
+
lastStatus: extra.lastStatus ?? args.recovery.lastStatus,
|
|
2376
|
+
},
|
|
2377
|
+
tabBack,
|
|
2378
|
+
};
|
|
2379
|
+
}
|
|
2322
2380
|
// ---- workflow_open verify-after-timeout (#215/#319/#496/#661) --------------
|
|
2323
2381
|
// `panel_open_workflow` forwards `workflow_open` over the UI bridge and waits for
|
|
2324
2382
|
// the tab to ACK. When the target tab is BACKGROUNDED/FROZEN, or the workflow is
|
|
@@ -15046,16 +15104,7 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
15046
15104
|
}
|
|
15047
15105
|
// Otherwise (the process WAS stopped/started, or restartComfyUI's own readiness
|
|
15048
15106
|
// poll merely expired — neither terminal) DEFER to OUR OWN observed DOWN→UP.
|
|
15049
|
-
|
|
15050
|
-
// #742 r4/r5/r15: the managed restart was observed back — clear THIS
|
|
15051
|
-
// session's record, CLEAR-IF-SAME: only when the session still holds
|
|
15052
|
-
// the token THIS restart stamped (a concurrent dispatch's newer
|
|
15053
|
-
// record survives). restartComfyUI also clears its own process-wide
|
|
15054
|
-
// record on success; this covers only-observer-saw-it recoveries.
|
|
15055
|
-
if (recovery.ready && headlessDispatchToken != null) {
|
|
15056
|
-
clearSessionRestartDispatchIfSame(ctx, headlessDispatchToken);
|
|
15057
|
-
}
|
|
15058
|
-
const observed = recovery.via === "observed-cycle";
|
|
15107
|
+
let recovery = await proofPromise;
|
|
15059
15108
|
// The headless path restarts ComfyUI out-of-band too. Server recovery alone
|
|
15060
15109
|
// is not graph-tool readiness: wait for the browser tab to reconnect, then verify
|
|
15061
15110
|
// the same workflow-stamp capability the bridge requires before it dispatches a
|
|
@@ -15066,11 +15115,27 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
15066
15115
|
// bound one — `recovery.ready ? … : false` — so a managed kill+relaunch whose
|
|
15067
15116
|
// cold start outran the observation window forfeited the reconnect wait too,
|
|
15068
15117
|
// and reported a bare `false` for a tab nobody had looked at.
|
|
15069
|
-
|
|
15070
|
-
|
|
15071
|
-
|
|
15072
|
-
|
|
15073
|
-
|
|
15118
|
+
// #1996 r2: the tab wait also continues the health observation, so a boot
|
|
15119
|
+
// that starts listening in this reserved window is not reported unready
|
|
15120
|
+
// while the handler is still running.
|
|
15121
|
+
let tabBack;
|
|
15122
|
+
({ recovery, tabBack } = await awaitTabWhileContinuingRecovery({
|
|
15123
|
+
recovery,
|
|
15124
|
+
timing: headlessTiming,
|
|
15125
|
+
healthBase,
|
|
15126
|
+
overallDeadline,
|
|
15127
|
+
ctx,
|
|
15128
|
+
preRestartPanelIdentity,
|
|
15129
|
+
}));
|
|
15130
|
+
// #742 r4/r5/r15: the managed restart was observed back — clear THIS
|
|
15131
|
+
// session's record, CLEAR-IF-SAME: only when the session still holds
|
|
15132
|
+
// the token THIS restart stamped (a concurrent dispatch's newer
|
|
15133
|
+
// record survives). restartComfyUI also clears its own process-wide
|
|
15134
|
+
// record on success; this covers only-observer-saw-it recoveries.
|
|
15135
|
+
if (recovery.ready && headlessDispatchToken != null) {
|
|
15136
|
+
clearSessionRestartDispatchIfSame(ctx, headlessDispatchToken);
|
|
15137
|
+
}
|
|
15138
|
+
const observed = recovery.via === "observed-cycle";
|
|
15074
15139
|
// #1996: `recovery.ready &&` is LOAD-BEARING now that the wait above runs on
|
|
15075
15140
|
// both outcomes. Without it a tab that re-registered while the server was still
|
|
15076
15141
|
// unproven would report ready:true — turning the honest refusal this path
|
|
@@ -15857,13 +15922,7 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
15857
15922
|
overallDeadline,
|
|
15858
15923
|
reserveMs: reconnectWaitTiming().budgetMs,
|
|
15859
15924
|
});
|
|
15860
|
-
|
|
15861
|
-
// #742 r4/r5/r15: the dispatched restart was observed back — clear the
|
|
15862
|
-
// record, CLEAR-IF-SAME: only when the session still holds the token
|
|
15863
|
-
// THIS dispatch stamped (a concurrent dispatch's newer record survives).
|
|
15864
|
-
if (recovery.ready && acceptedDispatchToken != null) {
|
|
15865
|
-
clearSessionRestartDispatchIfSame(ctx, acceptedDispatchToken);
|
|
15866
|
-
}
|
|
15925
|
+
let recovery = await recoveryPromise;
|
|
15867
15926
|
// #400/#709: ComfyUI is healthy, but the panel's browser tab re-registers its own
|
|
15868
15927
|
// socket a moment later. The old socket can still be reachable after dispatch, so
|
|
15869
15928
|
// the generation waiter below requires a fresh hello before reporting readiness.
|
|
@@ -15882,11 +15941,24 @@ CHECKED FOR YOU: the graph read this message prescribes was just run, and it ` +
|
|
|
15882
15941
|
// it honestly could not give AND the reconnect wait it could have given, which is
|
|
15883
15942
|
// the only thing on this path that calls `ensureReachable()` to heal the session
|
|
15884
15943
|
// binding onto the returning tab. An unconfirmed boot now still gets watched.
|
|
15885
|
-
|
|
15886
|
-
|
|
15887
|
-
|
|
15888
|
-
|
|
15889
|
-
|
|
15944
|
+
// #1996 r2: the wait also continues /system_stats, so a boot that starts
|
|
15945
|
+
// listening in this reserved window is not reported unready while we are
|
|
15946
|
+
// still inside the handler.
|
|
15947
|
+
let tabBack;
|
|
15948
|
+
({ recovery, tabBack } = await awaitTabWhileContinuingRecovery({
|
|
15949
|
+
recovery,
|
|
15950
|
+
timing,
|
|
15951
|
+
healthBase,
|
|
15952
|
+
overallDeadline,
|
|
15953
|
+
ctx,
|
|
15954
|
+
preRestartPanelIdentity,
|
|
15955
|
+
}));
|
|
15956
|
+
// #742 r4/r5/r15: the dispatched restart was observed back — clear the
|
|
15957
|
+
// record, CLEAR-IF-SAME: only when the session still holds the token
|
|
15958
|
+
// THIS dispatch stamped (a concurrent dispatch's newer record survives).
|
|
15959
|
+
if (recovery.ready && acceptedDispatchToken != null) {
|
|
15960
|
+
clearSessionRestartDispatchIfSame(ctx, acceptedDispatchToken);
|
|
15961
|
+
}
|
|
15890
15962
|
if (!recovery.ready) {
|
|
15891
15963
|
const waited = Math.round(recovery.waited_ms / 1000);
|
|
15892
15964
|
// #1996: the refusal itself is NOT the defect and is left exactly as it was.
|