Add a Sleep GPU button that stops Comfy to free VRAM.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-08-30 19:19:41 -05:00
co-authored by Cursor
parent 3a90892859
commit 64179dd516
4 changed files with 184 additions and 6 deletions
+42 -2
View File
@@ -30,6 +30,17 @@
>
{{ gpuWaking ? 'Starting GPU…' : 'Wake GPU' }}
</button>
<button
v-if="showSleepGpu"
type="button"
class="rounded-full border px-3 py-1 hover:border-amber-300/50 hover:text-white disabled:cursor-not-allowed disabled:opacity-80"
:class="gpuSleeping ? 'border-amber-300/40 text-amber-100' : 'border-white/15 text-zinc-300'"
:disabled="gpuSleeping || rigBusy"
:title="gpuWakeError || (rigBusy ? 'Cancel the running job first' : (gpuSleeping ? 'Stopping Comfy on the GPU' : 'Stop Comfy on the GPU to free VRAM. Does not shut the PC down.'))"
@click="sleepGpu"
>
{{ gpuSleeping ? 'Stopping GPU…' : 'Sleep GPU' }}
</button>
</div>
<span class="hidden md:block text-zinc-400">{{ userName }}</span>
<button type="button" class="rounded-full border border-white/10 px-3 py-1 text-zinc-300 hover:border-amber-300/50 hover:text-white" @click="settingsOpen = true">
@@ -2453,6 +2464,7 @@ const comfyOk = ref(false)
const comfyBusy = ref(false)
const comfyAsleep = ref(false)
const gpuWaking = ref(false)
const gpuSleeping = ref(false)
const gpuWakeError = ref('')
const userName = ref('')
const authEnabled = ref(false)
@@ -2726,8 +2738,17 @@ const liveMaxStep = computed(() => (
const rigBusy = computed(() => (
comfyBusy.value || imageComfyBusy.value || videoBusy.value || editBusy.value
))
const showWakeGpu = computed(() => gpuWaking.value || (!comfyOk.value && !imageComfyOk.value))
const showWakeGpu = computed(() => gpuWaking.value || (!gpuSleeping.value && !comfyOk.value && !imageComfyOk.value))
const showSleepGpu = computed(() => gpuSleeping.value || ((comfyOk.value || imageComfyOk.value) && !gpuWaking.value))
const rigBadge = computed(() => {
if (gpuSleeping.value) {
return {
label: 'Stopping…',
className: 'border-amber-400/40 text-amber-200',
dot: 'bg-amber-400 animate-pulse',
title: 'Stopping Comfy on the GPU'
}
}
if (gpuWaking.value) {
return {
label: 'Starting…',
@@ -2857,6 +2878,7 @@ const recommendHint = computed(() => {
return 'Send this still and draft to Beast Qwen VL.'
})
const gpuSleepHint = computed(() => {
if (gpuSleeping.value) return 'Stopping Comfy on the GPU to free VRAM. The PC stays on.'
if (comfyOk.value || imageComfyOk.value) return ''
if (gpuWaking.value) return 'Starting Comfy on the GPU. Generate will wait in the job queue until it answers.'
if (comfyAsleep.value) return 'GPU is asleep. Generate will wake it — the first job can take a few minutes. Or click Wake GPU to pre-warm.'
@@ -3528,7 +3550,7 @@ async function pollComfyHealth() {
}
async function pokeGpu() {
if (gpuWaking.value) return
if (gpuWaking.value || gpuSleeping.value) return
gpuWaking.value = true
gpuWakeError.value = ''
try {
@@ -3550,6 +3572,24 @@ async function pokeGpu() {
}
}
async function sleepGpu() {
if (gpuSleeping.value || gpuWaking.value || rigBusy.value) return
gpuSleeping.value = true
gpuWakeError.value = ''
try {
await $fetch('/api/comfy/sleep', { method: 'POST' })
comfyOk.value = false
imageComfyOk.value = false
imageBeastOk.value = false
comfyAsleep.value = true
await pollComfyHealth()
} catch (error: any) {
gpuWakeError.value = error?.data?.statusMessage || error?.statusMessage || error?.message || 'Could not stop Comfy.'
} finally {
gpuSleeping.value = false
}
}
onMounted(async () => {
try {
withSound.value = localStorage.getItem('aigen-generate-sound') !== 'false'