use crate::core::adapters::ai::KandilAI;
use crate::core::agents::base::{Agent, AgentState, ReActLoop};
use anyhow::Result;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DesignDocument {
pub architecture: ArchitectureStyle,
pub components: Vec<Component>,
pub data_flow: Vec<DataFlow>,
pub technology_stack: TechnologyStack,
pub design_patterns: Vec<DesignPattern>,
pub diagrams: Vec<Diagram>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ArchitectureStyle {
CleanArchitecture,
Hexagonal,
Layered,
Microservices,
EventDriven,
Other(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Component {
pub name: String,
pub description: String,
pub responsibilities: Vec<String>,
pub interfaces: Vec<Interface>,
pub dependencies: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Interface {
pub name: String,
pub methods: Vec<Method>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Method {
pub name: String,
pub parameters: Vec<Parameter>,
pub return_type: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Parameter {
pub name: String,
pub parameter_type: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataFlow {
pub source: String,
pub destination: String,
pub data_type: String,
pub description: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TechnologyStack {
pub frontend: Vec<String>,
pub backend: Vec<String>,
pub database: Vec<String>,
pub infrastructure: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DesignPattern {
pub name: String,
pub description: String,
pub use_cases: Vec<String>,
pub implementation_notes: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Diagram {
pub title: String,
pub description: String,
pub content: String, pub diagram_type: DiagramType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DiagramType {
Component,
Sequence,
Class,
Deployment,
Flowchart,
Other(String),
}
pub struct DesignAgent {
ai: Arc<KandilAI>,
}
impl DesignAgent {
pub fn new(ai: Arc<KandilAI>) -> Self {
Self { ai }
}
pub async fn generate_design_document(&self, requirements_doc: &str) -> Result<DesignDocument> {
let loop_engine = ReActLoop::new(5);
let task = format!(
"As a Software Architect, design a system based on these requirements: {}.\n\nCreate a comprehensive design document covering architecture, components, data flow, technology stack, design patterns, and diagrams.",
requirements_doc
);
let result = loop_engine.run(self, &task).await?;
Ok(DesignDocument {
architecture: ArchitectureStyle::CleanArchitecture,
components: vec![],
data_flow: vec![],
technology_stack: TechnologyStack {
frontend: vec![],
backend: vec![],
database: vec![],
infrastructure: vec![],
},
design_patterns: vec![],
diagrams: vec![],
})
}
}
#[async_trait]
impl Agent for DesignAgent {
async fn plan(&self, state: &AgentState) -> Result<String> {
let prompt = format!(
"Given these design requirements: {}\n\nCurrent state: Step {}/{}\n\nPlan the next step to design the system architecture. Consider architectural patterns, technology selection, and component decomposition.",
state.task, state.current_step + 1, state.max_steps
);
self.ai.chat(&prompt).await
}
async fn act(&self, plan: &str) -> Result<String> {
let prompt = format!(
"Execute this design plan: {}\n\nGenerate specific architectural elements, component definitions, or technology recommendations.",
plan
);
self.ai.chat(&prompt).await
}
async fn observe(&self, result: &str) -> Result<String> {
let prompt = format!(
"Analyze this design result: {}\n\nHow does this contribute to the overall system architecture? What aspects need refinement?",
result
);
self.ai.chat(&prompt).await
}
}