#![cfg_attr(coverage_nightly, coverage(off))]
use crate::agents::analyzer_actor::AnalyzerActor;
use crate::agents::messages::{AnalyzeMessage, TransformMessage, ValidateMessage};
use crate::agents::registry::AgentRegistry;
use crate::agents::transformer_actor::TransformerActor;
use crate::agents::validator_actor::ValidatorActor;
use crate::agents::Priority;
use crate::mcp_integration::{error_codes, McpError, McpTool, ToolMetadata};
use actix::prelude::*;
use async_trait::async_trait;
use serde_json::{json, Value};
use std::sync::Arc;
pub struct AnalyzeTool {
pub(super) _registry: Arc<AgentRegistry>,
pub(super) analyzer: Option<Addr<AnalyzerActor>>,
}
impl AnalyzeTool {
pub fn new(registry: Arc<AgentRegistry>) -> Self {
Self {
_registry: registry,
analyzer: None,
}
}
pub fn new_with_actor(registry: Arc<AgentRegistry>, analyzer: Addr<AnalyzerActor>) -> Self {
Self {
_registry: registry,
analyzer: Some(analyzer),
}
}
}
#[async_trait]
impl McpTool for AnalyzeTool {
fn metadata(&self) -> ToolMetadata {
ToolMetadata {
name: "analyze".to_string(),
description: "Analyze code for quality metrics and issues".to_string(),
input_schema: json!({
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Source code to analyze"
},
"language": {
"type": "string",
"description": "Programming language"
},
"metrics": {
"type": "array",
"items": {"type": "string"},
"description": "Metrics to calculate"
}
},
"required": ["code", "language"]
}),
}
}
async fn execute(&self, params: Value) -> Result<Value, McpError> {
let code = params["code"].as_str().ok_or_else(|| McpError {
code: error_codes::INVALID_PARAMS,
message: "Missing code parameter".to_string(),
data: None,
})?;
let _language = params["language"].as_str().ok_or_else(|| McpError {
code: error_codes::INVALID_PARAMS,
message: "Missing language parameter".to_string(),
data: None,
})?;
let analyzer = self.analyzer.as_ref().ok_or_else(|| McpError {
code: error_codes::INTERNAL_ERROR,
message: "Analyzer actor not initialized".to_string(),
data: None,
})?;
let priority = params["priority"]
.as_str()
.map(|p| match p {
"critical" => Priority::Critical,
"high" => Priority::High,
"low" => Priority::Low,
_ => Priority::Normal,
})
.unwrap_or(Priority::Normal);
let message = AnalyzeMessage {
code: code.to_string(),
priority,
};
let response = analyzer
.send(message)
.await
.map_err(|e| McpError {
code: error_codes::INTERNAL_ERROR,
message: format!("Actor communication failed: {}", e),
data: None,
})?
.map_err(|e| McpError {
code: error_codes::INTERNAL_ERROR,
message: format!("Analysis failed: {}", e),
data: None,
})?;
match response {
crate::agents::AgentResponse::Analyzed(metrics) => Ok(json!({
"type": "text",
"text": format!("Analysis Results:\n\nComplexity: {}\nLines: {}\nFunctions: {}\nClasses: {}\nImports: {}\n",
metrics.complexity,
metrics.lines_of_code,
metrics.functions,
metrics.classes,
metrics.imports
)
})),
_ => Err(McpError {
code: error_codes::INTERNAL_ERROR,
message: "Unexpected response type".to_string(),
data: None,
}),
}
}
}
pub struct TransformTool {
pub(super) _registry: Arc<AgentRegistry>,
pub(super) transformer: Option<Addr<TransformerActor>>,
}
impl TransformTool {
pub fn new(registry: Arc<AgentRegistry>) -> Self {
Self {
_registry: registry,
transformer: None,
}
}
pub fn new_with_actor(
registry: Arc<AgentRegistry>,
transformer: Addr<TransformerActor>,
) -> Self {
Self {
_registry: registry,
transformer: Some(transformer),
}
}
}
#[async_trait]
impl McpTool for TransformTool {
fn metadata(&self) -> ToolMetadata {
ToolMetadata {
name: "transform".to_string(),
description: "Transform code using AST manipulation".to_string(),
input_schema: json!({
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Source code to transform"
},
"language": {
"type": "string",
"description": "Programming language"
},
"transformation": {
"type": "string",
"description": "Type of transformation",
"enum": ["optimize", "minify", "beautify", "refactor"]
},
"options": {
"type": "object",
"description": "Transformation options"
}
},
"required": ["code", "language", "transformation"]
}),
}
}
async fn execute(&self, params: Value) -> Result<Value, McpError> {
let code = params["code"].as_str().ok_or_else(|| McpError {
code: error_codes::INVALID_PARAMS,
message: "Missing code parameter".to_string(),
data: None,
})?;
let _transformation = params["transformation"].as_str().ok_or_else(|| McpError {
code: error_codes::INVALID_PARAMS,
message: "Missing transformation parameter".to_string(),
data: None,
})?;
let transformer = self.transformer.as_ref().ok_or_else(|| McpError {
code: error_codes::INTERNAL_ERROR,
message: "Transformer actor not initialized".to_string(),
data: None,
})?;
let priority = params["priority"]
.as_str()
.map(|p| match p {
"critical" => Priority::Critical,
"high" => Priority::High,
"low" => Priority::Low,
_ => Priority::Normal,
})
.unwrap_or(Priority::Normal);
let rules = params["rules"]
.as_array()
.map(|arr| {
arr.iter()
.filter_map(|v| v.as_str().map(String::from))
.collect::<Vec<_>>()
})
.unwrap_or_default();
let message = TransformMessage {
code: code.to_string(),
rules,
priority,
};
let response = transformer
.send(message)
.await
.map_err(|e| McpError {
code: error_codes::INTERNAL_ERROR,
message: format!("Actor communication failed: {}", e),
data: None,
})?
.map_err(|e| McpError {
code: error_codes::INTERNAL_ERROR,
message: format!("Transformation failed: {}", e),
data: None,
})?;
match response {
crate::agents::AgentResponse::Transformed(result) => Ok(json!({
"type": "text",
"text": format!(
"Transformation Results:\n\nTransformed Code:\n{}\n\nChanges: {}\n",
result.transformed,
result.changes.len()
)
})),
_ => Err(McpError {
code: error_codes::INTERNAL_ERROR,
message: "Unexpected response type".to_string(),
data: None,
}),
}
}
}
pub struct ValidateTool {
pub(super) _registry: Arc<AgentRegistry>,
pub(super) analyzer: Option<Addr<AnalyzerActor>>,
pub(super) validator: Option<Addr<ValidatorActor>>,
}
impl ValidateTool {
pub fn new(registry: Arc<AgentRegistry>) -> Self {
Self {
_registry: registry,
analyzer: None,
validator: None,
}
}
pub fn new_with_actors(
registry: Arc<AgentRegistry>,
analyzer: Addr<AnalyzerActor>,
validator: Addr<ValidatorActor>,
) -> Self {
Self {
_registry: registry,
analyzer: Some(analyzer),
validator: Some(validator),
}
}
}
#[async_trait]
impl McpTool for ValidateTool {
fn metadata(&self) -> ToolMetadata {
ToolMetadata {
name: "validate".to_string(),
description: "Validate code against quality standards".to_string(),
input_schema: json!({
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Source code to validate"
},
"language": {
"type": "string",
"description": "Programming language"
},
"rules": {
"type": "array",
"items": {"type": "string"},
"description": "Validation rules to apply"
},
"thresholds": {
"type": "object",
"description": "Quality thresholds"
}
},
"required": ["code", "language"]
}),
}
}
async fn execute(&self, params: Value) -> Result<Value, McpError> {
let code = params["code"].as_str().ok_or_else(|| McpError {
code: error_codes::INVALID_PARAMS,
message: "Missing code parameter".to_string(),
data: None,
})?;
let analyzer = self.analyzer.as_ref().ok_or_else(|| McpError {
code: error_codes::INTERNAL_ERROR,
message: "Analyzer actor not initialized".to_string(),
data: None,
})?;
let validator = self.validator.as_ref().ok_or_else(|| McpError {
code: error_codes::INTERNAL_ERROR,
message: "Validator actor not initialized".to_string(),
data: None,
})?;
let analyze_msg = AnalyzeMessage {
code: code.to_string(),
priority: Priority::Normal,
};
let analyze_response = analyzer
.send(analyze_msg)
.await
.map_err(|e| McpError {
code: error_codes::INTERNAL_ERROR,
message: format!("Actor communication failed: {}", e),
data: None,
})?
.map_err(|e| McpError {
code: error_codes::INTERNAL_ERROR,
message: format!("Analysis failed: {}", e),
data: None,
})?;
let metrics = match analyze_response {
crate::agents::AgentResponse::Analyzed(m) => m,
_ => {
return Err(McpError {
code: error_codes::INTERNAL_ERROR,
message: "Unexpected response type from analyzer".to_string(),
data: None,
})
}
};
let thresholds = crate::modules::validator::Thresholds::default();
let validate_msg = ValidateMessage {
metrics: metrics.clone(),
thresholds,
priority: Priority::Normal,
};
let validate_response = validator
.send(validate_msg)
.await
.map_err(|e| McpError {
code: error_codes::INTERNAL_ERROR,
message: format!("Actor communication failed: {}", e),
data: None,
})?
.map_err(|e| McpError {
code: error_codes::INTERNAL_ERROR,
message: format!("Validation failed: {}", e),
data: None,
})?;
match validate_response {
crate::agents::AgentResponse::Validated(result) => Ok(json!({
"type": "text",
"text": format!(
"Validation Results:\n\nPassed: {}\nComplexity: {}\nViolations: {}\n",
result.passed,
metrics.complexity,
result.violations.len()
)
})),
_ => Err(McpError {
code: error_codes::INTERNAL_ERROR,
message: "Unexpected response type from validator".to_string(),
data: None,
}),
}
}
}