i-self 0.4.3

Personal developer-companion CLI: scans your repos, indexes code semantically, watches your activity, and moves AI-agent sessions between tools (Claude Code, Aider, Goose, OpenAI Codex CLI, Continue.dev, OpenCode).
use super::{AgentId, AgentResult, AgentTask, TaskType};
use anyhow::Result;
use dashmap::DashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::{debug, info};

/// Executes agent tasks and manages results
pub struct AgentExecutor {
    results: DashMap<AgentId, AgentResult>,
    metrics: Arc<RwLock<ExecutionMetrics>>,
}

#[derive(Default)]
struct ExecutionMetrics {
    total_executed: usize,
    successful: usize,
    failed: usize,
    total_duration_ms: u64,
}

impl AgentExecutor {
    pub fn new() -> Self {
        Self {
            results: DashMap::new(),
            metrics: Arc::new(RwLock::new(ExecutionMetrics::default())),
        }
    }

    /// Execute a single task
    pub async fn execute(&self, task: AgentTask) -> Result<AgentResult> {
        let start = std::time::Instant::now();
        
        debug!("Executing task: {:?}", task.task_type);
        
        // Task execution logic based on type
        let result = match task.task_type {
            TaskType::ScanRepository => {
                self.execute_repo_scan(&task).await
            }
            TaskType::AnalyzeCode => {
                self.execute_code_analysis(&task).await
            }
            TaskType::ExtractPatterns => {
                self.execute_pattern_extraction(&task).await
            }
            TaskType::SummarizeWork => {
                self.execute_work_summary(&task).await
            }
            TaskType::UpdateKnowledge => {
                self.execute_knowledge_update(&task).await
            }
            TaskType::QueryKnowledge => {
                self.execute_knowledge_query(&task).await
            }
        };

        let duration = start.elapsed().as_millis() as u64;
        
        // Update metrics
        {
            let mut metrics = self.metrics.write().await;
            metrics.total_executed += 1;
            metrics.total_duration_ms += duration;
            if result.is_ok() {
                metrics.successful += 1;
            } else {
                metrics.failed += 1;
            }
        }

        result
    }

    /// Store result from agent execution
    pub async fn store_result(&self, agent_id: AgentId, result: AgentResult) {
        self.results.insert(agent_id, result);
    }

    /// Collect all results
    pub async fn collect_results(&self) -> Vec<(AgentId, AgentResult)> {
        self.results
            .iter()
            .map(|entry| (entry.key().clone(), entry.value().clone()))
            .collect()
    }

    /// Get execution metrics
    pub async fn get_metrics(&self) -> ExecutionMetricsSnapshot {
        let metrics = self.metrics.read().await;
        ExecutionMetricsSnapshot {
            total_executed: metrics.total_executed,
            successful: metrics.successful,
            failed: metrics.failed,
            average_duration_ms: if metrics.total_executed > 0 {
                metrics.total_duration_ms / metrics.total_executed as u64
            } else {
                0
            },
        }
    }

    // Task-specific execution methods
    async fn execute_repo_scan(&self, task: &AgentTask) -> Result<AgentResult> {
        info!("Scanning repository: {:?}", task.metadata.source);
        
        // Implementation will be provided by github module
        Ok(AgentResult {
            task_id: task.id.clone(),
            success: true,
            data: serde_json::json!({ "status": "scanned" }),
            summary: "Repository scanned successfully".to_string(),
            confidence: 1.0,
        })
    }

    async fn execute_code_analysis(&self, task: &AgentTask) -> Result<AgentResult> {
        info!("Analyzing code from: {:?}", task.metadata.source);
        
        Ok(AgentResult {
            task_id: task.id.clone(),
            success: true,
            data: serde_json::json!({ "status": "analyzed" }),
            summary: "Code analysis completed".to_string(),
            confidence: 0.95,
        })
    }

    async fn execute_pattern_extraction(&self, task: &AgentTask) -> Result<AgentResult> {
        info!("Extracting patterns from: {:?}", task.metadata.source);
        
        Ok(AgentResult {
            task_id: task.id.clone(),
            success: true,
            data: serde_json::json!({ "status": "patterns_extracted" }),
            summary: "Patterns extracted successfully".to_string(),
            confidence: 0.9,
        })
    }

    async fn execute_work_summary(&self, task: &AgentTask) -> Result<AgentResult> {
        info!("Summarizing work");
        
        Ok(AgentResult {
            task_id: task.id.clone(),
            success: true,
            data: serde_json::json!({ "status": "summarized" }),
            summary: "Work summary generated".to_string(),
            confidence: 0.85,
        })
    }

    async fn execute_knowledge_update(&self, task: &AgentTask) -> Result<AgentResult> {
        info!("Updating knowledge base");
        
        Ok(AgentResult {
            task_id: task.id.clone(),
            success: true,
            data: serde_json::json!({ "status": "updated" }),
            summary: "Knowledge base updated".to_string(),
            confidence: 1.0,
        })
    }

    async fn execute_knowledge_query(&self, task: &AgentTask) -> Result<AgentResult> {
        info!("Querying knowledge base");
        
        Ok(AgentResult {
            task_id: task.id.clone(),
            success: true,
            data: serde_json::json!({ "status": "queried" }),
            summary: "Knowledge query completed".to_string(),
            confidence: 0.9,
        })
    }
}

#[derive(Debug, Clone)]
pub struct ExecutionMetricsSnapshot {
    pub total_executed: usize,
    pub successful: usize,
    pub failed: usize,
    pub average_duration_ms: u64,
}

impl Default for AgentExecutor {
    fn default() -> Self {
        Self::new()
    }
}