Spaces:
Sleeping
Sleeping
| export function initProgressPanel(ctx) { | |
| const sseUrl = '/api/telemetry/stream'; | |
| let eventSource = null; | |
| function connect() { | |
| if (eventSource) return; | |
| eventSource = new EventSource(sseUrl); | |
| eventSource.onmessage = (event) => { | |
| try { | |
| const payload = JSON.parse(event.data); | |
| const { event: eventName, data } = payload; | |
| if (eventName === 'ingest_progress') { | |
| handleIngestProgress(data); | |
| } else if (eventName === 'sae_progress') { | |
| handleSaeProgress(data); | |
| } | |
| } catch (err) { | |
| console.error("Error parsing telemetry SSE event:", err); | |
| } | |
| }; | |
| eventSource.onerror = (err) => { | |
| console.warn("SSE connection error, closing EventSource:", err); | |
| if (eventSource) { | |
| eventSource.close(); | |
| eventSource = null; | |
| } | |
| // Auto reconnect after 3 seconds | |
| setTimeout(connect, 3000); | |
| }; | |
| } | |
| function handleIngestProgress(data) { | |
| const container = document.getElementById('relief-ingest-progress'); | |
| const phaseLabel = document.getElementById('relief-ingest-phase'); | |
| const fillBar = document.getElementById('relief-ingest-fill'); | |
| const subLabel = document.getElementById('relief-ingest-sublabel'); | |
| const pctLabel = document.getElementById('relief-ingest-pct'); | |
| const resultLabel = document.getElementById('relief-ingest-result'); | |
| const shield = document.getElementById('relief-ingest-shield'); | |
| if (!container) return; | |
| if (data.status === 'processing') { | |
| container.style.display = 'flex'; | |
| container.classList.add('active'); | |
| if (shield) shield.style.display = 'block'; | |
| if (fillBar) fillBar.style.width = `${data.progress}%`; | |
| if (pctLabel) pctLabel.textContent = `${data.progress}%`; | |
| let stageMsg = "Processing..."; | |
| if (data.stage === 'extract_text') { | |
| stageMsg = "Extracting text from PDF..."; | |
| if (subLabel && data.current && data.total) { | |
| subLabel.textContent = `Page ${data.current} / ${data.total}`; | |
| } | |
| } else if (data.stage === 'cleaning') { | |
| stageMsg = "Normalizing text..."; | |
| if (subLabel) subLabel.textContent = ""; | |
| } else if (data.stage === 'chunking') { | |
| stageMsg = "Splitting text into chunks..."; | |
| if (subLabel) subLabel.textContent = ""; | |
| } else if (data.stage === 'embeddings') { | |
| stageMsg = "Generating semantic embeddings..."; | |
| if (subLabel && data.current && data.total) { | |
| subLabel.textContent = `Chunk ${data.current} / ${data.total}`; | |
| } | |
| } else if (data.stage === 'storing') { | |
| stageMsg = "Storing in database..."; | |
| if (subLabel) subLabel.textContent = ""; | |
| } | |
| if (phaseLabel) phaseLabel.textContent = stageMsg; | |
| if (resultLabel) resultLabel.textContent = ""; | |
| } else if (data.status === 'complete') { | |
| if (fillBar) fillBar.style.width = '100%'; | |
| if (pctLabel) pctLabel.textContent = '100%'; | |
| if (phaseLabel) phaseLabel.textContent = "Ingestion complete!"; | |
| if (subLabel) subLabel.textContent = `${data.chunks} chunks generated`; | |
| if (resultLabel) { | |
| resultLabel.style.color = 'var(--color-semantic-success)'; | |
| resultLabel.textContent = `✅ Successfully indexed ${data.chunks} chunks.`; | |
| } | |
| setTimeout(() => { | |
| if (shield) shield.style.display = 'none'; | |
| container.style.display = 'none'; | |
| container.classList.remove('active'); | |
| if (resultLabel) resultLabel.textContent = ""; | |
| }, 3000); | |
| // Reload file selector list! | |
| if (ctx && ctx.refresh && typeof ctx.refresh.reliefFiles === 'function') { | |
| ctx.refresh.reliefFiles(data.filename); | |
| } | |
| } else if (data.status === 'error') { | |
| if (phaseLabel) phaseLabel.textContent = "Error"; | |
| if (resultLabel) { | |
| resultLabel.style.color = 'var(--color-semantic-error)'; | |
| resultLabel.textContent = `❌ ${data.message || 'Unknown error'}`; | |
| } | |
| if (shield) shield.style.display = 'none'; | |
| setTimeout(() => { | |
| container.style.display = 'none'; | |
| container.classList.remove('active'); | |
| }, 6000); | |
| } | |
| } | |
| function handleSaeProgress(data) { | |
| const progressContainer = document.getElementById('sae-training-progress'); | |
| const fill = document.getElementById('sae-training-fill'); | |
| const label = document.getElementById('sae-training-label'); | |
| const saeStatusHint = document.getElementById('sae-status-hint'); | |
| const saeToggle = document.getElementById('sae-space-toggle'); | |
| const btnTrainSae = document.getElementById('btn-train-sae'); | |
| if (!progressContainer) return; | |
| if (data.status === 'loading_vectors') { | |
| progressContainer.style.display = 'flex'; | |
| if (fill) fill.style.width = '0%'; | |
| if (label) label.textContent = "Loading vectors from database..."; | |
| if (saeStatusHint) saeStatusHint.textContent = "Preparing data..."; | |
| if (saeToggle) saeToggle.setAttribute('disabled', 'true'); | |
| if (btnTrainSae) { | |
| btnTrainSae.setAttribute('disabled', 'true'); | |
| btnTrainSae.textContent = '⏳ Preparing...'; | |
| } | |
| } else if (data.status === 'training') { | |
| progressContainer.style.display = 'flex'; | |
| if (fill) fill.style.width = `${data.progress}%`; | |
| if (label) { | |
| label.textContent = `Epoch ${data.current_epoch}/${data.total_epochs} (Loss: ${data.loss.toFixed(6)})`; | |
| } | |
| if (saeStatusHint) { | |
| saeStatusHint.textContent = "⏳ Training SAE on server..."; | |
| saeStatusHint.style.color = 'var(--color-brand-secondary)'; | |
| } | |
| if (btnTrainSae) { | |
| btnTrainSae.textContent = `⏳ Training (${data.progress}%)`; | |
| btnTrainSae.setAttribute('disabled', 'true'); | |
| } | |
| } else if (data.status === 'success') { | |
| if (fill) fill.style.width = '100%'; | |
| if (label) label.textContent = "Training complete."; | |
| setTimeout(() => { | |
| progressContainer.style.display = 'none'; | |
| }, 3000); | |
| // Trigger saeStatus UI refresh | |
| if (ctx && ctx.refresh && typeof ctx.refresh.saeStatus === 'function') { | |
| ctx.refresh.saeStatus(); | |
| } | |
| } else if (data.status === 'failed') { | |
| if (label) label.textContent = `Failed: ${data.error_message}`; | |
| if (saeStatusHint) { | |
| saeStatusHint.textContent = `❌ Failed: ${data.error_message}`; | |
| saeStatusHint.style.color = 'var(--color-semantic-error)'; | |
| } | |
| setTimeout(() => { | |
| progressContainer.style.display = 'none'; | |
| }, 5000); | |
| if (ctx && ctx.refresh && typeof ctx.refresh.saeStatus === 'function') { | |
| ctx.refresh.saeStatus(); | |
| } | |
| } | |
| } | |
| connect(); | |
| } | |