python_analysis/
python_analysis.rs

1use env_logger;
2use kowalski_code_agent::agent::CodeAgent;
3use kowalski_core::{
4    agent::Agent,
5    config::Config,
6    role::{Audience, Preset, Role},
7};
8use std::io::{self, Write};
9
10#[tokio::main]
11async fn main() -> Result<(), Box<dyn std::error::Error>> {
12    // Initialize logging
13    env_logger::init();
14
15    // Load configuration
16    let config = Config::default();
17    let mut code_agent = CodeAgent::new(config).await?;
18
19    // Start a conversation
20    println!("šŸ Starting Python Code Analysis...");
21    let conversation_id = code_agent.start_conversation("llama3.2");
22    println!("Code Agent Conversation ID: {}", conversation_id);
23
24    // Set up the role for code analysis
25    let role = Role::new(
26        "Python Code Analysis Assistant",
27        "You are an expert at analyzing Python code, providing insights on code quality, PEP 8 compliance, and potential improvements.",
28    )
29    .with_audience(Audience::new(
30        "Python Developer",
31        "You are speaking to a Python developer who needs detailed code analysis.",
32    ))
33    .with_preset(Preset::new(
34        "Analysis",
35        "Provide comprehensive analysis with specific recommendations for improvement.",
36    ));
37
38    // Sample Python code for analysis
39    let python_code = r#"
40import os
41import sys
42from typing import List, Optional
43
44class DataProcessor:
45    def __init__(self, data: List[int]):
46        self.data = data
47        self.result = 0
48    
49    def calculate_sum(self) -> int:
50        """Calculate the sum of all data points."""
51        total = 0
52        for item in self.data:
53            total += item
54        return total
55    
56    def calculate_average(self) -> float:
57        """Calculate the average of all data points."""
58        if len(self.data) == 0:
59            print("Error: No data to calculate average")
60            return 0.0
61        return self.calculate_sum() / len(self.data)
62    
63    def find_max(self) -> Optional[int]:
64        """Find the maximum value in the data."""
65        if not self.data:
66            return None
67        max_val = self.data[0]
68        for item in self.data:
69            if item > max_val:
70                max_val = item
71        return max_val
72
73def main():
74    # Sample data
75    numbers = [10, 20, 30, 40, 50]
76    
77    # Create processor
78    processor = DataProcessor(numbers)
79    
80    # Calculate statistics
81    print(f"Sum: {processor.calculate_sum()}")
82    print(f"Average: {processor.calculate_average()}")
83    print(f"Maximum: {processor.find_max()}")
84    
85    # Process empty data
86    empty_processor = DataProcessor([])
87    print(f"Empty average: {empty_processor.calculate_average()}")
88
89if __name__ == "__main__":
90    main()
91"#;
92
93    println!("\nšŸ“ Python Code to Analyze:");
94    println!("{}", python_code);
95
96    // Analyze the Python code
97    let analysis_result = code_agent.analyze_python(python_code).await?;
98
99    println!("\nšŸ“Š Python Analysis Results:");
100    println!("Language: {}", analysis_result.language);
101    println!(
102        "Metrics: {}",
103        serde_json::to_string_pretty(&analysis_result.metrics)?
104    );
105    println!("Suggestions: {:?}", analysis_result.suggestions);
106    println!("PEP 8 Issues: {:?}", analysis_result.issues);
107
108    // Ask the agent to analyze the code
109    let analysis_prompt = format!(
110        "Please analyze this Python code and provide insights:\n\n{}\n\nAnalysis results:\nMetrics: {}\nSuggestions: {:?}\nPEP 8 Issues: {:?}",
111        python_code,
112        serde_json::to_string_pretty(&analysis_result.metrics)?,
113        analysis_result.suggestions,
114        analysis_result.issues
115    );
116
117    let mut response = code_agent
118        .chat_with_history(&conversation_id, &analysis_prompt, Some(role))
119        .await?;
120
121    println!("\nšŸ¤– AI Analysis:");
122
123    // Process the streaming response
124    let mut buffer = String::new();
125    while let Some(chunk) = response.chunk().await? {
126        match code_agent
127            .process_stream_response(&conversation_id, &chunk)
128            .await
129        {
130            Ok(Some(message)) => {
131                // Print the content if it exists
132                if !message.content.is_empty() {
133                    print!("{}", message.content);
134                    io::stdout().flush()?;
135                    buffer.push_str(&message.content);
136                }
137
138                // Handle tool calls if they exist
139                if let Some(tool_calls) = &message.tool_calls {
140                    for tool_call in tool_calls {
141                        print!("\n[Tool Call] {}(", tool_call.function.name);
142                        if let Some(obj) = tool_call.function.arguments.as_object() {
143                            for (key, value) in obj {
144                                print!("{}: {}, ", key, value);
145                            }
146                        }
147                        println!(")");
148                        io::stdout().flush()?;
149                    }
150                }
151            }
152            Ok(None) => {
153                code_agent
154                    .add_message(&conversation_id, "assistant", &buffer)
155                    .await;
156                println!("\nāœ… Analysis complete!\n");
157                break;
158            }
159            Err(e) => {
160                eprintln!("\nāŒ Error processing stream: {}", e);
161                break;
162            }
163        }
164    }
165
166    // Ask a follow-up question about PEP 8 compliance
167    let follow_up = "How can this Python code be improved to better follow PEP 8 guidelines?";
168    let mut follow_up_response = code_agent
169        .chat_with_history(&conversation_id, follow_up, None)
170        .await?;
171
172    println!("\nšŸ” Follow-up Analysis:");
173    let mut buffer = String::new();
174    while let Some(chunk) = follow_up_response.chunk().await? {
175        match code_agent
176            .process_stream_response(&conversation_id, &chunk)
177            .await
178        {
179            Ok(Some(message)) => {
180                // Print the content if it exists
181                if !message.content.is_empty() {
182                    print!("{}", message.content);
183                    io::stdout().flush()?;
184                    buffer.push_str(&message.content);
185                }
186
187                // Handle tool calls if they exist
188                if let Some(tool_calls) = &message.tool_calls {
189                    for tool_call in tool_calls {
190                        print!("\n[Tool Call] {}(", tool_call.function.name);
191                        if let Some(obj) = tool_call.function.arguments.as_object() {
192                            for (key, value) in obj {
193                                print!("{}: {}, ", key, value);
194                            }
195                        }
196                        println!(")");
197                        io::stdout().flush()?;
198                    }
199                }
200            }
201            Ok(None) => {
202                code_agent
203                    .add_message(&conversation_id, "assistant", &buffer)
204                    .await;
205                println!("\n");
206                break;
207            }
208            Err(e) => {
209                eprintln!("\nāŒ Error processing stream: {}", e);
210                break;
211            }
212        }
213    }
214
215    Ok(())
216}