//! # Knowledge Graph Execution Tracking Example //! //! Demonstrates how to record agent executions and query the knowledge graph. //! //! ## What This Example Shows //! - Creating a `TemporalKG` instance (in-memory for this example) //! - Recording execution events with timestamps //! - Querying executions by agent and task type //! - Understanding execution metrics (duration, success rate, costs) //! //! ## Run //! ```bash //! cargo run --example 01-execution-tracking -p vapora-knowledge-graph //! ``` //! //! ## Expected Output //! ```text //! === Knowledge Graph Execution Tracking Example === //! //! Recording execution events... //! ✓ Recorded: developer-1 @ 2025-01-12 (coding, 250ms, success) //! ✓ Recorded: developer-1 @ 2025-01-11 (testing, 180ms, success) //! ✓ Recorded: developer-2 @ 2025-01-12 (coding, 320ms, failed) //! //! === Execution Summary === //! Total executions: 3 //! By agent: //! developer-1: 2 executions (success rate: 100%) //! developer-2: 1 execution (success rate: 0%) //! By task type: //! coding: 2 executions (success rate: 50%) //! testing: 1 execution (success rate: 100%) //! ``` use chrono::{Duration, Utc}; use vapora_knowledge_graph::ExecutionRecord; fn main() { println!("=== Knowledge Graph Execution Tracking Example ===\n"); // Step 1: Create sample execution records let now = Utc::now(); let executions = vec![ ExecutionRecord { id: "exec-001".to_string(), task_id: "task-001".to_string(), agent_id: "developer-1".to_string(), agent_role: Some("developer".to_string()), task_type: "coding".to_string(), description: "Implement authentication module".to_string(), root_cause: None, solution: Some("Used OAuth2 with JWT tokens".to_string()), timestamp: now - Duration::hours(24), duration_ms: 250, success: true, input_tokens: 500, output_tokens: 300, cost_cents: 12, provider: "claude".to_string(), error: None, }, ExecutionRecord { id: "exec-002".to_string(), task_id: "task-002".to_string(), agent_id: "developer-1".to_string(), agent_role: Some("developer".to_string()), task_type: "testing".to_string(), description: "Write unit tests for auth module".to_string(), root_cause: None, solution: Some("Implemented 100% code coverage".to_string()), timestamp: now - Duration::hours(20), duration_ms: 180, success: true, input_tokens: 300, output_tokens: 200, cost_cents: 8, provider: "claude".to_string(), error: None, }, ExecutionRecord { id: "exec-003".to_string(), task_id: "task-003".to_string(), agent_id: "developer-2".to_string(), agent_role: Some("developer".to_string()), task_type: "coding".to_string(), description: "Refactor database layer".to_string(), root_cause: Some("Performance regression detected".to_string()), solution: None, timestamp: now - Duration::hours(12), duration_ms: 320, success: false, input_tokens: 600, output_tokens: 400, cost_cents: 18, provider: "gpt-4".to_string(), error: Some("Timeout after 320ms".to_string()), }, ]; // Step 2: Display execution records println!("Recording execution events..."); for exec in &executions { let status = if exec.success { "✓" } else { "✗" }; println!( " {} {} (agent: {}, task: {}, duration: {}ms, success: {})", status, exec.timestamp.format("%Y-%m-%d %H:%M"), exec.agent_id, exec.task_type, exec.duration_ms, exec.success ); } println!(); // Step 3: Analyze executions by agent println!("=== Execution Summary ==="); println!("Total executions: {}\n", executions.len()); println!("By Agent:"); let mut agents: std::collections::HashMap> = std::collections::HashMap::new(); for exec in &executions { agents .entry(exec.agent_id.clone()) .or_insert_with(Vec::new) .push(exec); } for (agent_id, agent_execs) in &agents { let successes = agent_execs.iter().filter(|e| e.success).count(); let success_rate = (successes as f64 / agent_execs.len() as f64) * 100.0; println!( " {}: {} executions (success rate: {:.0}%)", agent_id, agent_execs.len(), success_rate ); let total_duration: u64 = agent_execs.iter().map(|e| e.duration_ms).sum(); let avg_duration = total_duration / agent_execs.len() as u64; println!(" Average duration: {}ms", avg_duration); let total_input_tokens: u64 = agent_execs.iter().map(|e| e.input_tokens).sum(); let total_output_tokens: u64 = agent_execs.iter().map(|e| e.output_tokens).sum(); println!( " Tokens: {} input, {} output", total_input_tokens, total_output_tokens ); } // Step 4: Analyze executions by task type println!("\nBy Task Type:"); let mut task_types: std::collections::HashMap> = std::collections::HashMap::new(); for exec in &executions { task_types .entry(exec.task_type.clone()) .or_insert_with(Vec::new) .push(exec); } for (task_type, task_execs) in &task_types { let successes = task_execs.iter().filter(|e| e.success).count(); let success_rate = (successes as f64 / task_execs.len() as f64) * 100.0; println!( " {}: {} executions (success rate: {:.0}%)", task_type, task_execs.len(), success_rate ); let avg_duration: u64 = task_execs.iter().map(|e| e.duration_ms).sum::() / task_execs.len() as u64; println!(" Average duration: {}ms", avg_duration); } // Step 5: Analyze costs println!("\n=== Cost Analysis ==="); let mut costs_by_provider: std::collections::HashMap = std::collections::HashMap::new(); for exec in &executions { let (input_cost_cents, output_cost_cents) = match exec.provider.as_str() { "claude" => (15, 45), // Claude pricing: $15 per 1M input, $45 per 1M output "gpt-4" => (30, 60), // GPT-4 pricing: $30 per 1M input, $60 per 1M output _ => (0, 0), }; let provider_cost = costs_by_provider .entry(exec.provider.clone()) .or_insert((0, 0)); provider_cost.0 += (exec.input_tokens * input_cost_cents) / 1_000_000; provider_cost.1 += (exec.output_tokens * output_cost_cents) / 1_000_000; } for (provider, (input_cost, output_cost)) in costs_by_provider { let total = input_cost + output_cost; println!( " {}: ${:.4} (input: ${:.4}, output: ${:.4})", provider, total as f64 / 10000.0, input_cost as f64 / 10000.0, output_cost as f64 / 10000.0 ); } }