chore: fix formatting and clippy lints
This commit is contained in:
1 parent
8952bd5399
commit
9d9e959744
35 files changed
+1091
-582
No files matched your search
+153
-69
@@ -62,8 +62,8 @@ impl<'a> GraphQueryBuilder<'a> {
|
||||
break;
|
||||
}
|
||||
nodes_at_current_depth -= 1;
|
||||
if current_depth < self.max_depth {
|
||||
if let Some(neighbors) = adj.get(current) {
|
||||
if current_depth < self.max_depth
|
||||
&& let Some(neighbors) = adj.get(current) {
|
||||
for &(neighbor, rel_type, is_inverse) in neighbors {
|
||||
if !visited.contains(neighbor) {
|
||||
visited.insert(neighbor);
|
||||
@@ -73,7 +73,6 @@ impl<'a> GraphQueryBuilder<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if nodes_at_current_depth == 0 {
|
||||
current_depth += 1;
|
||||
nodes_at_current_depth = nodes_at_next_depth;
|
||||
@@ -138,7 +137,9 @@ impl McpTool for QueryGraphPathHandler {
|
||||
})
|
||||
})
|
||||
.await
|
||||
.map_err(|e| crate::error::AppError::Internal(format!("Graph traversal task failed: {}", e)))?
|
||||
.map_err(|e| {
|
||||
crate::error::AppError::Internal(format!("Graph traversal task failed: {}", e))
|
||||
})?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,12 +170,19 @@ impl McpTool for CreateEntitiesHandler {
|
||||
}
|
||||
}
|
||||
});
|
||||
let names: Vec<String> = inserted.iter().map(|e| format!("{} ({})", e.name, e.entity_type)).collect();
|
||||
let names: Vec<String> = inserted
|
||||
.iter()
|
||||
.map(|e| format!("{} ({})", e.name, e.entity_type))
|
||||
.collect();
|
||||
if !inserted.is_empty() {
|
||||
let idx = state.get_search_index().await;
|
||||
let _ = idx.index_entities_batch(&inserted).await;
|
||||
}
|
||||
Ok(format!("Successfully created {} entity/entities: {}", names.len(), names.join(", ")))
|
||||
Ok(format!(
|
||||
"Successfully created {} entity/entities: {}",
|
||||
names.len(),
|
||||
names.join(", ")
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +244,9 @@ impl McpTool for CreateRelationsHandler {
|
||||
crate::models::Entity {
|
||||
name: node_name.clone(),
|
||||
entity_type: "Entity".to_string(),
|
||||
observations: vec!["Auto-created stub entity for relation endpoint".to_string()],
|
||||
observations: vec![
|
||||
"Auto-created stub entity for relation endpoint".to_string(),
|
||||
],
|
||||
namespace: crate::models::default_namespace(),
|
||||
git_branch: None,
|
||||
..Default::default()
|
||||
@@ -247,16 +257,28 @@ impl McpTool for CreateRelationsHandler {
|
||||
}
|
||||
for mut relation in req.relations {
|
||||
if !relation.from.is_empty() && !relation.to.is_empty() {
|
||||
relation.relation_type = crate::models::normalize_relation_type(&relation.relation_type);
|
||||
added_relations.push(format!("{} -[{}]-> {}", relation.from, relation.relation_type, relation.to));
|
||||
relation.relation_type =
|
||||
crate::models::normalize_relation_type(&relation.relation_type);
|
||||
added_relations.push(format!(
|
||||
"{} -[{}]-> {}",
|
||||
relation.from, relation.relation_type, relation.to
|
||||
));
|
||||
g.relations.push(relation);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut msg = format!("Successfully created {} relation(s):\n{}", added_relations.len(), added_relations.join("\n"));
|
||||
let mut msg = format!(
|
||||
"Successfully created {} relation(s):\n{}",
|
||||
added_relations.len(),
|
||||
added_relations.join("\n")
|
||||
);
|
||||
if !auto_created.is_empty() {
|
||||
msg.push_str(&format!("\nNote: Auto-created {} missing stub entity/entities: {}", auto_created.len(), auto_created.join(", ")));
|
||||
msg.push_str(&format!(
|
||||
"\nNote: Auto-created {} missing stub entity/entities: {}",
|
||||
auto_created.len(),
|
||||
auto_created.join(", ")
|
||||
));
|
||||
}
|
||||
Ok(msg)
|
||||
}
|
||||
@@ -462,7 +484,7 @@ impl McpTool for ReadGraphHandler {
|
||||
let filtered_entities: Vec<(&String, &crate::models::Entity)> = full
|
||||
.entities
|
||||
.iter()
|
||||
.filter(|(_, v)| req.namespace.as_ref().map_or(true, |ns| &v.namespace == ns))
|
||||
.filter(|(_, v)| req.namespace.as_ref().is_none_or(|ns| &v.namespace == ns))
|
||||
.collect();
|
||||
|
||||
let total_count = filtered_entities.len();
|
||||
@@ -481,7 +503,7 @@ impl McpTool for ReadGraphHandler {
|
||||
.relations
|
||||
.iter()
|
||||
.filter(|r| {
|
||||
let ns_match = req.namespace.as_ref().map_or(true, |ns| &r.namespace == ns);
|
||||
let ns_match = req.namespace.as_ref().is_none_or(|ns| &r.namespace == ns);
|
||||
ns_match && (paged_entities.contains_key(&r.from) || paged_entities.contains_key(&r.to))
|
||||
})
|
||||
.collect();
|
||||
@@ -499,7 +521,7 @@ impl McpTool for ReadGraphHandler {
|
||||
let rel_vec: Vec<&crate::models::Relation> = full
|
||||
.relations
|
||||
.iter()
|
||||
.filter(|r| req.namespace.as_ref().map_or(true, |ns| &r.namespace == ns))
|
||||
.filter(|r| req.namespace.as_ref().is_none_or(|ns| &r.namespace == ns))
|
||||
.collect();
|
||||
(ent_map, rel_vec, None)
|
||||
};
|
||||
@@ -549,21 +571,19 @@ impl McpTool for ReadGraphHandler {
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(meta) = &meta_json {
|
||||
if let Some(obj) = truncated_val.as_object_mut() {
|
||||
if let Some(meta) = &meta_json
|
||||
&& let Some(obj) = truncated_val.as_object_mut() {
|
||||
obj.insert("total_count".to_string(), meta["total_count"].clone());
|
||||
obj.insert("offset".to_string(), meta["offset"].clone());
|
||||
obj.insert("limit".to_string(), meta["limit"].clone());
|
||||
obj.insert("has_more".to_string(), serde_json::Value::Bool(true));
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(trunc_str) = serde_json::to_string(&truncated_val) {
|
||||
if trunc_str.len() <= max_chars || keep_count == 1 {
|
||||
if let Ok(trunc_str) = serde_json::to_string(&truncated_val)
|
||||
&& (trunc_str.len() <= max_chars || keep_count == 1) {
|
||||
result_json = trunc_str;
|
||||
break;
|
||||
}
|
||||
}
|
||||
keep_count = keep_count.saturating_sub(keep_count / 3 + 1);
|
||||
}
|
||||
}
|
||||
@@ -820,7 +840,10 @@ impl McpTool for CondenseEntityHandler {
|
||||
e.observations = unique_obs;
|
||||
}
|
||||
});
|
||||
return Ok(format!("Entity '{}' observations condensed with deduplication/AI summary.", req.entity_name));
|
||||
return Ok(format!(
|
||||
"Entity '{}' observations condensed with deduplication/AI summary.",
|
||||
req.entity_name
|
||||
));
|
||||
}
|
||||
|
||||
state.modify_graph(|master| {
|
||||
@@ -953,10 +976,9 @@ impl McpTool for GetSubgraphHandler {
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: GetSubgraphTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let root = req
|
||||
.root_entity
|
||||
.or(req.root_node)
|
||||
.ok_or_else(|| crate::error::AppError::Internal("root_entity or root_node is required".to_string()))?;
|
||||
let root = req.root_entity.or(req.root_node).ok_or_else(|| {
|
||||
crate::error::AppError::Internal("root_entity or root_node is required".to_string())
|
||||
})?;
|
||||
let depth = req.depth.unwrap_or(2);
|
||||
let format = req.format.unwrap_or(SubgraphFormat::Json);
|
||||
|
||||
@@ -974,15 +996,14 @@ impl McpTool for GetSubgraphHandler {
|
||||
visited.insert(root.clone());
|
||||
|
||||
while let Some((curr, d)) = queue.pop_front() {
|
||||
if d < depth {
|
||||
if let Some(neighbors) = adj.get(curr) {
|
||||
if d < depth
|
||||
&& let Some(neighbors) = adj.get(curr) {
|
||||
for &next in neighbors {
|
||||
if visited.insert(next.to_string()) {
|
||||
queue.push_back((next, d + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let ent: std::collections::HashMap<String, crate::models::Entity> = visited
|
||||
@@ -1011,7 +1032,10 @@ impl McpTool for GetSubgraphHandler {
|
||||
|
||||
markdown.push_str("\n## Relations\n");
|
||||
for r in &matched_relations {
|
||||
markdown.push_str(&format!("- `{}` --[{}]--> `{}`\n", r.from, r.relation_type, r.to));
|
||||
markdown.push_str(&format!(
|
||||
"- `{}` --[{}]--> `{}`\n",
|
||||
r.from, r.relation_type, r.to
|
||||
));
|
||||
}
|
||||
return Ok(markdown);
|
||||
}
|
||||
@@ -1038,7 +1062,10 @@ impl McpTool for SweepGraphHealthHandler {
|
||||
}
|
||||
|
||||
fn schema(&self) -> Value {
|
||||
crate::mcp::tool_def::<SweepGraphHealthTool>("sweep_graph_health", "Audit and sweep graph health")
|
||||
crate::mcp::tool_def::<SweepGraphHealthTool>(
|
||||
"sweep_graph_health",
|
||||
"Audit and sweep graph health",
|
||||
)
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
@@ -1132,26 +1159,31 @@ impl McpTool for ResolveStaleSymbolsHandler {
|
||||
}
|
||||
|
||||
fn schema(&self) -> Value {
|
||||
crate::mcp::tool_def::<ResolveStaleSymbolsTool>("resolve_stale_symbols", "Inspect Knowledge Graph entities and tech debt symbol/line references against files on disk, healing stale pointers.")
|
||||
crate::mcp::tool_def::<ResolveStaleSymbolsTool>(
|
||||
"resolve_stale_symbols",
|
||||
"Inspect Knowledge Graph entities and tech debt symbol/line references against files on disk, healing stale pointers.",
|
||||
)
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: ResolveStaleSymbolsTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let req: ResolveStaleSymbolsTool =
|
||||
serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let auto_heal = req.auto_heal.unwrap_or(true);
|
||||
|
||||
let mut checked = 0;
|
||||
let mut stale_entities = Vec::new();
|
||||
|
||||
state.modify_graph(|g| {
|
||||
for (name, _entity) in g.entities.iter_mut() {
|
||||
if let Some(target) = &req.target {
|
||||
if name != target && !name.contains(target) {
|
||||
for name in g.entities.keys() {
|
||||
if let Some(target) = &req.target
|
||||
&& name != target && !name.contains(target) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
checked += 1;
|
||||
let path = std::path::Path::new(name);
|
||||
if (name.contains('/') || name.contains('\\') || name.contains('.')) && !path.exists() {
|
||||
if (name.contains('/') || name.contains('\\') || name.contains('.'))
|
||||
&& !path.exists()
|
||||
{
|
||||
stale_entities.push(name.clone());
|
||||
}
|
||||
}
|
||||
@@ -1184,7 +1216,10 @@ impl McpTool for SummarizeSubgraphHandler {
|
||||
}
|
||||
|
||||
fn schema(&self) -> Value {
|
||||
crate::mcp::tool_def::<SummarizeSubgraphTool>("summarize_subgraph", "Generate compact, LLM-optimized Markdown topology of a graph component capped within a token budget.")
|
||||
crate::mcp::tool_def::<SummarizeSubgraphTool>(
|
||||
"summarize_subgraph",
|
||||
"Generate compact, LLM-optimized Markdown topology of a graph component capped within a token budget.",
|
||||
)
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
@@ -1212,8 +1247,18 @@ impl McpTool for SummarizeSubgraphHandler {
|
||||
}
|
||||
}
|
||||
|
||||
let ent: Vec<_> = g.entities.values().filter(|e| visited.contains(&e.name)).cloned().collect();
|
||||
let rel: Vec<_> = g.relations.iter().filter(|r| visited.contains(&r.from) && visited.contains(&r.to)).cloned().collect();
|
||||
let ent: Vec<_> = g
|
||||
.entities
|
||||
.values()
|
||||
.filter(|e| visited.contains(&e.name))
|
||||
.cloned()
|
||||
.collect();
|
||||
let rel: Vec<_> = g
|
||||
.relations
|
||||
.iter()
|
||||
.filter(|r| visited.contains(&r.from) && visited.contains(&r.to))
|
||||
.cloned()
|
||||
.collect();
|
||||
(ent, rel)
|
||||
});
|
||||
|
||||
@@ -1228,7 +1273,10 @@ impl McpTool for SummarizeSubgraphHandler {
|
||||
|
||||
markdown.push_str("\n## Relations\n");
|
||||
for r in &sub_relations {
|
||||
markdown.push_str(&format!("- `{}` --[{}]--> `{}`\n", r.from, r.relation_type, r.to));
|
||||
markdown.push_str(&format!(
|
||||
"- `{}` --[{}]--> `{}`\n",
|
||||
r.from, r.relation_type, r.to
|
||||
));
|
||||
}
|
||||
|
||||
let max_tokens = req.max_tokens.unwrap_or(1000);
|
||||
@@ -1249,7 +1297,6 @@ mod tests {
|
||||
use crate::handlers::meta::AgentSignalsHandler;
|
||||
use serde_json::json;
|
||||
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_and_read_entities() {
|
||||
let state = Arc::new(MemoryState::new_in_memory());
|
||||
@@ -1324,10 +1371,7 @@ mod tests {
|
||||
{"source": "A", "target": "B", "relationType": "knows"}
|
||||
]
|
||||
});
|
||||
let alias_res = handler
|
||||
.execute(alias_args, state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
let alias_res = handler.execute(alias_args, state.clone()).await.unwrap();
|
||||
assert!(alias_res.contains("Successfully created 1 relation(s)"));
|
||||
|
||||
// Test semantic LLM schema feedback on missing fields
|
||||
@@ -1499,7 +1543,10 @@ mod tests {
|
||||
{"name": "Beta", "entity_type": "Node", "observations": ["Obs3"], "namespace": "global"}
|
||||
]
|
||||
});
|
||||
create_handler.execute(args_ent, state.clone()).await.unwrap();
|
||||
create_handler
|
||||
.execute(args_ent, state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let rel_handler = CreateRelationsHandler;
|
||||
let args_rel = json!({
|
||||
@@ -1510,48 +1557,86 @@ mod tests {
|
||||
rel_handler.execute(args_rel, state.clone()).await.unwrap();
|
||||
|
||||
let path_handler = QueryGraphPathHandler;
|
||||
let path_res = path_handler.execute(json!({"start_node": "Alpha", "end_node": "Beta"}), state.clone()).await.unwrap();
|
||||
let path_res = path_handler
|
||||
.execute(
|
||||
json!({"start_node": "Alpha", "end_node": "Beta"}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(path_res.contains("Alpha"));
|
||||
|
||||
let sub_handler = GetSubgraphHandler;
|
||||
let sub_res = sub_handler.execute(json!({"root_entity": "Alpha"}), state.clone()).await.unwrap();
|
||||
let sub_res = sub_handler
|
||||
.execute(json!({"root_entity": "Alpha"}), state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(sub_res.contains("Alpha"));
|
||||
|
||||
let sum_handler = SummarizeSubgraphHandler;
|
||||
let sum_res = sum_handler.execute(json!({"root_entity": "Alpha"}), state.clone()).await.unwrap();
|
||||
let sum_res = sum_handler
|
||||
.execute(json!({"root_entity": "Alpha"}), state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(!sum_res.is_empty());
|
||||
|
||||
|
||||
let sweep_handler = SweepGraphHealthHandler;
|
||||
let sweep_res = sweep_handler.execute(json!({}), state.clone()).await.unwrap();
|
||||
let sweep_res = sweep_handler
|
||||
.execute(json!({}), state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(!sweep_res.is_empty());
|
||||
|
||||
let del_obs_handler = DeleteObservationsHandler;
|
||||
let del_obs_res = del_obs_handler.execute(json!({
|
||||
"deletions": [{"entity_name": "Alpha", "observations": ["Obs1"]}]
|
||||
}), state.clone()).await.unwrap();
|
||||
let del_obs_res = del_obs_handler
|
||||
.execute(
|
||||
json!({
|
||||
"deletions": [{"entity_name": "Alpha", "observations": ["Obs1"]}]
|
||||
}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(del_obs_res, "Observations deleted");
|
||||
|
||||
let del_rel_handler = DeleteRelationsHandler;
|
||||
let del_rel_res = del_rel_handler.execute(json!({
|
||||
"relations": [{"from": "Alpha", "to": "Beta", "relation_type": "links_to"}]
|
||||
}), state.clone()).await.unwrap();
|
||||
let del_rel_res = del_rel_handler
|
||||
.execute(
|
||||
json!({
|
||||
"relations": [{"from": "Alpha", "to": "Beta", "relation_type": "links_to"}]
|
||||
}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(del_rel_res, "Relations deleted");
|
||||
|
||||
let bcast_handler = AgentSignalsHandler;
|
||||
let bcast_res = bcast_handler.execute(json!({
|
||||
"action": "broadcast",
|
||||
"sender": "agent1",
|
||||
"signal_type": "task_completed",
|
||||
"payload": "fix_bug"
|
||||
}), state.clone()).await.unwrap();
|
||||
let bcast_res = bcast_handler
|
||||
.execute(
|
||||
json!({
|
||||
"action": "broadcast",
|
||||
"sender": "agent1",
|
||||
"signal_type": "task_completed",
|
||||
"payload": "fix_bug"
|
||||
}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(bcast_res.contains("Broadcasted signal"));
|
||||
|
||||
let qsignal_handler = AgentSignalsHandler;
|
||||
let qsignal_res = qsignal_handler.execute(json!({
|
||||
"action": "query",
|
||||
"sender": "agent1"
|
||||
}), state.clone()).await.unwrap();
|
||||
let qsignal_res = qsignal_handler
|
||||
.execute(
|
||||
json!({
|
||||
"action": "query",
|
||||
"sender": "agent1"
|
||||
}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(qsignal_res.contains("task_completed"));
|
||||
let read_paged_handler = ReadGraphHandler;
|
||||
let paged_res = read_paged_handler
|
||||
@@ -1563,4 +1648,3 @@ mod tests {
|
||||
assert_eq!(parsed_paged["has_more"], true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user