Run image edit on Beast with Flux.2 Klein and stop routing jobs to Sidecar.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-08-27 09:06:50 -05:00
co-authored by Cursor
parent 6fec10febd
commit 13ecec949c
8 changed files with 899 additions and 212 deletions
+27 -54
View File
@@ -1,4 +1,4 @@
import { getImageComfyHost, setImageComfyHostOverride, imageComfyConfigured, getBeastImageHost, getSidecarImageHost, sameImageHost, withImageComfyHost, type ImageEditBox } from '~/server/utils/imageComfy'
import { getImageComfyHost, setImageComfyHostOverride, imageComfyConfigured, getBeastImageHost, withImageComfyHost, type ImageEditBox } from '~/server/utils/imageComfy'
export type ImageComfyState = 'online' | 'booting' | 'busy' | 'starting' | 'offline'
@@ -231,67 +231,40 @@ export function ensureImageComfyReady(onStatus: StatusFn = () => undefined) {
export async function pickImageEditHost(onStatus: StatusFn = () => undefined): Promise<ImageEditTarget> {
const beast = getBeastImageHost()
const sidecar = getSidecarImageHost()
if (!beast && !sidecar) {
if (!beast) {
throw createError({
statusCode: 503,
statusMessage: 'No image ComfyUI host is configured. Set COMFY_HOST (Beast) and/or IMAGE_COMFY_HOST (Sidecar).'
statusMessage: 'Beast ComfyUI is not configured. Set COMFY_HOST.'
})
}
if (beast) {
const health = await checkImageComfyHttp(2500, beast)
if (health.ok) {
const queue = await fetchQueueAt(beast)
if (queue.running === 0) {
onStatus({
state: 'online',
message: 'Beast is free. Editing on this machine.',
host: beast,
box: 'beast',
queueRunning: 0,
queuePending: queue.pending
})
return { host: beast, box: 'beast', label: 'Beast' }
}
const canOverflow = Boolean(sidecar && !sameImageHost(beast, sidecar))
onStatus({
state: 'busy',
message: canOverflow
? 'Beast is busy. Rolling over to Sidecar...'
: `Beast is busy (${queue.running} running). Waiting for a free slot...`,
host: beast,
box: 'beast',
queueRunning: queue.running,
queuePending: queue.pending
})
if (!canOverflow) {
await withImageComfyHost(beast, () => waitWhileBusy(onStatus))
return { host: beast, box: 'beast', label: 'Beast' }
}
} else if (sidecar && !sameImageHost(beast, sidecar)) {
onStatus({
state: 'offline',
message: 'Beast is offline. Trying Sidecar...',
host: beast,
box: 'beast'
})
}
const health = await checkImageComfyHttp(2500, beast)
if (!health.ok) {
throw createError({
statusCode: 503,
statusMessage: 'Beast is offline. Image edit runs on the 5080 only.'
})
}
if (sidecar && (!beast || !sameImageHost(beast, sidecar))) {
const queue = await fetchQueueAt(beast)
if (queue.running === 0) {
onStatus({
state: 'starting',
message: 'Checking Sidecar for this edit...',
host: sidecar,
box: 'sidecar'
state: 'online',
message: 'Beast is free. Editing on this machine.',
host: beast,
box: 'beast',
queueRunning: 0,
queuePending: queue.pending
})
await withImageComfyHost(sidecar, () => ensureImageComfyReady(onStatus))
return { host: sidecar, box: 'sidecar', label: 'Sidecar' }
return { host: beast, box: 'beast', label: 'Beast' }
}
throw createError({
statusCode: 503,
statusMessage: 'Beast is unavailable and Sidecar is not configured.'
onStatus({
state: 'busy',
message: `Beast is busy (${queue.running} running). Waiting for a free slot...`,
host: beast,
box: 'beast',
queueRunning: queue.running,
queuePending: queue.pending
})
await withImageComfyHost(beast, () => waitWhileBusy(onStatus))
return { host: beast, box: 'beast', label: 'Beast' }
}