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
+134
-103
@@ -110,11 +110,10 @@ impl McpTool for SearchErrorFixesHandler {
|
||||
} else if st_lower.contains(&sol_lower) || sol_lower.contains(&st_lower) {
|
||||
score += 0.5;
|
||||
}
|
||||
if let Some(emb) = &f.embedding {
|
||||
if !query_emb.is_empty() {
|
||||
if let Some(emb) = &f.embedding
|
||||
&& !query_emb.is_empty() {
|
||||
score += crate::embedding::cosine_similarity(&query_emb, emb);
|
||||
}
|
||||
}
|
||||
(f, score)
|
||||
})
|
||||
.filter(|(_, score)| *score > 0.1)
|
||||
@@ -198,11 +197,10 @@ impl McpTool for LogCodeChangeHandler {
|
||||
if let Some(range) = &req.line_range {
|
||||
description = format!("{} [Line Range: {}]", description, range);
|
||||
}
|
||||
if let Some(symbols) = &req.symbol_references {
|
||||
if !symbols.is_empty() {
|
||||
if let Some(symbols) = &req.symbol_references
|
||||
&& !symbols.is_empty() {
|
||||
description = format!("{} [Symbols: {}]", description, symbols.join(", "));
|
||||
}
|
||||
}
|
||||
|
||||
if state.ollama.is_available().await {
|
||||
let prompt = format!(
|
||||
@@ -323,13 +321,14 @@ impl McpTool for QueryRecentChangesHandler {
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: QueryRecentChangesTool = serde_json::from_value(args).unwrap_or(QueryRecentChangesTool {
|
||||
namespace: None,
|
||||
repo_name: None,
|
||||
vcs_type: None,
|
||||
limit: None,
|
||||
offset: None,
|
||||
});
|
||||
let req: QueryRecentChangesTool =
|
||||
serde_json::from_value(args).unwrap_or(QueryRecentChangesTool {
|
||||
namespace: None,
|
||||
repo_name: None,
|
||||
vcs_type: None,
|
||||
limit: None,
|
||||
offset: None,
|
||||
});
|
||||
let limit = req.limit.unwrap_or(50);
|
||||
let offset = req.offset.unwrap_or(0);
|
||||
let data = state.code.ledger.read_with(|l| {
|
||||
@@ -337,25 +336,22 @@ impl McpTool for QueryRecentChangesHandler {
|
||||
.iter()
|
||||
.rev()
|
||||
.filter(|c| {
|
||||
if let Some(ns) = &req.namespace {
|
||||
if !c.namespace.eq_ignore_ascii_case(ns) {
|
||||
if let Some(ns) = &req.namespace
|
||||
&& !c.namespace.eq_ignore_ascii_case(ns) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if let Some(repo) = &req.repo_name {
|
||||
if c.repo_name
|
||||
if let Some(repo) = &req.repo_name
|
||||
&& c.repo_name
|
||||
.as_ref()
|
||||
.map(|rn| !rn.eq_ignore_ascii_case(repo))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if let Some(vcs) = &req.vcs_type {
|
||||
if !c.effective_vcs().eq_ignore_ascii_case(vcs) {
|
||||
if let Some(vcs) = &req.vcs_type
|
||||
&& !c.effective_vcs().eq_ignore_ascii_case(vcs) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
})
|
||||
.skip(offset)
|
||||
@@ -386,7 +382,7 @@ impl McpTool for DecisionsHandler {
|
||||
let req: DecisionsTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let ns = req
|
||||
.namespace
|
||||
.unwrap_or_else(|| crate::models::default_namespace());
|
||||
.unwrap_or_else(crate::models::default_namespace);
|
||||
match req.action {
|
||||
DecisionAction::Log => {
|
||||
let title = req.title.ok_or_else(|| {
|
||||
@@ -464,14 +460,14 @@ impl McpTool for DecisionsHandler {
|
||||
state.code.adrs.modify(|adrs| {
|
||||
let target_pos = adrs.iter().position(|a| a.id.eq_ignore_ascii_case(&id));
|
||||
if let Some(pos) = target_pos {
|
||||
if let Some(superseded_id) = &req.supersedes {
|
||||
if let Some(s_pos) = adrs.iter().position(|a| a.id.eq_ignore_ascii_case(superseded_id)) {
|
||||
if s_pos != pos {
|
||||
if let Some(superseded_id) = &req.supersedes
|
||||
&& let Some(s_pos) = adrs
|
||||
.iter()
|
||||
.position(|a| a.id.eq_ignore_ascii_case(superseded_id))
|
||||
&& s_pos != pos {
|
||||
adrs[s_pos].status = "superseded".to_string();
|
||||
adrs_to_index.push(adrs[s_pos].clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let a = &mut adrs[pos];
|
||||
if let Some(t) = req.title {
|
||||
@@ -488,7 +484,9 @@ impl McpTool for DecisionsHandler {
|
||||
}
|
||||
if let Some(s) = req.status {
|
||||
let s_lower = s.to_ascii_lowercase();
|
||||
if (s_lower == "implemented" || s_lower == "resolved") && a.resolved_at.is_none() {
|
||||
if (s_lower == "implemented" || s_lower == "resolved")
|
||||
&& a.resolved_at.is_none()
|
||||
{
|
||||
a.resolved_at = Some(crate::handlers::utils::now_secs());
|
||||
} else if s_lower != "implemented" && s_lower != "resolved" {
|
||||
a.resolved_at = None;
|
||||
@@ -535,11 +533,15 @@ impl McpTool for DecisionsHandler {
|
||||
&format!("Updated {}: {}", adr.id, adr.title),
|
||||
Some(&adr.status),
|
||||
);
|
||||
Ok(format!("Updated decision {}: {} (status: {})", adr.id, adr.title, adr.status))
|
||||
} else {
|
||||
Err(crate::error::AppError::Internal(
|
||||
format!("Decision with id '{}' not found", id),
|
||||
Ok(format!(
|
||||
"Updated decision {}: {} (status: {})",
|
||||
adr.id, adr.title, adr.status
|
||||
))
|
||||
} else {
|
||||
Err(crate::error::AppError::Internal(format!(
|
||||
"Decision with id '{}' not found",
|
||||
id
|
||||
)))
|
||||
}
|
||||
}
|
||||
DecisionAction::Query => {
|
||||
@@ -554,9 +556,17 @@ impl McpTool for DecisionsHandler {
|
||||
}
|
||||
if let Some(q) = &req.query {
|
||||
crate::handlers::utils::contains_ignore_ascii_case(&a.title, q)
|
||||
|| crate::handlers::utils::contains_ignore_ascii_case(&a.context, q)
|
||||
|| crate::handlers::utils::contains_ignore_ascii_case(&a.decision, q)
|
||||
|| crate::handlers::utils::contains_ignore_ascii_case(&a.consequence, q)
|
||||
|| crate::handlers::utils::contains_ignore_ascii_case(
|
||||
&a.context, q,
|
||||
)
|
||||
|| crate::handlers::utils::contains_ignore_ascii_case(
|
||||
&a.decision,
|
||||
q,
|
||||
)
|
||||
|| crate::handlers::utils::contains_ignore_ascii_case(
|
||||
&a.consequence,
|
||||
q,
|
||||
)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
@@ -632,17 +642,14 @@ impl McpTool for TechDebtHandler {
|
||||
let req: TechDebtTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let ns = req
|
||||
.namespace
|
||||
.unwrap_or_else(|| crate::models::default_namespace());
|
||||
.unwrap_or_else(crate::models::default_namespace);
|
||||
match req.action {
|
||||
TechDebtAction::Log => {
|
||||
let desc = req.description.or(req.title).ok_or_else(|| {
|
||||
crate::error::AppError::Internal("Missing required parameter 'description' for action 'log'. Next step: Provide tech debt 'description' in request and retry.".to_string())
|
||||
})?;
|
||||
let ideal = req.ideal_solution.unwrap_or_default();
|
||||
let text_to_embed = format!(
|
||||
"Description: {}\nIdeal Solution: {}",
|
||||
desc, ideal
|
||||
);
|
||||
let text_to_embed = format!("Description: {}\nIdeal Solution: {}", desc, ideal);
|
||||
let embedding = crate::embedding::generate_embedding_async(text_to_embed)
|
||||
.await
|
||||
.ok();
|
||||
@@ -665,18 +672,21 @@ impl McpTool for TechDebtHandler {
|
||||
effort_estimate: req.effort_estimate,
|
||||
});
|
||||
if debts.len() > 300 {
|
||||
let severity_rank = |sev: Option<&str>| match sev.unwrap_or("").to_lowercase().as_str() {
|
||||
"critical" => 4,
|
||||
"high" => 3,
|
||||
"medium" => 2,
|
||||
"low" => 1,
|
||||
_ => 1,
|
||||
};
|
||||
if let Some((idx_to_remove, _)) = debts.iter().enumerate().min_by_key(|(_, d)| {
|
||||
let status_score = if d.is_resolved { 0 } else { 10 };
|
||||
let sev_score = severity_rank(d.severity.as_deref());
|
||||
(status_score + sev_score, d.created_at)
|
||||
}) {
|
||||
let severity_rank =
|
||||
|sev: Option<&str>| match sev.unwrap_or("").to_lowercase().as_str() {
|
||||
"critical" => 4,
|
||||
"high" => 3,
|
||||
"medium" => 2,
|
||||
"low" => 1,
|
||||
_ => 1,
|
||||
};
|
||||
if let Some((idx_to_remove, _)) =
|
||||
debts.iter().enumerate().min_by_key(|(_, d)| {
|
||||
let status_score = if d.is_resolved { 0 } else { 10 };
|
||||
let sev_score = severity_rank(d.severity.as_deref());
|
||||
(status_score + sev_score, d.created_at)
|
||||
})
|
||||
{
|
||||
debts.remove(idx_to_remove);
|
||||
}
|
||||
}
|
||||
@@ -712,9 +722,7 @@ impl McpTool for TechDebtHandler {
|
||||
let data = state.code.tech_debts.read_with(|debts| {
|
||||
let filtered: Vec<_> = debts
|
||||
.iter()
|
||||
.filter(|d| {
|
||||
d.namespace == ns && (inc || !d.is_resolved)
|
||||
})
|
||||
.filter(|d| d.namespace == ns && (inc || !d.is_resolved))
|
||||
.map(|d| match level {
|
||||
"compact" => serde_json::json!({
|
||||
"id": d.id,
|
||||
@@ -811,7 +819,8 @@ impl McpTool for OmniSearchHandler {
|
||||
let mut ranked_items: Vec<_> = rrf_scores.into_values().collect();
|
||||
ranked_items.sort_by(|a, b| b.0.total_cmp(&a.0));
|
||||
|
||||
let matches: Vec<crate::search::SearchResult> = ranked_items.into_iter().map(|(_, item)| item).collect();
|
||||
let matches: Vec<crate::search::SearchResult> =
|
||||
ranked_items.into_iter().map(|(_, item)| item).collect();
|
||||
|
||||
let kg_json = state.read_graph(|full| {
|
||||
let mut kg_results = serde_json::Map::new();
|
||||
@@ -1263,25 +1272,21 @@ impl McpTool for ManageCheckpointHandler {
|
||||
)));
|
||||
}
|
||||
|
||||
if let Ok(graph_content) = std::fs::read_to_string(target_dir.join("graph.json")) {
|
||||
if let Ok(graph) = serde_json::from_str(&graph_content) {
|
||||
if let Ok(graph_content) = std::fs::read_to_string(target_dir.join("graph.json"))
|
||||
&& let Ok(graph) = serde_json::from_str(&graph_content) {
|
||||
state.graph.modify(|g| *g = graph);
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(tasks_content) = std::fs::read_to_string(target_dir.join("tasks.json")) {
|
||||
if let Ok(tasks) = serde_json::from_str(&tasks_content) {
|
||||
if let Ok(tasks_content) = std::fs::read_to_string(target_dir.join("tasks.json"))
|
||||
&& let Ok(tasks) = serde_json::from_str(&tasks_content) {
|
||||
state.project.tasks.modify(|t| *t = tasks);
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(debts_content) =
|
||||
std::fs::read_to_string(target_dir.join("tech_debts.json"))
|
||||
{
|
||||
if let Ok(debts) = serde_json::from_str(&debts_content) {
|
||||
&& let Ok(debts) = serde_json::from_str(&debts_content) {
|
||||
state.code.tech_debts.modify(|d| *d = debts);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(format!("Checkpoint '{}' restored successfully.", name))
|
||||
}
|
||||
@@ -1290,11 +1295,10 @@ impl McpTool for ManageCheckpointHandler {
|
||||
let checkpoints_dir = state.base_dir.join("checkpoints");
|
||||
if let Ok(entries) = std::fs::read_dir(&checkpoints_dir) {
|
||||
for entry in entries.flatten() {
|
||||
if entry.path().is_dir() {
|
||||
if let Some(n) = entry.file_name().to_str() {
|
||||
if entry.path().is_dir()
|
||||
&& let Some(n) = entry.file_name().to_str() {
|
||||
list.push(serde_json::json!({"type": "checkpoint", "name": n}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let snaps = state.project.snapshots.read_with(|snaps| snaps.clone());
|
||||
@@ -1461,13 +1465,11 @@ impl McpTool for GetNextActionableTasksHandler {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(branch) = &req.git_branch {
|
||||
if let Some(tb) = &task.git_branch {
|
||||
if tb != branch {
|
||||
if let Some(branch) = &req.git_branch
|
||||
&& let Some(tb) = &task.git_branch
|
||||
&& tb != branch {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let unblocked = task.dependencies.is_empty()
|
||||
|| task.dependencies.iter().all(|d| completed_ids.contains(d));
|
||||
@@ -1509,7 +1511,9 @@ impl McpTool for HypothesesHandler {
|
||||
match req.action {
|
||||
HypothesisAction::Log => {
|
||||
let hyp_text = req.hypothesis.ok_or_else(|| {
|
||||
crate::error::AppError::Internal("Missing required 'hypothesis' for action 'log'".to_string())
|
||||
crate::error::AppError::Internal(
|
||||
"Missing required 'hypothesis' for action 'log'".to_string(),
|
||||
)
|
||||
})?;
|
||||
let hyp_id = format!(
|
||||
"HYP-{}",
|
||||
@@ -1536,17 +1540,16 @@ impl McpTool for HypothesesHandler {
|
||||
let filtered: Vec<_> = hypotheses
|
||||
.into_iter()
|
||||
.filter(|h| {
|
||||
if let Some(tid) = &req.task_id {
|
||||
if h.task_id.as_ref() != Some(tid) {
|
||||
if let Some(tid) = &req.task_id
|
||||
&& h.task_id.as_ref() != Some(tid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if let Some(q) = &req.query {
|
||||
let lq = q.to_lowercase();
|
||||
return h.hypothesis.to_lowercase().contains(&lq)
|
||||
|| h.evidence
|
||||
.as_ref()
|
||||
.map_or(false, |e| e.to_lowercase().contains(&lq));
|
||||
.is_some_and(|e| e.to_lowercase().contains(&lq));
|
||||
}
|
||||
true
|
||||
})
|
||||
@@ -1656,13 +1659,19 @@ impl McpTool for AgentSignalsHandler {
|
||||
match req.action {
|
||||
AgentSignalAction::Broadcast => {
|
||||
let sender = req.sender.ok_or_else(|| {
|
||||
crate::error::AppError::Internal("Missing required 'sender' for action 'broadcast'".to_string())
|
||||
crate::error::AppError::Internal(
|
||||
"Missing required 'sender' for action 'broadcast'".to_string(),
|
||||
)
|
||||
})?;
|
||||
let signal_type = req.signal_type.ok_or_else(|| {
|
||||
crate::error::AppError::Internal("Missing required 'signal_type' for action 'broadcast'".to_string())
|
||||
crate::error::AppError::Internal(
|
||||
"Missing required 'signal_type' for action 'broadcast'".to_string(),
|
||||
)
|
||||
})?;
|
||||
let payload = req.payload.ok_or_else(|| {
|
||||
crate::error::AppError::Internal("Missing required 'payload' for action 'broadcast'".to_string())
|
||||
crate::error::AppError::Internal(
|
||||
"Missing required 'payload' for action 'broadcast'".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let timestamp = std::time::SystemTime::now()
|
||||
@@ -1715,25 +1724,21 @@ impl McpTool for AgentSignalsHandler {
|
||||
signals
|
||||
.iter()
|
||||
.filter(|s| {
|
||||
if let Some(ttl) = s.ttl_seconds {
|
||||
if now > s.timestamp + ttl {
|
||||
if let Some(ttl) = s.ttl_seconds
|
||||
&& now > s.timestamp + ttl {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if let Some(sender) = &req.sender {
|
||||
if s.sender.to_lowercase() != sender.to_lowercase() {
|
||||
if let Some(sender) = &req.sender
|
||||
&& s.sender.to_lowercase() != sender.to_lowercase() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if let Some(st) = &req.signal_type {
|
||||
if s.signal_type.to_lowercase() != st.to_lowercase() {
|
||||
if let Some(st) = &req.signal_type
|
||||
&& s.signal_type.to_lowercase() != st.to_lowercase() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
})
|
||||
.cloned()
|
||||
.take(req.limit.unwrap_or(20))
|
||||
.take(req.limit.unwrap_or(20)).cloned()
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
@@ -2110,7 +2115,10 @@ mod tests {
|
||||
assert!(q_dec_res.contains("Fast async API routing"));
|
||||
|
||||
let q_by_consequence = handler_dec
|
||||
.execute(serde_json::json!({"action": "query", "query": "Fast async"}), state.clone())
|
||||
.execute(
|
||||
serde_json::json!({"action": "query", "query": "Fast async"}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(q_by_consequence.contains("Use Axum"));
|
||||
@@ -2133,7 +2141,10 @@ mod tests {
|
||||
assert!(update_res.contains("implemented"));
|
||||
|
||||
let q_after_update = handler_dec
|
||||
.execute(serde_json::json!({"action": "query", "include_body": false}), state.clone())
|
||||
.execute(
|
||||
serde_json::json!({"action": "query", "include_body": false}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(q_after_update.contains("implemented"));
|
||||
@@ -2143,7 +2154,10 @@ mod tests {
|
||||
assert!(q_after_update.contains("resolved_at"));
|
||||
|
||||
let del_dec_res = handler_dec
|
||||
.execute(serde_json::json!({"action": "delete", "id": "ADR-0001"}), state.clone())
|
||||
.execute(
|
||||
serde_json::json!({"action": "delete", "id": "ADR-0001"}),
|
||||
state.clone(),
|
||||
)
|
||||
.await;
|
||||
assert!(del_dec_res.is_ok());
|
||||
|
||||
@@ -2163,14 +2177,20 @@ mod tests {
|
||||
assert!(td_res.contains("Tech debt logged"));
|
||||
|
||||
let list_td_res = handler_td
|
||||
.execute(serde_json::json!({"action": "list", "include_resolved": true}), state.clone())
|
||||
.execute(
|
||||
serde_json::json!({"action": "list", "include_resolved": true}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(list_td_res.contains("Replace unwraps"));
|
||||
|
||||
let debt_id = state.code.tech_debts.read_with(|debts| debts[0].id.clone());
|
||||
let res_td_res = handler_td
|
||||
.execute(serde_json::json!({"action": "resolve", "id": debt_id}), state.clone())
|
||||
.execute(
|
||||
serde_json::json!({"action": "resolve", "id": debt_id}),
|
||||
state.clone(),
|
||||
)
|
||||
.await;
|
||||
assert!(res_td_res.is_ok());
|
||||
|
||||
@@ -2394,7 +2414,10 @@ mod tests {
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(rest_state_res.contains("restored successfully") || rest_state_res.contains("restored memory state from snapshot"));
|
||||
assert!(
|
||||
rest_state_res.contains("restored successfully")
|
||||
|| rest_state_res.contains("restored memory state from snapshot")
|
||||
);
|
||||
|
||||
let mg_list = mg_chk
|
||||
.execute(serde_json::json!({"action": "list"}), state.clone())
|
||||
@@ -2607,7 +2630,10 @@ mod tests {
|
||||
|
||||
// DeleteDecision non-existent
|
||||
let del_dec_err = handler_dec
|
||||
.execute(serde_json::json!({"action": "delete", "id": "ADR-9999"}), state.clone())
|
||||
.execute(
|
||||
serde_json::json!({"action": "delete", "id": "ADR-9999"}),
|
||||
state.clone(),
|
||||
)
|
||||
.await;
|
||||
assert!(del_dec_err.is_err());
|
||||
|
||||
@@ -2882,9 +2908,14 @@ mod tests {
|
||||
|
||||
state.code.tech_debts.read_with(|debts| {
|
||||
assert_eq!(debts.len(), 300);
|
||||
assert!(debts.iter().any(|d| d.id == "critical-debt"), "Critical unresolved debt must be retained");
|
||||
assert!(!debts.iter().any(|d| d.id == "resolved-debt"), "Resolved debt should have been evicted first");
|
||||
assert!(
|
||||
debts.iter().any(|d| d.id == "critical-debt"),
|
||||
"Critical unresolved debt must be retained"
|
||||
);
|
||||
assert!(
|
||||
!debts.iter().any(|d| d.id == "resolved-debt"),
|
||||
"Resolved debt should have been evicted first"
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user