From 1fa5b9e2b03d1b8a77088d8ba8e4a522e4fac700 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sun, 15 Mar 2026 18:15:35 -0700 Subject: [PATCH] feat(avocet): add cancel buttons for benchmark and fine-tune runs --- web/src/views/BenchmarkView.vue | 59 ++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/web/src/views/BenchmarkView.vue b/web/src/views/BenchmarkView.vue index 1ec80ac..7351b42 100644 --- a/web/src/views/BenchmarkView.vue +++ b/web/src/views/BenchmarkView.vue @@ -14,6 +14,13 @@ > {{ running ? '⏳ Running…' : results ? 'πŸ”„ Re-run' : 'β–Ά Run Benchmark' }} + @@ -36,8 +43,8 @@
- {{ running ? '⏳ Running benchmark…' : runError ? '❌ Failed' : 'βœ… Done' }} - + {{ running ? '⏳ Running benchmark…' : runCancelled ? '⏹ Cancelled' : runError ? '❌ Failed' : 'βœ… Done' }} +
{{ ftRunning ? '⏳ Training…' : 'β–Ά Run fine-tune' }} +
- {{ ftRunning ? '⏳ Training…' : ftError ? '❌ Failed' : 'βœ… Done' }} - + {{ ftRunning ? '⏳ Training…' : ftCancelled ? '⏹ Cancelled' : ftError ? '❌ Failed' : 'βœ… Done' }} +
([]) const ftError = ref('') const ftLogEl = ref(null) +const runCancelled = ref(false) +const ftCancelled = ref(false) + +async function cancelBenchmark() { + await fetch('/api/benchmark/cancel', { method: 'POST' }).catch(() => {}) +} + +async function cancelFinetune() { + await fetch('/api/finetune/cancel', { method: 'POST' }).catch(() => {}) +} + // ── Derived ────────────────────────────────────────────────────────────────── const modelNames = computed(() => Object.keys(results.value?.models ?? {})) const modelCount = computed(() => modelNames.value.length) @@ -328,6 +353,7 @@ function startBenchmark() { running.value = true runLog.value = [] runError.value = '' + runCancelled.value = false const url = `/api/benchmark/run${includeSlow.value ? '?include_slow=true' : ''}` useApiSSE( @@ -341,6 +367,10 @@ function startBenchmark() { if (event.type === 'error' && typeof event.message === 'string') { runError.value = event.message } + if (event.type === 'cancelled') { + running.value = false + runCancelled.value = true + } }, async () => { running.value = false @@ -363,6 +393,7 @@ function startFinetune() { ftRunning.value = true ftLog.value = [] ftError.value = '' + ftCancelled.value = false const params = new URLSearchParams({ model: ftModel.value, epochs: String(ftEpochs.value) }) useApiSSE( @@ -376,6 +407,10 @@ function startFinetune() { if (event.type === 'error' && typeof event.message === 'string') { ftError.value = event.message } + if (event.type === 'cancelled') { + ftRunning.value = false + ftCancelled.value = true + } }, async () => { ftRunning.value = false @@ -453,6 +488,22 @@ onMounted(() => { .btn-run:disabled { opacity: 0.5; cursor: not-allowed; } .btn-run:not(:disabled):hover { opacity: 0.85; } +.btn-cancel { + padding: 0.45rem 0.9rem; + background: transparent; + border: 1px solid var(--color-text-secondary, #6b7a99); + color: var(--color-text-secondary, #6b7a99); + border-radius: 0.4rem; + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + transition: background 0.15s; +} + +.btn-cancel:hover { + background: color-mix(in srgb, var(--color-text-secondary, #6b7a99) 12%, transparent); +} + /* ── Run log ────────────────────────────────────────────── */ .run-log { border: 1px solid var(--color-border, #d0d7e8);