Refactor: Migrate unwrap calls to AppError in MCP handlers
This commit is contained in:
1 parent
4e1a633dbd
commit
0e866f2465
12 files changed
+276
-326
No files matched your search
+36
-49
@@ -18,7 +18,7 @@ impl McpTool for LogDecisionHandler {
|
||||
crate::mcp::tool_def::<LogDecisionTool>("log_decision", "Execute log_decision")
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: LogDecisionTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
|
||||
let idx = state.get_search_index();
|
||||
@@ -68,7 +68,7 @@ impl McpTool for QueryDecisionsHandler {
|
||||
crate::mcp::tool_def::<QueryDecisionsTool>("query_decisions", "Execute query_decisions")
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: QueryDecisionsTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let data = state.adrs.read_with(|adrs| {
|
||||
let filtered: Vec<_> = adrs
|
||||
@@ -83,7 +83,7 @@ impl McpTool for QueryDecisionsHandler {
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
serde_json::to_string(&filtered).map_err(|e| e.to_string())
|
||||
Ok::<String, crate::error::AppError>(serde_json::to_string(&filtered)?)
|
||||
})?;
|
||||
Ok(data)
|
||||
}
|
||||
@@ -104,7 +104,7 @@ impl McpTool for DeleteDecisionHandler {
|
||||
)
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: crate::tools::DeleteDecisionTool =
|
||||
serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let mut found = false;
|
||||
@@ -119,7 +119,7 @@ impl McpTool for DeleteDecisionHandler {
|
||||
state.rebuild_index().await;
|
||||
Ok("Decision deleted successfully".to_string())
|
||||
} else {
|
||||
Err("Decision not found".to_string())
|
||||
Err(crate::error::AppError::Internal("Decision not found".to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,7 @@ impl McpTool for LogErrorFixHandler {
|
||||
crate::mcp::tool_def::<LogErrorFixTool>("log_error_fix", "Execute log_error_fix")
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: LogErrorFixTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let text_to_embed = format!("Signature: {}\nSolution: {}", req.signature, req.solution);
|
||||
let embedding = crate::embedding::generate_embedding_async(text_to_embed).await.ok();
|
||||
@@ -169,7 +169,7 @@ impl McpTool for SearchErrorFixesHandler {
|
||||
)
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: SearchErrorFixesTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let q = req.query;
|
||||
let data = state.error_fixes.read_with(|fixes| {
|
||||
@@ -180,7 +180,7 @@ impl McpTool for SearchErrorFixesHandler {
|
||||
|| contains_ignore_ascii_case(&f.solution, &q)
|
||||
})
|
||||
.collect();
|
||||
serde_json::to_string(&filtered).map_err(|e| e.to_string())
|
||||
Ok::<String, crate::error::AppError>(serde_json::to_string(&filtered)?)
|
||||
})?;
|
||||
Ok(data)
|
||||
}
|
||||
@@ -198,7 +198,7 @@ impl McpTool for LogCodeChangeHandler {
|
||||
crate::mcp::tool_def::<LogCodeChangeTool>("log_code_change", "Execute log_code_change")
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: LogCodeChangeTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
state.ledger.modify(|ledger| {
|
||||
ledger.push(CodeChange {
|
||||
@@ -228,10 +228,10 @@ impl McpTool for QueryRecentChangesHandler {
|
||||
)
|
||||
}
|
||||
|
||||
async fn execute(&self, _args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, _args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let data = state
|
||||
.ledger
|
||||
.read_with(|l| serde_json::to_string(l).map_err(|e| e.to_string()))?;
|
||||
.read_with(|l| Ok::<String, crate::error::AppError>(serde_json::to_string(l)?))?;
|
||||
Ok(data)
|
||||
}
|
||||
}
|
||||
@@ -248,7 +248,7 @@ impl McpTool for LearnPreferenceHandler {
|
||||
crate::mcp::tool_def::<LearnPreferenceTool>("learn_preference", "Execute learn_preference")
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: LearnPreferenceTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
state.prefs.modify(|prefs| {
|
||||
prefs.insert(
|
||||
@@ -276,10 +276,10 @@ impl McpTool for ReadPreferencesHandler {
|
||||
crate::mcp::tool_def::<ReadPreferencesTool>("read_preferences", "Execute read_preferences")
|
||||
}
|
||||
|
||||
async fn execute(&self, _args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, _args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
state
|
||||
.prefs
|
||||
.read_with(|prefs| serde_json::to_string(prefs).map_err(|e| e.to_string()))
|
||||
.read_with(|prefs| Ok::<String, crate::error::AppError>(serde_json::to_string(prefs)?))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ impl McpTool for LogTechDebtHandler {
|
||||
crate::mcp::tool_def::<LogTechDebtTool>("log_tech_debt", "Execute log_tech_debt")
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: LogTechDebtTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let text_to_embed = format!("Description: {}\nIdeal Solution: {}", req.description, req.ideal_solution);
|
||||
let embedding = crate::embedding::generate_embedding_async(text_to_embed).await.ok();
|
||||
@@ -331,7 +331,7 @@ impl McpTool for ResolveTechDebtHandler {
|
||||
)
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: ResolveTechDebtTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let mut found = false;
|
||||
state.tech_debts.modify(|debts| {
|
||||
@@ -346,10 +346,7 @@ impl McpTool for ResolveTechDebtHandler {
|
||||
if found {
|
||||
Ok("Tech debt resolved".to_string())
|
||||
} else {
|
||||
Err(
|
||||
"Tech debt not found. Please verify the tech debt ID using list_tech_debt."
|
||||
.to_string(),
|
||||
)
|
||||
Err(crate::error::AppError::Internal("Tech debt not found. Please verify the tech debt ID using list_tech_debt.".to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,7 +363,7 @@ impl McpTool for ListTechDebtHandler {
|
||||
crate::mcp::tool_def::<ListTechDebtTool>("list_tech_debt", "Execute list_tech_debt")
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: ListTechDebtTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let data = state.tech_debts.read_with(|debts| {
|
||||
let filtered: Vec<_> = debts
|
||||
@@ -375,7 +372,7 @@ impl McpTool for ListTechDebtHandler {
|
||||
d.namespace == req.namespace && (req.include_resolved || !d.is_resolved)
|
||||
})
|
||||
.collect();
|
||||
serde_json::to_string(&filtered).map_err(|e| e.to_string())
|
||||
Ok::<String, crate::error::AppError>(serde_json::to_string(&filtered)?)
|
||||
})?;
|
||||
Ok(data)
|
||||
}
|
||||
@@ -393,7 +390,7 @@ impl McpTool for OmniSearchHandler {
|
||||
crate::mcp::tool_def::<OmniSearchTool>("omni_search", "Execute omni_search")
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: OmniSearchTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let limit = req.limit.unwrap_or(5);
|
||||
let include_body = req.include_body.unwrap_or(false);
|
||||
@@ -403,10 +400,10 @@ impl McpTool for OmniSearchHandler {
|
||||
{
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
return Err(format!(
|
||||
return Err(crate::error::AppError::Internal(format!(
|
||||
"Search query failed (possibly malformed Lucene syntax). Error: {}",
|
||||
e
|
||||
));
|
||||
)));
|
||||
}
|
||||
};
|
||||
// tracing::info!("OMNI SEARCH MATCHES: {:?}", matches);
|
||||
@@ -614,7 +611,7 @@ impl McpTool for GetProjectHealthHandler {
|
||||
)
|
||||
}
|
||||
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
|
||||
let req: GetProjectHealthTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||
let active_tasks = state
|
||||
.tasks
|
||||
@@ -677,7 +674,7 @@ mod tests {
|
||||
"git_branch": "main"
|
||||
});
|
||||
|
||||
let res = handler.execute(args, state.clone()).await.unwrap();
|
||||
let res = handler.execute(args, state.clone()).await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
assert!(res.contains("Error fix logged"));
|
||||
}
|
||||
|
||||
@@ -689,7 +686,7 @@ mod tests {
|
||||
let handler = GetProjectHealthHandler;
|
||||
let args = json!({"namespace": "global"});
|
||||
|
||||
let res = handler.execute(args, state.clone()).await.unwrap();
|
||||
let res = handler.execute(args, state.clone()).await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
assert!(res.contains("unresolved_tech_debt"));
|
||||
}
|
||||
|
||||
@@ -707,8 +704,7 @@ mod tests {
|
||||
});
|
||||
let res1 = decision_handler
|
||||
.execute(args_dec, state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
assert_eq!(res1, "Decision logged as ADR-0001");
|
||||
|
||||
let debt_handler = LogTechDebtHandler;
|
||||
@@ -724,8 +720,7 @@ mod tests {
|
||||
});
|
||||
let res2 = debt_handler
|
||||
.execute(args_debt, state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
assert_eq!(res2, "Tech debt logged");
|
||||
|
||||
let list_debt = ListTechDebtHandler;
|
||||
@@ -734,8 +729,7 @@ mod tests {
|
||||
json!({"namespace": "global", "include_resolved": false}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
assert!(res3.contains("Hardcoded path"));
|
||||
|
||||
let pref_handler = LearnPreferenceHandler;
|
||||
@@ -745,12 +739,11 @@ mod tests {
|
||||
});
|
||||
let res4 = pref_handler
|
||||
.execute(args_pref, state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
assert_eq!(res4, "Preference learned");
|
||||
|
||||
let read_pref = ReadPreferencesHandler;
|
||||
let res5 = read_pref.execute(json!({}), state.clone()).await.unwrap();
|
||||
let res5 = read_pref.execute(json!({}), state.clone()).await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
assert!(res5.contains("use spaces"));
|
||||
}
|
||||
|
||||
@@ -768,14 +761,12 @@ mod tests {
|
||||
});
|
||||
code_handler
|
||||
.execute(args_code, state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
|
||||
let query_changes = QueryRecentChangesHandler;
|
||||
let res_changes = query_changes
|
||||
.execute(json!({}), state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
assert!(res_changes.contains("main.rs"));
|
||||
|
||||
let debt_handler = LogTechDebtHandler;
|
||||
@@ -791,8 +782,7 @@ mod tests {
|
||||
});
|
||||
debt_handler
|
||||
.execute(args_debt, state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
|
||||
// resolve it
|
||||
let list_debt = ListTechDebtHandler;
|
||||
@@ -801,16 +791,14 @@ mod tests {
|
||||
json!({"namespace": "global", "include_resolved": false}),
|
||||
state.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
let uuid_start = debt_list.find("id\":\"").unwrap() + 5;
|
||||
let uuid = &debt_list[uuid_start..uuid_start + 36];
|
||||
|
||||
let resolve_debt = ResolveTechDebtHandler;
|
||||
resolve_debt
|
||||
.execute(json!({"id": uuid}), state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -844,8 +832,7 @@ mod tests {
|
||||
let omni = OmniSearchHandler;
|
||||
let omni_res = omni
|
||||
.execute(json!({"query": "Omni"}), state.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
.await.map_err(|e| crate::error::AppError::Internal(e.to_string()))?;
|
||||
// tracing::info!("OMNI RES: {}", omni_res);
|
||||
assert!(
|
||||
omni_res.contains("omni-1"),
|
||||
|
||||
Reference in new issue
Block a user