feat: Add Brain Monitor dashboard and live API stats
This commit is contained in:
1 parent
3239e32866
commit
18fd05bb11
10 files changed
+672
-80
No files matched your search
+63
-71
@@ -120,6 +120,9 @@ impl ServerHandler for MemoryHandler {
|
||||
} {
|
||||
let entity: Entity = e;
|
||||
if !entity.name.is_empty() {
|
||||
if let Ok(idx) = self.state.search_index.read() {
|
||||
let _ = idx.index_entity(&entity);
|
||||
}
|
||||
g.entities.insert(entity.name.clone(), entity);
|
||||
}
|
||||
}
|
||||
@@ -267,29 +270,19 @@ impl ServerHandler for MemoryHandler {
|
||||
}
|
||||
"search_nodes" => {
|
||||
let req: SearchNodesTool = parse_args(args)?;
|
||||
let query = req.query.to_lowercase();
|
||||
let tokens: Vec<&str> = query.split_whitespace().collect();
|
||||
let matches = if let Ok(idx) = self.state.search_index.read() {
|
||||
idx.search(&req.query, req.namespace.as_deref()).unwrap_or_default()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let mut result = KnowledgeGraph::default();
|
||||
for (name, e) in self.state.get_full_graph().entities {
|
||||
if let Some(ns) = &req.namespace
|
||||
&& e.namespace != *ns
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let name_low = name.to_lowercase();
|
||||
let type_low = e.entity_type.to_lowercase();
|
||||
let full_txt = format!(
|
||||
"{} {} {}",
|
||||
name_low,
|
||||
type_low,
|
||||
e.observations.join(" ").to_lowercase()
|
||||
);
|
||||
let matched = full_txt.contains(&query)
|
||||
|| (!tokens.is_empty() && tokens.iter().all(|&t| full_txt.contains(t)))
|
||||
|| strsim::jaro_winkler(&name_low, &query) > 0.85
|
||||
|| strsim::jaro_winkler(&type_low, &query) > 0.85;
|
||||
if matched {
|
||||
result.entities.insert(name, e);
|
||||
let full = self.state.get_full_graph();
|
||||
for (id, doc_type) in matches {
|
||||
if doc_type == "entity" {
|
||||
if let Some(e) = full.entities.get(&id) {
|
||||
result.entities.insert(id, e.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
let data = serde_json::to_string(&result).unwrap_or_default();
|
||||
@@ -456,16 +449,20 @@ impl ServerHandler for MemoryHandler {
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
let id = uuid::Uuid::new_v4().to_string();
|
||||
let task = Task {
|
||||
id: id.clone(),
|
||||
title: req.title,
|
||||
status: "pending".to_string(),
|
||||
description: req.description,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
git_branch: req.git_branch,
|
||||
};
|
||||
if let Ok(idx) = self.state.search_index.read() {
|
||||
let _ = idx.index_task(&task);
|
||||
}
|
||||
self.state.tasks.modify(|tasks| {
|
||||
tasks.push(Task {
|
||||
id: id.clone(),
|
||||
title: req.title,
|
||||
status: "pending".to_string(),
|
||||
description: req.description,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
git_branch: req.git_branch,
|
||||
});
|
||||
tasks.push(task);
|
||||
});
|
||||
Ok(ServerResult::from(CallToolResult::text_content(vec![
|
||||
format!("Task added with ID: {}", id).into(),
|
||||
@@ -1098,47 +1095,42 @@ impl ServerHandler for MemoryHandler {
|
||||
}
|
||||
"omni_search" => {
|
||||
let req: OmniSearchTool = parse_args(args)?;
|
||||
let matches = if let Ok(idx) = self.state.search_index.read() {
|
||||
idx.search(&req.query, req.namespace.as_deref()).unwrap_or_default()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let mut kg = KnowledgeGraph::default();
|
||||
let mut tasks = Vec::new();
|
||||
let mut snippets = Vec::new();
|
||||
let mut adrs = Vec::new();
|
||||
|
||||
let full = self.state.get_full_graph();
|
||||
for (id, doc_type) in &matches {
|
||||
if doc_type == "entity" {
|
||||
if let Some(e) = full.entities.get(id) {
|
||||
kg.entities.insert(id.clone(), e.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
for t in self.state.tasks.read() {
|
||||
if matches.iter().any(|(id, typ)| id == &t.id && typ == "task") {
|
||||
tasks.push(t);
|
||||
}
|
||||
}
|
||||
for s in self.state.snippets.read() {
|
||||
if matches.iter().any(|(id, typ)| id == &s.name && typ == "snippet") {
|
||||
snippets.push(s);
|
||||
}
|
||||
}
|
||||
for a in self.state.adrs.read() {
|
||||
if matches.iter().any(|(id, typ)| id == &a.id && typ == "adr") {
|
||||
adrs.push(a);
|
||||
}
|
||||
}
|
||||
|
||||
let q = req.query.to_lowercase();
|
||||
|
||||
let mut kg = self.state.get_full_graph();
|
||||
kg.entities.retain(|name, e| {
|
||||
(req.namespace.is_none() || e.namespace == *req.namespace.as_ref().unwrap())
|
||||
&& (name.to_lowercase().contains(&q)
|
||||
|| e.entity_type.to_lowercase().contains(&q)
|
||||
|| e.observations.join(" ").to_lowercase().contains(&q))
|
||||
});
|
||||
|
||||
let tasks: Vec<_> = self
|
||||
.state
|
||||
.tasks
|
||||
.read()
|
||||
.into_iter()
|
||||
.filter(|t| {
|
||||
t.title.to_lowercase().contains(&q)
|
||||
|| t.description.to_lowercase().contains(&q)
|
||||
})
|
||||
.collect();
|
||||
let snippets: Vec<_> = self
|
||||
.state
|
||||
.snippets
|
||||
.read()
|
||||
.into_iter()
|
||||
.filter(|s| {
|
||||
s.name.to_lowercase().contains(&q)
|
||||
|| s.description.to_lowercase().contains(&q)
|
||||
})
|
||||
.collect();
|
||||
let adrs: Vec<_> = self
|
||||
.state
|
||||
.adrs
|
||||
.read()
|
||||
.into_iter()
|
||||
.filter(|a| {
|
||||
a.title.to_lowercase().contains(&q)
|
||||
|| a.context.to_lowercase().contains(&q)
|
||||
|| a.decision.to_lowercase().contains(&q)
|
||||
})
|
||||
.collect();
|
||||
let tech_debts: Vec<_> = self
|
||||
.state
|
||||
.tech_debts
|
||||
|
||||
Reference in new issue
Block a user