From 2c217104dbf96f86f90b87b65264369934544ee0 Mon Sep 17 00:00:00 2001 From: Kimi Agent Date: Fri, 20 Mar 2026 16:22:15 -0400 Subject: [PATCH] feat: real-time Spark visualization in Mission Control (#615) Co-authored-by: Kimi Agent Co-committed-by: Kimi Agent --- src/dashboard/templates/mission_control.html | 69 ++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/dashboard/templates/mission_control.html b/src/dashboard/templates/mission_control.html index 7447a24..27acbd1 100644 --- a/src/dashboard/templates/mission_control.html +++ b/src/dashboard/templates/mission_control.html @@ -138,6 +138,47 @@ + +{% from "macros.html" import panel %} +
+
+
+

Spark Intelligence

+
+ Loading... +
+
+
+
+
-
+
Events
+
+
+
-
+
Memories
+
+
+
-
+
Predictions
+
+
+
+
+ {% call panel("SPARK TIMELINE", id="spark-timeline-panel", + hx_get="/spark/timeline", + hx_trigger="load, every 10s") %} +
+

Loading timeline...

+
+ {% endcall %} + {% call panel("SPARK INSIGHTS", id="spark-insights-panel", + hx_get="/spark/insights", + hx_trigger="load, every 30s") %} +

Loading insights...

+ {% endcall %} +
+
+
@@ -428,7 +469,34 @@ async function loadGrokStats() { } } +// Load Spark status +async function loadSparkStatus() { + try { + var response = await fetch('/spark'); + var data = await response.json(); + var st = data.status || {}; + + document.getElementById('spark-events').textContent = st.total_events || 0; + document.getElementById('spark-memories').textContent = st.total_memories || 0; + document.getElementById('spark-predictions').textContent = st.total_predictions || 0; + + var badge = document.getElementById('spark-status-badge'); + if (st.total_events > 0) { + badge.textContent = 'Active'; + badge.className = 'badge badge-success'; + } else { + badge.textContent = 'Idle'; + badge.className = 'badge badge-warning'; + } + } catch (error) { + var badge = document.getElementById('spark-status-badge'); + badge.textContent = 'Offline'; + badge.className = 'badge badge-danger'; + } +} + // Initial load +loadSparkStatus(); loadSovereignty(); loadHealth(); loadSwarmStats(); @@ -442,5 +510,6 @@ setInterval(loadHealth, 10000); setInterval(loadSwarmStats, 5000); setInterval(updateHeartbeat, 5000); setInterval(loadGrokStats, 10000); +setInterval(loadSparkStatus, 15000); {% endblock %}