use super::{SubagentDefinition, SubagentError, SubagentResult, SubagentTools};
use std::collections::HashMap;
use std::path::Path;
pub struct DynamicSubagentGenerator {
templates: HashMap<String, AgentTemplate>,
}
#[derive(Debug, Clone)]
pub struct AgentTemplate {
pub name_pattern: String,
pub description_template: String,
pub base_tools: SubagentTools,
pub base_capabilities: Vec<String>,
pub instructions_template: String,
}
#[derive(Debug)]
pub struct GenerationRequest {
pub agent_type: AgentType,
pub technologies: Vec<String>,
pub project_context: ProjectContext,
pub requirements: Vec<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum AgentType {
FrameworkSpecialist,
LanguageExpert,
DomainSpecialist,
IntegrationSpecialist,
PerformanceSpecialist,
SecuritySpecialist,
Custom(String),
}
#[derive(Debug)]
pub struct ProjectContext {
pub primary_language: String,
pub frameworks: Vec<String>,
pub project_type: String,
pub complexity: ComplexityMetrics,
}
#[derive(Debug)]
pub struct ComplexityMetrics {
pub lines_of_code: usize,
pub module_count: usize,
pub avg_complexity: f32,
pub test_coverage: f32,
}
impl Default for DynamicSubagentGenerator {
fn default() -> Self {
Self::new()
}
}
impl DynamicSubagentGenerator {
pub fn new() -> Self {
Self {
templates: Self::initialize_templates(),
}
}
fn initialize_templates() -> HashMap<String, AgentTemplate> {
let mut templates = HashMap::new();
templates.insert(
"framework".to_string(),
AgentTemplate {
name_pattern: "{tech}-specialist".to_string(),
description_template:
"Specialist in {tech} development with deep framework knowledge.".to_string(),
base_tools: SubagentTools {
standard: vec![
"read_file".to_string(),
"write_file".to_string(),
"execute_command".to_string(),
],
semantic: vec!["find_symbol".to_string(), "search_for_pattern".to_string()],
memory: vec!["read_memory".to_string(), "write_memory".to_string()],
custom: vec![],
},
base_capabilities: vec![
"{tech} best practices".to_string(),
"Component architecture".to_string(),
"Performance optimization".to_string(),
],
instructions_template: include_str!("../../templates/framework_specialist.md")
.to_string(),
},
);
templates.insert(
"language".to_string(),
AgentTemplate {
name_pattern: "{lang}-expert".to_string(),
description_template:
"Expert in {lang} programming with advanced language features.".to_string(),
base_tools: SubagentTools {
standard: vec![
"read_file".to_string(),
"write_file".to_string(),
"execute_command".to_string(),
],
semantic: vec![
"find_symbol".to_string(),
"replace_symbol_body".to_string(),
"find_referencing_symbols".to_string(),
],
memory: vec!["read_memory".to_string(), "write_memory".to_string()],
custom: vec![],
},
base_capabilities: vec![
"{lang} idioms".to_string(),
"Memory management".to_string(),
"Concurrency patterns".to_string(),
],
instructions_template: include_str!("../../templates/language_expert.md")
.to_string(),
},
);
templates.insert(
"security".to_string(),
AgentTemplate {
name_pattern: "security-specialist".to_string(),
description_template:
"Security specialist focused on vulnerability detection and secure coding."
.to_string(),
base_tools: SubagentTools {
standard: vec![
"read_file".to_string(),
"write_file".to_string(),
"execute_command".to_string(),
],
semantic: vec![
"search_for_pattern".to_string(),
"find_referencing_symbols".to_string(),
],
memory: vec!["read_memory".to_string(), "write_memory".to_string()],
custom: vec![
"vulnerability_scanner".to_string(),
"security_analyzer".to_string(),
],
},
base_capabilities: vec![
"OWASP guidelines".to_string(),
"Security auditing".to_string(),
"Threat modeling".to_string(),
],
instructions_template: include_str!("../../templates/security_specialist.md")
.to_string(),
},
);
templates
}
pub async fn analyze_and_suggest(
&self,
project_path: &Path,
) -> SubagentResult<Vec<GenerationRequest>> {
let mut suggestions = Vec::new();
let context = self.analyze_project(project_path).await?;
for framework in &context.frameworks {
suggestions.push(GenerationRequest {
agent_type: AgentType::FrameworkSpecialist,
technologies: vec![framework.clone()],
project_context: context.clone(),
requirements: vec![
format!("Deep knowledge of {}", framework),
format!("{} best practices", framework),
],
});
}
if context.complexity.avg_complexity > 10.0 {
suggestions.push(GenerationRequest {
agent_type: AgentType::LanguageExpert,
technologies: vec![context.primary_language.clone()],
project_context: context.clone(),
requirements: vec![
"Advanced language features".to_string(),
"Performance optimization".to_string(),
],
});
}
if context.complexity.test_coverage < 50.0 {
suggestions.push(GenerationRequest {
agent_type: AgentType::SecuritySpecialist,
technologies: vec![],
project_context: context.clone(),
requirements: vec![
"Security auditing".to_string(),
"Vulnerability detection".to_string(),
],
});
}
Ok(suggestions)
}
pub fn generate_from_request(
&self,
request: &GenerationRequest,
) -> SubagentResult<(SubagentDefinition, String)> {
let template = self.get_template_for_type(&request.agent_type)?;
let name = self.generate_name(template, request);
let description = self.generate_description(template, request);
let tools = self.generate_tools(template, request);
let capabilities = self.generate_capabilities(template, request);
let instructions = self.generate_instructions(template, request);
let mut metadata = HashMap::new();
metadata.insert("generated".to_string(), serde_json::json!(true));
metadata.insert(
"generation_type".to_string(),
serde_json::json!(format!("{:?}", request.agent_type)),
);
metadata.insert(
"technologies".to_string(),
serde_json::json!(request.technologies),
);
let definition = SubagentDefinition {
name,
description,
tools,
capabilities,
metadata,
execution_config: Default::default(),
resource_limits: Default::default(),
spawn_context: None,
handoff_config: None,
};
Ok((definition, instructions))
}
fn get_template_for_type(&self, agent_type: &AgentType) -> SubagentResult<&AgentTemplate> {
match agent_type {
AgentType::FrameworkSpecialist => self
.templates
.get("framework")
.ok_or_else(|| SubagentError::NotFound("Framework template not found".to_string())),
AgentType::LanguageExpert => self
.templates
.get("language")
.ok_or_else(|| SubagentError::NotFound("Language template not found".to_string())),
AgentType::SecuritySpecialist => self
.templates
.get("security")
.ok_or_else(|| SubagentError::NotFound("Security template not found".to_string())),
_ => {
self.templates.get("framework").ok_or_else(|| {
SubagentError::NotFound("Default template not found".to_string())
})
}
}
}
fn generate_name(&self, template: &AgentTemplate, request: &GenerationRequest) -> String {
let mut name = template.name_pattern.clone();
if !request.technologies.is_empty() {
name = name.replace("{tech}", &request.technologies[0].to_lowercase());
name = name.replace("{lang}", &request.technologies[0].to_lowercase());
} else {
name = name.replace("{tech}", "specialized");
name = name.replace(
"{lang}",
&request.project_context.primary_language.to_lowercase(),
);
}
name
}
fn generate_description(
&self,
template: &AgentTemplate,
request: &GenerationRequest,
) -> String {
let mut description = template.description_template.clone();
if !request.technologies.is_empty() {
description = description.replace("{tech}", &request.technologies[0]);
description = description.replace("{lang}", &request.technologies[0]);
} else {
description = description.replace("{tech}", "specialized technology");
description = description.replace("{lang}", &request.project_context.primary_language);
}
description
}
fn generate_tools(
&self,
template: &AgentTemplate,
request: &GenerationRequest,
) -> SubagentTools {
let mut tools = template.base_tools.clone();
for req in &request.requirements {
if req.contains("performance") {
tools.custom.push("performance_profiler".to_string());
}
if req.contains("testing") {
tools.custom.push("test_generator".to_string());
}
if req.contains("documentation") {
tools.custom.push("doc_generator".to_string());
}
}
tools
}
fn generate_capabilities(
&self,
template: &AgentTemplate,
request: &GenerationRequest,
) -> Vec<String> {
let mut capabilities = Vec::new();
for cap in &template.base_capabilities {
let mut capability = cap.clone();
if !request.technologies.is_empty() {
capability = capability.replace("{tech}", &request.technologies[0]);
capability = capability.replace("{lang}", &request.technologies[0]);
}
capabilities.push(capability);
}
capabilities.extend(request.requirements.clone());
capabilities
}
fn generate_instructions(
&self,
template: &AgentTemplate,
request: &GenerationRequest,
) -> String {
let mut instructions = template.instructions_template.clone();
if !request.technologies.is_empty() {
instructions = instructions.replace("{tech}", &request.technologies[0]);
instructions = instructions.replace("{lang}", &request.technologies[0]);
}
if !request.requirements.is_empty() {
instructions.push_str("\n\n## Specific Requirements\n\n");
for req in &request.requirements {
instructions.push_str(&format!("- {}\n", req));
}
}
instructions
}
async fn analyze_project(&self, _project_path: &Path) -> SubagentResult<ProjectContext> {
Ok(ProjectContext {
primary_language: "Rust".to_string(),
frameworks: vec!["tokio".to_string(), "serde".to_string()],
project_type: "library".to_string(),
complexity: ComplexityMetrics {
lines_of_code: 10000,
module_count: 50,
avg_complexity: 8.5,
test_coverage: 75.0,
},
})
}
}
impl Clone for ProjectContext {
fn clone(&self) -> Self {
Self {
primary_language: self.primary_language.clone(),
frameworks: self.frameworks.clone(),
project_type: self.project_type.clone(),
complexity: ComplexityMetrics {
lines_of_code: self.complexity.lines_of_code,
module_count: self.complexity.module_count,
avg_complexity: self.complexity.avg_complexity,
test_coverage: self.complexity.test_coverage,
},
}
}
}