Files
aigen/scripts/comfy-host-agent.mjs
T
TowstyandCursor f5829995c8 Start ComfyUI automatically before queueing MiniMax jobs.
Health-check /system_stats, wait if the desktop is booting or busy, and start the host instance when it is fully offline.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-25 19:39:28 -05:00

80 lines
2.9 KiB
JavaScript

import http from 'node:http'
import { execFile, spawn } from 'node:child_process'
import { promisify } from 'node:util'
const execFileAsync = promisify(execFile)
const port = Number(process.env.COMFY_CONTROL_PORT || 8199)
const token = process.env.COMFY_CONTROL_TOKEN || ''
const comfyHttp = (process.env.COMFY_HOST || 'http://127.0.0.1:8188').replace(/\/$/, '')
function json(res, status, body) {
const payload = JSON.stringify(body)
res.writeHead(status, { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) })
res.end(payload)
}
function authorized(req) {
if (!token) return true
const header = String(req.headers.authorization || '')
return header === `Bearer ${token}`
}
async function httpUp() {
try {
const res = await fetch(`${comfyHttp}/system_stats`, { signal: AbortSignal.timeout(2500) })
return res.ok
} catch {
return false
}
}
async function processUp() {
try {
const { stdout } = await execFileAsync('tasklist', ['/FO', 'CSV', '/NH'], { windowsHide: true, timeout: 4000 })
if (/Comfy Desktop|ComfyUI/i.test(stdout)) return true
} catch { /* ignore */ }
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"
], { windowsHide: true, timeout: 6000 })
return Boolean(String(stdout).trim())
} catch {
return false
}
}
function launchCommand() {
if (process.env.COMFY_LAUNCH_CMD) return process.env.COMFY_LAUNCH_CMD
const local = process.env.LOCALAPPDATA || ''
const desktop = `${local}\\Programs\\Comfy Desktop\\Comfy Desktop.exe`
return `start "" "${desktop}"`
}
function startComfy() {
const command = launchCommand()
const child = spawn(command, { shell: true, detached: true, stdio: 'ignore', windowsHide: true })
child.unref()
return { started: true, command }
}
const server = http.createServer(async (req, res) => {
if (!authorized(req)) return json(res, 401, { ok: false, error: 'unauthorized' })
const url = new URL(req.url || '/', 'http://localhost')
if (req.method === 'GET' && url.pathname === '/status') {
const [httpReady, process] = await Promise.all([httpUp(), processUp()])
return json(res, 200, { ok: true, http: httpReady, process })
}
if (req.method === 'POST' && url.pathname === '/start') {
if (await httpUp()) return json(res, 200, { ok: true, started: false, already: true })
if (await processUp()) return json(res, 200, { ok: true, started: false, booting: true })
const launched = startComfy()
return json(res, 200, { ok: true, ...launched })
}
json(res, 404, { ok: false, error: 'not found' })
})
server.listen(port, '0.0.0.0', () => {
console.log(JSON.stringify({ src: 'comfy-host-agent', event: 'listen', port, comfyHttp }))
})