rust_analysis/
rust_analysis.rs1use 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 env_logger::init();
14
15 let config = Config::default();
17 let mut code_agent = CodeAgent::new(config).await?;
18
19 println!("š¦ Starting Rust Code Analysis...");
21 let conversation_id = code_agent.start_conversation("llama3.2");
22 println!("Code Agent Conversation ID: {}", conversation_id);
23
24 let role = Role::new(
26 "Rust Code Analysis Assistant",
27 "You are an expert at analyzing Rust code, providing insights on code quality, safety, and potential improvements.",
28 )
29 .with_audience(Audience::new(
30 "Rust Developer",
31 "You are speaking to a Rust 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 let rust_code = r#"
40use std::collections::HashMap;
41use std::error::Error;
42
43#[derive(Debug)]
44struct DataProcessor {
45 data: Vec<i32>,
46 cache: HashMap<String, i32>,
47}
48
49impl DataProcessor {
50 fn new(data: Vec<i32>) -> Self {
51 Self {
52 data,
53 cache: HashMap::new(),
54 }
55 }
56
57 fn calculate_sum(&self) -> i32 {
58 self.data.iter().sum()
59 }
60
61 fn calculate_average(&self) -> Option<f64> {
62 if self.data.is_empty() {
63 None
64 } else {
65 Some(self.calculate_sum() as f64 / self.data.len() as f64)
66 }
67 }
68
69 fn find_max(&self) -> Option<&i32> {
70 self.data.iter().max()
71 }
72
73 fn process_with_cache(&mut self, key: String) -> Result<i32, Box<dyn Error>> {
74 if let Some(&cached_value) = self.cache.get(&key) {
75 return Ok(cached_value);
76 }
77
78 let result = self.calculate_sum();
79 self.cache.insert(key, result);
80 Ok(result)
81 }
82}
83
84fn main() {
85 let numbers = vec![10, 20, 30, 40, 50];
86 let mut processor = DataProcessor::new(numbers);
87
88 println!("Sum: {}", processor.calculate_sum());
89
90 match processor.calculate_average() {
91 Some(avg) => println!("Average: {}", avg),
92 None => println!("No data to calculate average"),
93 }
94
95 match processor.find_max() {
96 Some(max) => println!("Maximum: {}", max),
97 None => println!("No data to find maximum"),
98 }
99
100 match processor.process_with_cache("sum".to_string()) {
101 Ok(result) => println!("Cached result: {}", result),
102 Err(e) => println!("Error: {}", e),
103 }
104}
105"#;
106
107 println!("\nš Rust Code to Analyze:");
108 println!("{}", rust_code);
109
110 let analysis_result = code_agent.analyze_rust(rust_code).await?;
112
113 println!("\nš Rust Analysis Results:");
114 println!("Language: {}", analysis_result.language);
115 println!(
116 "Metrics: {}",
117 serde_json::to_string_pretty(&analysis_result.metrics)?
118 );
119 println!("Suggestions: {:?}", analysis_result.suggestions);
120 println!("Rust Issues: {:?}", analysis_result.issues);
121
122 let analysis_prompt = format!(
124 "Please analyze this Rust code and provide insights:\n\n{}\n\nAnalysis results:\nMetrics: {}\nSuggestions: {:?}\nRust Issues: {:?}",
125 rust_code,
126 serde_json::to_string_pretty(&analysis_result.metrics)?,
127 analysis_result.suggestions,
128 analysis_result.issues
129 );
130
131 let mut response = code_agent
132 .chat_with_history(&conversation_id, &analysis_prompt, Some(role))
133 .await?;
134
135 println!("\nš¤ AI Analysis:");
136
137 let mut buffer = String::new();
139 while let Some(chunk) = response.chunk().await? {
140 match code_agent
141 .process_stream_response(&conversation_id, &chunk)
142 .await
143 {
144 Ok(Some(message)) => {
145 if !message.content.is_empty() {
147 print!("{}", message.content);
148 io::stdout().flush()?;
149 buffer.push_str(&message.content);
150 }
151
152 if let Some(tool_calls) = &message.tool_calls {
154 for tool_call in tool_calls {
155 print!("\n[Tool Call] {}(", tool_call.function.name);
156 if let Some(obj) = tool_call.function.arguments.as_object() {
157 for (key, value) in obj {
158 print!("{}: {}, ", key, value);
159 }
160 }
161 println!(")");
162 io::stdout().flush()?;
163 }
164 }
165 }
166 Ok(None) => {
167 code_agent
168 .add_message(&conversation_id, "assistant", &buffer)
169 .await;
170 println!("\nā
Analysis complete!\n");
171 break;
172 }
173 Err(e) => {
174 eprintln!("\nā Error processing stream: {}", e);
175 break;
176 }
177 }
178 }
179
180 let follow_up = "What Rust-specific improvements would you recommend for this code?";
182 let mut follow_up_response = code_agent
183 .chat_with_history(&conversation_id, follow_up, None)
184 .await?;
185
186 println!("\nš Follow-up Analysis:");
187 let mut buffer = String::new();
188 while let Some(chunk) = follow_up_response.chunk().await? {
189 match code_agent
190 .process_stream_response(&conversation_id, &chunk)
191 .await
192 {
193 Ok(Some(message)) => {
194 if !message.content.is_empty() {
196 print!("{}", message.content);
197 io::stdout().flush()?;
198 buffer.push_str(&message.content);
199 }
200
201 if let Some(tool_calls) = &message.tool_calls {
203 for tool_call in tool_calls {
204 print!("\n[Tool Call] {}(", tool_call.function.name);
205 if let Some(obj) = tool_call.function.arguments.as_object() {
206 for (key, value) in obj {
207 print!("{}: {}, ", key, value);
208 }
209 }
210 println!(")");
211 io::stdout().flush()?;
212 }
213 }
214 }
215 Ok(None) => {
216 code_agent
217 .add_message(&conversation_id, "assistant", &buffer)
218 .await;
219 println!("\n");
220 break;
221 }
222 Err(e) => {
223 eprintln!("\nā Error processing stream: {}", e);
224 break;
225 }
226 }
227 }
228
229 Ok(())
230}