feat: Add Brain Monitor dashboard and live API stats

This commit is contained in:
Riz Ashraf committed 2026-09-08 15:09:44 +01:00
1 parent 3239e32866
commit 18fd05bb11
10 files changed
+672 -80

No files matched your search

+35 -1
View File
@@ -3,6 +3,7 @@ mod models;
mod state;
mod store;
mod tools;
mod search;
use crate::handlers::MemoryHandler;
use crate::models::*;
@@ -84,6 +85,7 @@ async fn reconcile_worker(state: Arc<MemoryState>) {
let has_files = glob::glob(&pattern).map(|p| p.count() > 0).unwrap_or(false);
if has_local || has_files {
state.apply_sync_write(|_master| {});
state.rebuild_index();
}
let now = SystemTime::now()
@@ -152,6 +154,35 @@ fn run_server(state: Arc<MemoryState>) -> SdkResult<()> {
axum::routing::get(|| async move {
axum::http::StatusCode::OK
}),
).with_route(
"/dashboard",
axum::routing::get(|| async move {
axum::response::Html(include_str!("dashboard.html"))
}),
).with_route(
"/api/stats",
axum::routing::get({
let state_clone = 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
}))
}
}),
);
println!("MCP Memory Server running on http://0.0.0.0:3000/sse");
@@ -190,7 +221,7 @@ fn main() -> SdkResult<()> {
{
// This shouldn't be executed on linux natively anymore due to workspace split,
// but keeping it as a fallback.
let target_url = cli.target.as_deref().unwrap_or("http://host.docker.internal:3000");
let target_url = cli.target.as_deref().unwrap_or("http://127.0.0.1:3000");
let _ = proxy::run_proxy(target_url);
return Ok(());
}
@@ -211,6 +242,7 @@ fn main() -> SdkResult<()> {
session_graph: RwLock::new(KnowledgeGraph::default()),
base_dir: base.clone(),
master_cache: RwLock::new((KnowledgeGraph::default(), SystemTime::UNIX_EPOCH)),
search_index: RwLock::new(crate::search::MemoryIndex::new().unwrap()),
ledger: Store::new(base.join("audit_ledger.json")),
sticky: Store::new(base.join("sticky_notes.json")),
tasks: Store::new(base.join("tasks.json")),
@@ -231,6 +263,8 @@ fn main() -> SdkResult<()> {
context_workspaces: Store::new(base.join("context_workspaces.json")),
});
state.rebuild_index();
if let Some(command) = cli.command {
match command {
Commands::Gate { subcmd } => {