From 36674df176dc9f7af22f3240f6cb433e9e886eb2 Mon Sep 17 00:00:00 2001 From: Riz Ashraf Date: Sat, 12 Sep 2026 09:17:59 +0100 Subject: [PATCH] feat(server): completely overhaul dashboard into interactive memory hub Added interactive knowledge graph visualization, omni-search, kanban task board, and real-time live agent activity stream. --- server/src/add_endpoints.py | 39 +++++ server/src/dashboard.html | 289 ++++++++++++++++++++++-------------- server/src/main.rs | 18 +++ 3 files changed, 234 insertions(+), 112 deletions(-) create mode 100644 server/src/add_endpoints.py diff --git a/server/src/add_endpoints.py b/server/src/add_endpoints.py new file mode 100644 index 0000000..64e2e8b --- /dev/null +++ b/server/src/add_endpoints.py @@ -0,0 +1,39 @@ +import re + +endpoints = """ + .route("/api/graph", get({ + let state_clone = app_state.handler.state.clone(); + move || async move { + let graph = state_clone.get_full_graph(); + axum::Json(graph) + } + })) + .route("/api/tasks", get({ + let state_clone = app_state.handler.state.clone(); + move || async move { + let tasks = state_clone.tasks.read(); + axum::Json(tasks.clone()) + } + })) + .route("/api/search", get({ + let state_clone = app_state.handler.state.clone(); + move |axum::extract::Query(params): axum::extract::Query>| async move { + if let Some(q) = params.get("q") { + if let Ok(idx) = state_clone.search_index.read() { + let results = idx.search(q, 50); + return axum::Json(serde_json::json!({ "results": results })); + } + } + axum::Json(serde_json::json!({ "results": [] })) + } + })) +""" + +filepath = "C:\\Users\\reazul.ashraf\\workspace\\rust\\mcp-memory\\server\\src\\main.rs" +with open(filepath, "r", encoding="utf-8") as f: + content = f.read() + +content = content.replace('.route("/api/stats",', endpoints + ' .route("/api/stats",') + +with open(filepath, "w", encoding="utf-8") as f: + f.write(content) diff --git a/server/src/dashboard.html b/server/src/dashboard.html index 3d3d503..0e728d2 100644 --- a/server/src/dashboard.html +++ b/server/src/dashboard.html @@ -1,139 +1,204 @@ - Brain Monitor + Antigravity Memory Hub +
-

🧠 Antigravity Brain Monitor

+

🧠 Antigravity Memory Hub

System Online
-
-
-
Entities
-
-
+
+
+

Knowledge Graph

+
-
-
Relations
-
-
-
-
-
Active Tasks
-
-
-
-
-
Snippets
-
-
-
-
-
Tech Debt
-
-
-
-
-
ADRs
-
-
-
-
-
Audit Ledger
-
-
-
-
-
Sticky Notes
-
-
-
-
-
Error Fixes
-
-
-
-
-
Pinned Files
-
-
-
-
-
Session Summaries
-
-
-
-
-
Handoff Memos
-
-
-
-
-
Env Fingerprints
-
-
-
-
-
Env Requirements
-
-
-
-
-
Milestones
-
-
-
-
-
Environments
-
-
-
-
-
PR Checklists
-
-
-
-
-
Safety Gates
-
-
-
-
-
Workspaces
-
-
+ +
+
+

Omni-Search

+ +
+
+ +
+

Task Board

+
+
+

TODO / IN PROGRESS

+
+
+
+

COMPLETED

+
+
+
+
+ +
+

Live Activity Feed

+
+
+ diff --git a/server/src/main.rs b/server/src/main.rs index 5f18ff0..0539efb 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -426,6 +426,24 @@ async fn message_handler( let session_id = query.session_id.clone(); let clients = Arc::clone(&state); + let activity_msg = if let Some(method) = payload.get("method").and_then(|m| m.as_str()) { + if method == "tools/call" { + let name = payload.get("params").and_then(|p| p.get("name")).and_then(|n| n.as_str()).unwrap_or("unknown_tool"); + Some(format!("Agent executed tool: {}", name)) + } else { + None + } + } else { + None + }; + + if let Some(msg) = activity_msg { + let clients_map = clients.clients.read().unwrap().clone(); + for tx in clients_map.values() { + let _ = tx.send(Ok(Event::default().event("activity").data(msg.clone()))); + } + } + tokio::spawn(async move { if let Some(response) = handler.handle_request(payload).await { let tx_opt = clients.clients.read().unwrap().get(&session_id).cloned();