diff --git a/server/src/dashboard.html b/server/src/dashboard.html new file mode 100644 index 0000000..54a580d --- /dev/null +++ b/server/src/dashboard.html @@ -0,0 +1,73 @@ + + + + Brain Monitor + + + +
+

🧠 Antigravity Brain Monitor

+
System Online
+
+ +
+
+
Entities
+
-
+
+
+
Relations
+
-
+
+
+
Active Tasks
+
-
+
+
+
Snippets
+
-
+
+
+
Tech Debt
+
-
+
+
+
ADRs
+
-
+
+
+ + + + diff --git a/server/src/main.rs b/server/src/main.rs index 1e26993..75edd27 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -139,6 +139,32 @@ fn run_server(state: Arc) -> Result<(), Box> let app = Router::new() .route("/sse", get(sse_handler)) .route("/messages", post(message_handler)) + .route("/health", get(health_handler)) + .route("/dashboard", get(|| async move { + axum::response::Html(include_str!("dashboard.html")) + })) + .route("/api/stats", get({ + let state_clone = app_state.handler.state.clone(); + move || async move { + let (entities, relations) = { + let graph = state_clone.get_full_graph(); + (graph.entities.len(), graph.relations.len()) + }; + let tasks = state_clone.tasks.read().len(); + let snippets = state_clone.snippets.read().len(); + let tech_debts = state_clone.tech_debts.read().len(); + let adrs = state_clone.adrs.read().len(); + + axum::Json(serde_json::json!({ + "entities": entities, + "relations": relations, + "tasks": tasks, + "snippets": snippets, + "tech_debts": tech_debts, + "adrs": adrs + })) + } + })) .with_state(app_state); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); @@ -162,6 +188,10 @@ async fn sse_handler( Sse::new(stream).keep_alive(axum::response::sse::KeepAlive::new()) } +async fn health_handler() -> &'static str { + "OK" +} + #[derive(serde::Deserialize)] struct SessionQuery { #[serde(rename = "sessionId")]