diff --git a/Cargo.lock b/Cargo.lock index 3bf68ac..e279f8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2654,6 +2654,7 @@ dependencies = [ "schemars", "serde", "serde_json", + "serde_yaml", "tantivy", "tempfile", "thiserror 2.0.20", @@ -4342,6 +4343,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.10.7" @@ -5438,6 +5452,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/server/Cargo.toml b/server/Cargo.toml index f68ac6f..16aa387 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -51,6 +51,7 @@ tokio-stream = { version = "0.1", features = ["sync"] } chrono = { version = "0.4.45", features = ["serde"] } ocrs = "0.13.1" rten = "0.26.0" +serde_yaml = "0.9.34" [build-dependencies] chrono = "0.4.45" diff --git a/server/src/error.rs b/server/src/error.rs index 3619f7c..f11cdd9 100644 --- a/server/src/error.rs +++ b/server/src/error.rs @@ -40,6 +40,9 @@ pub enum AppError { #[error("I/O Error: {0}")] IoError(#[from] std::io::Error), + + #[error("YAML Serialization Error: {0}")] + YamlError(#[from] serde_yaml::Error), } impl From for String { @@ -81,6 +84,10 @@ impl IntoResponse for AppError { StatusCode::INTERNAL_SERVER_ERROR, format!("I/O Error: {}", e), ), + AppError::YamlError(e) => ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("YAML Serialization Error: {}", e), + ), }; let body = Json(json!({ diff --git a/server/src/handlers/ast.rs b/server/src/handlers/ast.rs index 3e58663..ae1e649 100644 --- a/server/src/handlers/ast.rs +++ b/server/src/handlers/ast.rs @@ -504,7 +504,7 @@ impl McpTool for FindSymbolReferencesHandler { matches.extend(disk_matches); } - Ok(serde_json::to_string_pretty(&matches)?) + Ok(serde_yaml::to_string(&matches)?) } } @@ -560,7 +560,7 @@ impl McpTool for GetCallersHandler { callers.extend(disk_callers); } - Ok(serde_json::to_string_pretty(&callers)?) + Ok(serde_yaml::to_string(&callers)?) } } @@ -649,7 +649,7 @@ impl McpTool for AnalyzeImpactHandler { } }); - Ok(serde_json::to_string_pretty(&result)?) + Ok(serde_yaml::to_string(&result)?) } } diff --git a/server/src/handlers/env.rs b/server/src/handlers/env.rs index 6a55ec6..d1ad744 100644 --- a/server/src/handlers/env.rs +++ b/server/src/handlers/env.rs @@ -70,7 +70,7 @@ impl McpTool for EnvironmentHandler { .env_fingerprints .read_with(|fps| fps.get(&ns).cloned()); if let Some(fp) = data { - let data = Ok::(serde_json::to_string(&fp)?)?; + let data = Ok::(serde_yaml::to_string(&fp)?)?; Ok(data) } else { Ok("{}".to_string()) @@ -118,7 +118,7 @@ impl McpTool for EnvironmentHandler { EnvAction::GetDetails => { let data = state.env.environments.read_with(|envs| { let filtered: Vec<_> = envs.iter().filter(|e| e.namespace == ns).collect(); - Ok::(serde_json::to_string(&filtered)?) + Ok::(serde_yaml::to_string(&filtered)?) })?; Ok(data) } diff --git a/server/src/handlers/git.rs b/server/src/handlers/git.rs index d0f5a81..a727cdb 100644 --- a/server/src/handlers/git.rs +++ b/server/src/handlers/git.rs @@ -87,7 +87,7 @@ impl McpTool for GetActiveWorktreeContextHandler { .await .map_err(|e| crate::error::AppError::Internal(format!("Task panic: {}", e)))??; - Ok::(serde_json::to_string_pretty(&result)?) + Ok::(serde_yaml::to_string(&result)?) } } @@ -168,7 +168,7 @@ impl McpTool for QueryGitDiffsHandler { matches.extend(git_matches); } - Ok(serde_json::to_string_pretty(&matches)?) + Ok(serde_yaml::to_string(&matches)?) } } diff --git a/server/src/handlers/graph.rs b/server/src/handlers/graph.rs index cb421c2..c7b1e5a 100644 --- a/server/src/handlers/graph.rs +++ b/server/src/handlers/graph.rs @@ -542,7 +542,7 @@ impl McpTool for ReadGraphHandler { }) }; - let mut result_json = serde_json::to_string(&serialized)?; + let mut result_json = serde_yaml::to_string(&serialized)?; if let Some(max_tok) = max_tokens { let max_chars = max_tok * 4; @@ -579,7 +579,7 @@ impl McpTool for ReadGraphHandler { obj.insert("has_more".to_string(), serde_json::Value::Bool(true)); } - if let Ok(trunc_str) = serde_json::to_string(&truncated_val) + if let Ok(trunc_str) = serde_yaml::to_string(&truncated_val) && (trunc_str.len() <= max_chars || keep_count == 1) { result_json = trunc_str; break; @@ -638,7 +638,7 @@ impl McpTool for SearchNodesHandler { } } } - Ok::(serde_json::to_string(&matched_entities)?) + Ok::(serde_yaml::to_string(&matched_entities)?) })?; Ok(data) } @@ -679,7 +679,7 @@ impl McpTool for OpenNodesHandler { result.entities.insert(name, e); } } - Ok::(serde_json::to_string(&result)?) + Ok::(serde_yaml::to_string(&result)?) })?; Ok(data) } @@ -954,7 +954,7 @@ impl McpTool for FindOrphansHandler { .cloned() .collect::>() }); - let data = Ok::(serde_json::to_string(&orphans)?)?; + let data = Ok::(serde_yaml::to_string(&orphans)?)?; Ok(data) } } @@ -1047,7 +1047,7 @@ impl McpTool for GetSubgraphHandler { "relations": matched_relations, }); - Ok(serde_json::to_string_pretty(&result)?) + Ok(serde_yaml::to_string(&result)?) } } @@ -1146,7 +1146,7 @@ impl McpTool for SweepGraphHealthHandler { "health_score": if orphans.is_empty() && duplicates.is_empty() && stale_entities.is_empty() { "100%" } else { "Needs Maintenance" } }); - Ok(serde_json::to_string_pretty(&report)?) + Ok(serde_yaml::to_string(&report)?) } } @@ -1203,7 +1203,7 @@ impl McpTool for ResolveStaleSymbolsHandler { "status": "success" }); - Ok(serde_json::to_string_pretty(&report)?) + Ok(serde_yaml::to_string(&report)?) } } diff --git a/server/src/handlers/meta.rs b/server/src/handlers/meta.rs index 31a4b45..3c4e915 100644 --- a/server/src/handlers/meta.rs +++ b/server/src/handlers/meta.rs @@ -142,7 +142,7 @@ impl McpTool for SearchErrorFixesHandler { }) .collect(); - Ok::(serde_json::to_string_pretty(&suggestions)?) + Ok::(serde_yaml::to_string(&suggestions)?) })?; return Ok(data); } @@ -169,7 +169,7 @@ impl McpTool for SearchErrorFixesHandler { } }) .collect(); - Ok::(serde_json::to_string_pretty(&filtered)?) + Ok::(serde_yaml::to_string(&filtered)?) })?; Ok(data) } @@ -358,7 +358,7 @@ impl McpTool for QueryRecentChangesHandler { .take(limit) .cloned() .collect(); - Ok::(serde_json::to_string(&filtered)?) + Ok::(serde_yaml::to_string(&filtered)?) })?; Ok(data) } @@ -575,7 +575,7 @@ impl McpTool for DecisionsHandler { .collect(); if include_body { - Ok::(serde_json::to_string(&filtered)?) + Ok::(serde_yaml::to_string(&filtered)?) } else { let compact: Vec<_> = filtered .iter() @@ -592,7 +592,7 @@ impl McpTool for DecisionsHandler { }) }) .collect(); - Ok::(serde_json::to_string(&compact)?) + Ok::(serde_yaml::to_string(&compact)?) } })?; Ok(data) @@ -738,7 +738,7 @@ impl McpTool for TechDebtHandler { }), }) .collect(); - let mut json_str = serde_json::to_string(&filtered)?; + let mut json_str = serde_yaml::to_string(&filtered)?; if let Some(max_t) = req.max_tokens { let char_limit = max_t * 4; if json_str.len() > char_limit { @@ -1305,7 +1305,7 @@ impl McpTool for ManageCheckpointHandler { for s in snaps { list.push(serde_json::json!({"type": "snapshot", "id": s.id, "description": s.description, "namespace": s.namespace})); } - Ok(serde_json::to_string_pretty(&list)?) + Ok(serde_yaml::to_string(&list)?) } CheckpointAction::Delete => { let name = req.name_or_id.ok_or_else(|| { @@ -1427,7 +1427,7 @@ impl McpTool for QueryLineageHandler { "timeline": timeline }); - Ok(serde_json::to_string_pretty(&res)?) + Ok(serde_yaml::to_string(&res)?) } } @@ -1486,7 +1486,7 @@ impl McpTool for GetNextActionableTasksHandler { "tasks": actionable }); - Ok(serde_json::to_string_pretty(&res)?) + Ok(serde_yaml::to_string(&res)?) } } @@ -1555,7 +1555,7 @@ impl McpTool for HypothesesHandler { }) .collect(); - Ok(serde_json::to_string_pretty(&filtered)?) + Ok(serde_yaml::to_string(&filtered)?) } } } @@ -1634,7 +1634,7 @@ impl McpTool for GetPreflightContextHandler { "recent_activities": recent_activities }); - Ok(serde_json::to_string_pretty(&preflight)?) + Ok(serde_yaml::to_string(&preflight)?) } } @@ -1742,7 +1742,7 @@ impl McpTool for AgentSignalsHandler { .collect::>() }); - Ok(serde_json::to_string_pretty(&filtered)?) + Ok(serde_yaml::to_string(&filtered)?) } } } diff --git a/server/src/handlers/notes.rs b/server/src/handlers/notes.rs index fb5c7cd..af49f5e 100644 --- a/server/src/handlers/notes.rs +++ b/server/src/handlers/notes.rs @@ -60,7 +60,7 @@ impl McpTool for HandoffMemosHandler { } }) .collect(); - Ok::(serde_json::to_string(&filtered)?) + Ok::(serde_yaml::to_string(&filtered)?) })?; Ok(data) } diff --git a/server/src/handlers/tasks.rs b/server/src/handlers/tasks.rs index 478173c..001765a 100644 --- a/server/src/handlers/tasks.rs +++ b/server/src/handlers/tasks.rs @@ -297,12 +297,12 @@ impl McpTool for TasksHandler { _ => serde_json::json!({ "id": t.id, "title": t.title, "status": t.status, "description": t.description, "git_branch": t.git_branch }), }) .collect(); - let mut json_str = serde_json::to_string(&filtered)?; + let mut json_str = serde_yaml::to_string(&filtered)?; if let Some(max_t) = req.max_tokens { let char_limit = max_t * 4; while json_str.len() > char_limit && !filtered.is_empty() { filtered.pop(); - json_str = serde_json::to_string(&filtered)?; + json_str = serde_yaml::to_string(&filtered)?; } } Ok::(json_str) @@ -514,7 +514,7 @@ impl McpTool for MilestonesHandler { } }) .collect(); - Ok::(serde_json::to_string(&filtered)?) + Ok::(serde_yaml::to_string(&filtered)?) })?; Ok(data) } diff --git a/server/src/handlers/vision.rs b/server/src/handlers/vision.rs index 206b265..d6161f8 100644 --- a/server/src/handlers/vision.rs +++ b/server/src/handlers/vision.rs @@ -758,7 +758,7 @@ impl McpTool for ClipboardHandler { ); if let Some(img) = item { - Ok(serde_json::to_string_pretty(&img)?) + Ok(serde_yaml::to_string(&img)?) } else { Ok(json!({ "status": "no_image_in_clipboard", @@ -786,7 +786,7 @@ impl McpTool for ClipboardHandler { state.record_activity("clipboard", "Retrieved text from clipboard cache", None); if let Some(txt) = item { - Ok(serde_json::to_string_pretty(&txt)?) + Ok(serde_yaml::to_string(&txt)?) } else { Ok(json!({ "text": "", @@ -818,7 +818,7 @@ impl McpTool for ClipboardHandler { }; state.record_activity("clipboard", "Viewed clipboard history ring buffer", None); - Ok(serde_json::to_string_pretty(&history)?) + Ok(serde_yaml::to_string(&history)?) } ClipboardAction::Clear => { tokio::task::spawn_blocking(|| { @@ -905,7 +905,7 @@ impl McpTool for ClipboardHandler { .map_err(|e| crate::error::AppError::Internal(format!("Task panic: {}", e)))??; state.record_activity("clipboard", "Read contents from OS clipboard", None); - Ok::(serde_json::to_string_pretty(&Value::Object( + Ok::(serde_yaml::to_string(&Value::Object( out, ))?) } diff --git a/server/src/handlers/workspaces.rs b/server/src/handlers/workspaces.rs index c2ad03d..02a1097 100644 --- a/server/src/handlers/workspaces.rs +++ b/server/src/handlers/workspaces.rs @@ -122,7 +122,7 @@ impl McpTool for SnippetsHandler { .total_cmp(&a["score"].as_f64().unwrap_or(0.0)) }); scored.truncate(10); - Ok(serde_json::to_string_pretty(&scored)?) + Ok(serde_yaml::to_string(&scored)?) } else { let data = state.code.snippets.read_with(|snippets| { let results: Vec<_> = snippets @@ -153,7 +153,7 @@ impl McpTool for SnippetsHandler { }) }) .collect::>(); - serde_json::to_string_pretty(&results) + serde_yaml::to_string(&results) })?; Ok(data) }