From 61876f18e5da03c34141bc35c58ee6e487814ade Mon Sep 17 00:00:00 2001 From: Giancarmine Salucci Date: Wed, 13 May 2026 03:00:58 +0200 Subject: [PATCH] fix(progress): currentPhase and live messages now update in real-time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three issues causing the 'prepping → done' jump: 1. +page.svelte updateQueueItem: never applied update.phase to currentPhase, so CookingHero always showed 'Prepping' regardless of actual backend state. Fixed: currentPhase: update.phase ?? prev. 2. +page.svelte updateQueueItem: progress events (type:'progress') were discarded. Fixed: append data.event to progressEvents array so live messages are available to components. 3. stream/+server.ts: initial SSE snapshot omitted phase field, so items already in-progress on page load showed wrong phase. Fixed. Bonus: CookingHero now shows the latest user-friendly progress message (status/complete/model_loading types) as a live scrolling sub-line under the phase hint. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/routes/+page.svelte | 17 ++++++++++---- src/routes/api/queue/stream/+server.ts | 1 + src/routes/components/CookingHero.svelte | 28 +++++++++++++++++++++++- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index ae858d3..b21fea3 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -184,12 +184,21 @@ function updateQueueItem(update: QueueStatusUpdate) { const idx = items.findIndex((i) => i.id === update.itemId); if (idx >= 0) { + const prev = items[idx]; + // Append progress events (type: 'progress' carries data.event) + const newEvents = update.data?.event + ? [...(prev.progressEvents ?? []), update.data.event] + : (prev.progressEvents ?? []); + items[idx] = { - ...items[idx], + ...prev, status: update.status, - phases: update.progress || items[idx].phases, - results: update.results || items[idx].results, - error: update.error || items[idx].error, + // currentPhase is sent as update.phase on status_change events + currentPhase: update.phase ?? prev.currentPhase, + phases: update.progress || prev.phases, + progressEvents: newEvents, + results: update.results || prev.results, + error: update.error || prev.error, updatedAt: update.timestamp }; // Keep selectedItem in sync diff --git a/src/routes/api/queue/stream/+server.ts b/src/routes/api/queue/stream/+server.ts index 8a6de6c..710e7de 100644 --- a/src/routes/api/queue/stream/+server.ts +++ b/src/routes/api/queue/stream/+server.ts @@ -124,6 +124,7 @@ export const GET: RequestHandler = async ({ url, request }) => { status: item.status, timestamp: new Date().toISOString(), url: item.url, + phase: item.currentPhase, progress: item.phases, results: item.results, error: item.error diff --git a/src/routes/components/CookingHero.svelte b/src/routes/components/CookingHero.svelte index 8b8829a..2d1742d 100644 --- a/src/routes/components/CookingHero.svelte +++ b/src/routes/components/CookingHero.svelte @@ -40,6 +40,19 @@ if (diff < 3600) return Math.floor(diff / 60) + 'm ago'; return Math.floor(diff / 3600) + 'h ago'; } + + // Latest progress message — shown as a live sub-status inside the hero. + // Only show user-friendly event types (skip low-level extraction method attempts). + const SHOW_TYPES = new Set(['status', 'complete', 'model_loading', 'error', 'retry']); + const latestMsg = $derived.by(() => { + const events = item.progressEvents ?? []; + for (let i = events.length - 1; i >= 0; i--) { + const ev = events[i]; + if (!ev?.message || ev.message.length <= 3) continue; + if (SHOW_TYPES.has(ev.type)) return ev.message as string; + } + return null; + });