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
+66
View File
@@ -10,6 +10,36 @@
<button type="button" class="rounded-full border border-white/10 px-3 py-1 text-sm text-zinc-400 hover:text-white" @click="emit('close')">Close</button>
</div>
<section class="mt-6">
<h3 class="text-sm font-semibold uppercase tracking-wider text-zinc-500">GPU</h3>
<div class="mt-2 space-y-3 rounded-2xl border border-white/10 bg-zinc-950/50 px-4 py-3">
<p class="text-sm text-zinc-400">
Stops Comfy on the desktop GPU so it drops out of VRAM. The PC stays on. Generate or Wake GPU will start it again.
</p>
<div class="flex flex-wrap items-center gap-2">
<button
type="button"
class="rounded-xl border px-3 py-2 text-sm disabled:cursor-not-allowed disabled:opacity-60"
:class="gpuSleeping ? 'border-amber-300/40 text-amber-100' : 'border-white/15 text-zinc-200 hover:border-amber-300/50 hover:text-white'"
:disabled="gpuSleeping || gpuWaking"
@click="sleepGpu"
>
{{ gpuSleeping ? 'Stopping GPU…' : 'Sleep GPU' }}
</button>
<button
type="button"
class="rounded-xl border px-3 py-2 text-sm disabled:cursor-not-allowed disabled:opacity-60"
:class="gpuWaking ? 'border-amber-300/40 text-amber-100' : 'border-amber-400/40 text-amber-200 hover:border-amber-300 hover:text-amber-50'"
:disabled="gpuWaking || gpuSleeping"
@click="wakeGpu"
>
{{ gpuWaking ? 'Starting GPU…' : 'Wake GPU' }}
</button>
</div>
<p v-if="gpuMessage" class="text-xs" :class="gpuError ? 'text-red-300' : 'text-zinc-500'">{{ gpuMessage }}</p>
</div>
</section>
<section class="mt-6">
<h3 class="text-sm font-semibold uppercase tracking-wider text-zinc-500">Storage</h3>
<div class="mt-2 rounded-2xl border border-white/10 bg-zinc-950/50 px-4 py-3">
@@ -256,6 +286,10 @@ const loginNext = ref('')
const drafts = reactive<Record<string, { name: string; protect: boolean; password: string; currentPassword: string }>>({})
const storageLoading = ref(true)
const storageError = ref('')
const gpuSleeping = ref(false)
const gpuWaking = ref(false)
const gpuError = ref(false)
const gpuMessage = ref('')
const storage = ref<{
libraryBytes: number
breakdown: { clips: number; stills: number; tmp: number; other: number }
@@ -392,6 +426,38 @@ async function loadStorage() {
}
}
async function sleepGpu() {
if (gpuSleeping.value || gpuWaking.value) return
gpuSleeping.value = true
gpuError.value = false
gpuMessage.value = 'Stopping Comfy on the GPU…'
try {
await $fetch('/api/comfy/sleep', { method: 'POST' })
gpuMessage.value = 'Comfy is stopped. VRAM is free until you generate or wake the GPU.'
} catch (error: any) {
gpuError.value = true
gpuMessage.value = error?.data?.statusMessage || error?.statusMessage || 'Could not stop Comfy.'
} finally {
gpuSleeping.value = false
}
}
async function wakeGpu() {
if (gpuWaking.value || gpuSleeping.value) return
gpuWaking.value = true
gpuError.value = false
gpuMessage.value = 'Starting Comfy on the GPU…'
try {
await $fetch('/api/comfy/wake', { method: 'POST' })
gpuMessage.value = 'Wake sent. The first job can still take a couple of minutes if Comfy is cold.'
} catch (error: any) {
gpuError.value = true
gpuMessage.value = error?.data?.statusMessage || error?.statusMessage || 'Could not wake the GPU.'
} finally {
gpuWaking.value = false
}
}
async function loadLoraKeys() {
loraRowsLoading.value = true
try {