diff --git a/scripts/comfy-host-agent.mjs b/scripts/comfy-host-agent.mjs index 760815c..9fd8314 100644 --- a/scripts/comfy-host-agent.mjs +++ b/scripts/comfy-host-agent.mjs @@ -183,6 +183,7 @@ function markAsleep() { lastHealthyPort = 0 lastProcessUp = false lastLaunchAt = 0 + probeSkipUntil.clear() setProxyTarget(0) } @@ -199,6 +200,11 @@ async function syncProxy() { return healthyPort } +// PowerShell -Command text used to contain the literal main.py path, so the +// probe process matched itself and /start forever returned already/booting. +const PS_COMFY_MAIN = + "Get-CimInstance Win32_Process | Where-Object { $_.Name -match '^python(w)?\\.exe$' -and $_.CommandLine -match ('ComfyUI' + '[\\\\/]main\\.py') } | Select-Object -First 1 -ExpandProperty ProcessId" + async function processUp() { try { const { stdout } = await execFileAsync('tasklist', ['/FO', 'CSV', '/NH'], { windowsHide: true, timeout: 4000 }) @@ -207,7 +213,7 @@ async function processUp() { try { const { stdout } = await execFileAsync('powershell.exe', [ '-NoProfile', '-Command', - "Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'ComfyUI\\\\main.py|ComfyUI/main.py' } | Select-Object -First 1 -ExpandProperty ProcessId" + PS_COMFY_MAIN ], { windowsHide: true, timeout: 6000 }) return Boolean(String(stdout).trim()) } catch { @@ -299,7 +305,7 @@ async function pythonMainUp() { if (!/python(?:w)?\.exe/i.test(stdout)) return false const { stdout: verbose } = await execFileAsync('powershell.exe', [ '-NoProfile', '-Command', - "Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'ComfyUI\\\\main.py|ComfyUI/main.py' } | Select-Object -First 1 -ExpandProperty ProcessId" + PS_COMFY_MAIN ], { windowsHide: true, timeout: 2500 }) return Boolean(String(verbose).trim()) } catch { @@ -482,7 +488,7 @@ async function stopComfyProcesses() { try { const { stdout } = await execFileAsync('powershell.exe', [ '-NoProfile', '-Command', - "Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'ComfyUI\\\\main.py|ComfyUI/main.py' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue; $_.ProcessId }" + "Get-CimInstance Win32_Process | Where-Object { $_.Name -match '^python(w)?\\.exe$' -and $_.CommandLine -match ('ComfyUI' + '[\\\\/]main\\.py') } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue; $_.ProcessId }" ], { windowsHide: true, timeout: 8000 }) if (String(stdout).trim()) killed.push('main.py') } catch { /* ignore */ } @@ -836,10 +842,10 @@ const server = http.createServer(async (req, res) => { return json(res, 200, { ok: true, started: false, already: true, asleep: false, port: healthyPort, proxyPort }) } const listenPort = desktopListenPort() - const processAlive = lastProcessUp || await processUp().catch(() => false) || await pythonMainUp().catch(() => false) + // Do not trust lastProcessUp alone — force-stop can leave it sticky while Comfy is dead. + const processAlive = await processUp().catch(() => false) || await pythonMainUp().catch(() => false) const portBusy = await portInUse(listenPort) - const recentlySlow = [...probeSkipUntil.entries()].some(([, until]) => Date.now() < until) - if (processAlive || portBusy || recentlySlow) { + if (processAlive || portBusy) { markWork() lastProcessUp = true if (portBusy) setProxyTarget(listenPort) @@ -853,10 +859,12 @@ const server = http.createServer(async (req, res) => { proxyPort }) } - if (lastLaunchAt && Date.now() - lastLaunchAt < 5 * 60_000) { + // Only honor launch cooldown if we actually spawned recently; never block a real cold start. + if (lastLaunchAt && Date.now() - lastLaunchAt < 45_000 && await processUp().catch(() => false)) { return json(res, 200, { ok: true, started: false, already: true, booting: true, asleep: false, proxyPort }) } stoppedByAgent = false + probeSkipUntil.clear() lastLaunchAt = Date.now() const launched = await startComfy() if (launched.port) {