1use crate::agents::custom_agent_config::{
6 CustomAgentConfigurationSystem, AgentPersonality, CodingStyle, RiskTolerance,
7 CommunicationStyle, PriorityWeights, ErrorHandlingStyle, FormattingPreferences,
8 IndentStyle, BraceStyle, UserAction, ProjectType
9};
10use crate::edit_control::ModifiableEdit;
11use std::io::{self, Write};
12use anyhow::Result;
13
14pub struct CustomAgentConfigCLI {
16 config_system: CustomAgentConfigurationSystem,
17 current_view: ConfigView,
18}
19
20#[derive(Debug, Clone)]
22pub enum ConfigView {
23 MainMenu,
24 PersonalityManagement,
25 PersonalityCreation,
26 PreferenceLearning,
27 ProjectConfiguration,
28 AgentTesting,
29}
30
31impl CustomAgentConfigCLI {
32 pub fn new() -> Result<Self> {
34 let config_dir = ".soma_config";
35 let mut config_system = CustomAgentConfigurationSystem::new(config_dir);
36 config_system.load_from_file()?;
37
38 Ok(Self {
39 config_system,
40 current_view: ConfigView::MainMenu,
41 })
42 }
43
44 pub fn start_interactive_session(&mut self) -> Result<()> {
46 self.print_welcome();
47
48 loop {
49 match &self.current_view {
50 ConfigView::MainMenu => {
51 if !self.handle_main_menu()? {
52 break;
53 }
54 }
55 ConfigView::PersonalityManagement => {
56 self.handle_personality_management()?;
57 }
58 ConfigView::PersonalityCreation => {
59 self.handle_personality_creation()?;
60 }
61 ConfigView::PreferenceLearning => {
62 self.handle_preference_learning()?;
63 }
64 ConfigView::ProjectConfiguration => {
65 self.handle_project_configuration()?;
66 }
67 ConfigView::AgentTesting => {
68 self.handle_agent_testing()?;
69 }
70 }
71 }
72
73 Ok(())
74 }
75
76 fn print_welcome(&self) {
77 println!("{}", "=".repeat(70));
78 println!("๐ค SOMA-CORE Custom Agent Configuration");
79 println!("{}", "=".repeat(70));
80 println!("Configure personalized AI agents for your development workflow!");
81 println!("Create custom personalities, set preferences, and optimize agent behavior.\n");
82 }
83
84 fn handle_main_menu(&mut self) -> Result<bool> {
85 println!("\n๐ Custom Agent Configuration - Main Menu");
86 println!("{}", "=".repeat(50));
87 println!(" [1] ๐ญ Personality Management");
88 println!(" [2] ๐ Preference Learning & Analytics");
89 println!(" [3] ๐๏ธ Project Configuration");
90 println!(" [4] ๐งช Agent Testing & Validation");
91 println!(" [5] ๐ View Current Configuration");
92 println!(" [6] ๐พ Save & Export Configuration");
93 println!(" [0] ๐ช Exit");
94
95 print!("\nSelect option (0-6): ");
96 io::stdout().flush()?;
97
98 let mut input = String::new();
99 io::stdin().read_line(&mut input)?;
100
101 match input.trim() {
102 "1" => {
103 self.current_view = ConfigView::PersonalityManagement;
104 Ok(true)
105 }
106 "2" => {
107 self.current_view = ConfigView::PreferenceLearning;
108 Ok(true)
109 }
110 "3" => {
111 self.current_view = ConfigView::ProjectConfiguration;
112 Ok(true)
113 }
114 "4" => {
115 self.current_view = ConfigView::AgentTesting;
116 Ok(true)
117 }
118 "5" => {
119 self.show_current_configuration()?;
120 Ok(true)
121 }
122 "6" => {
123 self.save_and_export_configuration()?;
124 Ok(true)
125 }
126 "0" => {
127 println!("\n๐ Configuration saved. Thank you for using SOMA-CORE!");
128 Ok(false)
129 }
130 _ => {
131 println!("โ Invalid option. Please try again.");
132 Ok(true)
133 }
134 }
135 }
136
137 fn handle_personality_management(&mut self) -> Result<()> {
138 println!("\n๐ญ Personality Management");
139 println!("{}", "=".repeat(30));
140
141 let personalities = self.config_system.get_personalities();
142
143 if personalities.is_empty() {
144 println!("No custom personalities found. Let's create your first one!");
145 self.current_view = ConfigView::PersonalityCreation;
146 return Ok(());
147 }
148
149 println!("Available personalities:");
150 let mut personality_list: Vec<_> = personalities.iter().collect();
151 personality_list.sort_by_key(|(name, _)| *name);
152
153 for (i, (_name, personality)) in personality_list.iter().enumerate() {
154 println!(" [{}] {} - {}", i + 1, personality.name, personality.description);
155 }
156
157 println!("\nOptions:");
158 println!(" [c] Create new personality");
159 println!(" [s] Set active personality");
160 println!(" [b] Back to main menu");
161
162 print!("\nYour choice: ");
163 io::stdout().flush()?;
164
165 let mut input = String::new();
166 io::stdin().read_line(&mut input)?;
167
168 match input.trim().to_lowercase().as_str() {
169 "c" => {
170 self.current_view = ConfigView::PersonalityCreation;
171 }
172 "s" => {
173 self.set_active_personality()?;
174 }
175 "b" => {
176 self.current_view = ConfigView::MainMenu;
177 }
178 _ => {
179 println!("โ Invalid option. Please try again.");
180 }
181 }
182
183 Ok(())
184 }
185
186 fn handle_personality_creation(&mut self) -> Result<()> {
187 println!("\n๐จ Create New Agent Personality");
188 println!("{}", "=".repeat(35));
189
190 print!("Enter personality name: ");
192 io::stdout().flush()?;
193 let mut name = String::new();
194 io::stdin().read_line(&mut name)?;
195 let name = name.trim().to_string();
196
197 if name.is_empty() {
198 println!("โ Name cannot be empty. Returning to personality management.");
199 self.current_view = ConfigView::PersonalityManagement;
200 return Ok(());
201 }
202
203 print!("Enter description: ");
204 io::stdout().flush()?;
205 let mut description = String::new();
206 io::stdin().read_line(&mut description)?;
207 let description = description.trim().to_string();
208
209 println!("\nSelect focus areas (comma-separated):");
211 println!(" performance, readability, security, testing, documentation, architecture");
212 print!("Focus areas: ");
213 io::stdout().flush()?;
214 let mut focus_input = String::new();
215 io::stdin().read_line(&mut focus_input)?;
216 let focus_areas: Vec<String> = focus_input
217 .trim()
218 .split(',')
219 .map(|s| s.trim().to_string())
220 .filter(|s| !s.is_empty())
221 .collect();
222
223 println!("\nSelect risk tolerance:");
225 println!(" [1] Conservative - Only safe, well-tested changes");
226 println!(" [2] Moderate - Balance between safety and innovation");
227 println!(" [3] Aggressive - Bold improvements even if risky");
228 println!(" [4] Adaptive - Adjust based on project context");
229 print!("Risk tolerance (1-4): ");
230 io::stdout().flush()?;
231 let mut risk_input = String::new();
232 io::stdin().read_line(&mut risk_input)?;
233
234 let risk_tolerance = match risk_input.trim() {
235 "1" => RiskTolerance::Conservative,
236 "2" => RiskTolerance::Moderate,
237 "3" => RiskTolerance::Aggressive,
238 "4" => RiskTolerance::Adaptive,
239 _ => RiskTolerance::Moderate,
240 };
241
242 println!("\nSelect communication style:");
244 println!(" [1] Concise - Brief, to-the-point explanations");
245 println!(" [2] Detailed - Comprehensive explanations with examples");
246 println!(" [3] Tutorial - Educational style with learning focus");
247 println!(" [4] Professional - Formal, business-oriented tone");
248 println!(" [5] Friendly - Casual, approachable tone");
249 print!("Communication style (1-5): ");
250 io::stdout().flush()?;
251 let mut comm_input = String::new();
252 io::stdin().read_line(&mut comm_input)?;
253
254 let communication_style = match comm_input.trim() {
255 "1" => CommunicationStyle::Concise,
256 "2" => CommunicationStyle::Detailed,
257 "3" => CommunicationStyle::Tutorial,
258 "4" => CommunicationStyle::Professional,
259 "5" => CommunicationStyle::Friendly,
260 _ => CommunicationStyle::Professional,
261 };
262
263 let priority_weights = self.configure_priority_weights()?;
265
266 let coding_style = self.configure_coding_style()?;
268
269 let personality = AgentPersonality {
271 name: name.clone(),
272 description,
273 focus_areas,
274 coding_style,
275 risk_tolerance,
276 communication_style,
277 priority_weights,
278 };
279
280 self.config_system.add_personality(name.clone(), personality);
281 self.config_system.save_to_file()?;
282
283 println!("\nโ
Personality '{}' created successfully!", name);
284 println!("You can now test it or set it as active.");
285
286 self.current_view = ConfigView::PersonalityManagement;
287 Ok(())
288 }
289
290 fn configure_priority_weights(&self) -> Result<PriorityWeights> {
291 println!("\nโ๏ธ Configure Priority Weights (0.0 to 1.0, total should sum to 1.0):");
292
293 let mut weights = PriorityWeights::default();
294
295 print!("Performance weight [{}]: ", weights.performance);
296 io::stdout().flush()?;
297 let mut input = String::new();
298 io::stdin().read_line(&mut input)?;
299 if let Ok(val) = input.trim().parse::<f64>() {
300 weights.performance = val.clamp(0.0, 1.0);
301 }
302
303 print!("Readability weight [{}]: ", weights.readability);
304 io::stdout().flush()?;
305 input.clear();
306 io::stdin().read_line(&mut input)?;
307 if let Ok(val) = input.trim().parse::<f64>() {
308 weights.readability = val.clamp(0.0, 1.0);
309 }
310
311 print!("Maintainability weight [{}]: ", weights.maintainability);
312 io::stdout().flush()?;
313 input.clear();
314 io::stdin().read_line(&mut input)?;
315 if let Ok(val) = input.trim().parse::<f64>() {
316 weights.maintainability = val.clamp(0.0, 1.0);
317 }
318
319 print!("Security weight [{}]: ", weights.security);
320 io::stdout().flush()?;
321 input.clear();
322 io::stdin().read_line(&mut input)?;
323 if let Ok(val) = input.trim().parse::<f64>() {
324 weights.security = val.clamp(0.0, 1.0);
325 }
326
327 print!("Testing weight [{}]: ", weights.testing);
328 io::stdout().flush()?;
329 input.clear();
330 io::stdin().read_line(&mut input)?;
331 if let Ok(val) = input.trim().parse::<f64>() {
332 weights.testing = val.clamp(0.0, 1.0);
333 }
334
335 print!("Documentation weight [{}]: ", weights.documentation);
336 io::stdout().flush()?;
337 input.clear();
338 io::stdin().read_line(&mut input)?;
339 if let Ok(val) = input.trim().parse::<f64>() {
340 weights.documentation = val.clamp(0.0, 1.0);
341 }
342
343 let total = weights.performance + weights.readability + weights.maintainability
345 + weights.security + weights.testing + weights.documentation;
346
347 if total > 0.0 {
348 weights.performance /= total;
349 weights.readability /= total;
350 weights.maintainability /= total;
351 weights.security /= total;
352 weights.testing /= total;
353 weights.documentation /= total;
354 }
355
356 println!("โ
Weights normalized. Total: 1.0");
357 Ok(weights)
358 }
359
360 fn configure_coding_style(&self) -> Result<CodingStyle> {
361 println!("\n๐จ Configure Coding Style Preferences:");
362
363 print!("Prefer verbose comments? (y/n) [y]: ");
365 io::stdout().flush()?;
366 let mut input = String::new();
367 io::stdin().read_line(&mut input)?;
368 let prefers_verbose_comments = !matches!(input.trim().to_lowercase().as_str(), "n" | "no");
369
370 print!("Prefer short functions? (y/n) [y]: ");
372 io::stdout().flush()?;
373 input.clear();
374 io::stdin().read_line(&mut input)?;
375 let prefers_short_functions = !matches!(input.trim().to_lowercase().as_str(), "n" | "no");
376
377 print!("Prefer explicit types? (y/n) [y]: ");
379 io::stdout().flush()?;
380 input.clear();
381 io::stdin().read_line(&mut input)?;
382 let prefers_explicit_types = !matches!(input.trim().to_lowercase().as_str(), "n" | "no");
383
384 println!("Error handling style:");
386 println!(" [1] Explicit - Always use Result<T, E>");
387 println!(" [2] Panic - Use unwrap() and expect()");
388 println!(" [3] Optional - Use Option<T> where possible");
389 println!(" [4] Hybrid - Mix based on context");
390 print!("Choice (1-4) [1]: ");
391 io::stdout().flush()?;
392 input.clear();
393 io::stdin().read_line(&mut input)?;
394
395 let prefers_error_handling = match input.trim() {
396 "2" => ErrorHandlingStyle::Panic,
397 "3" => ErrorHandlingStyle::Optional,
398 "4" => ErrorHandlingStyle::Hybrid,
399 _ => ErrorHandlingStyle::Explicit,
400 };
401
402 print!("Maximum line length [100]: ");
404 io::stdout().flush()?;
405 input.clear();
406 io::stdin().read_line(&mut input)?;
407 let max_line_length = input.trim().parse().unwrap_or(100);
408
409 print!("Prefer single-line blocks? (y/n) [n]: ");
410 io::stdout().flush()?;
411 input.clear();
412 io::stdin().read_line(&mut input)?;
413 let prefer_single_line_blocks = matches!(input.trim().to_lowercase().as_str(), "y" | "yes");
414
415 let formatting_preferences = FormattingPreferences {
416 max_line_length,
417 prefer_single_line_blocks,
418 indent_style: IndentStyle::Spaces(4),
419 brace_style: BraceStyle::SameLine,
420 };
421
422 Ok(CodingStyle {
423 prefers_verbose_comments,
424 prefers_short_functions,
425 prefers_explicit_types,
426 prefers_error_handling,
427 formatting_preferences,
428 })
429 }
430
431 fn handle_preference_learning(&mut self) -> Result<()> {
432 println!("\n๐ Preference Learning & Analytics");
433 println!("{}", "=".repeat(35));
434 println!("This feature tracks your interactions with agent suggestions");
435 println!("to continuously improve agent behavior and recommendations.");
436
437 println!("\n๐ Learning Statistics:");
439 println!(" โข Total interactions: 0 (new system)");
440 println!(" โข Acceptance rate: N/A");
441 println!(" โข Most preferred suggestion types: Learning...");
442 println!(" โข Confidence improvement: Baseline");
443
444 println!("\n๐ง Learning Configuration:");
445 println!(" [1] Reset learning data");
446 println!(" [2] Export learning insights");
447 println!(" [3] Configure learning sensitivity");
448 println!(" [b] Back to main menu");
449
450 print!("Your choice: ");
451 io::stdout().flush()?;
452
453 let mut input = String::new();
454 io::stdin().read_line(&mut input)?;
455
456 match input.trim() {
457 "1" => println!("๐ Learning data reset (feature coming soon)"),
458 "2" => println!("๐ค Export insights (feature coming soon)"),
459 "3" => println!("โ๏ธ Configure sensitivity (feature coming soon)"),
460 "b" => self.current_view = ConfigView::MainMenu,
461 _ => println!("โ Invalid option"),
462 }
463
464 Ok(())
465 }
466
467 fn handle_project_configuration(&mut self) -> Result<()> {
468 println!("\n๐๏ธ Project Configuration");
469 println!("{}", "=".repeat(25));
470 println!("Configure agent behavior for specific projects and contexts.");
471
472 println!("\nProject-specific settings:");
473 println!(" [1] Set project type and constraints");
474 println!(" [2] Configure team preferences");
475 println!(" [3] Set coding standards and guidelines");
476 println!(" [4] Configure review requirements");
477 println!(" [b] Back to main menu");
478
479 print!("Your choice: ");
480 io::stdout().flush()?;
481
482 let mut input = String::new();
483 io::stdin().read_line(&mut input)?;
484
485 match input.trim() {
486 "1" => self.configure_project_type()?,
487 "2" => println!("๐ฅ Team preferences (feature coming soon)"),
488 "3" => println!("๐ Coding standards (feature coming soon)"),
489 "4" => println!("๐ Review requirements (feature coming soon)"),
490 "b" => self.current_view = ConfigView::MainMenu,
491 _ => println!("โ Invalid option"),
492 }
493
494 Ok(())
495 }
496
497 fn configure_project_type(&self) -> Result<()> {
498 println!("\n๐ฏ Project Type Configuration");
499 println!("Select your project type:");
500 println!(" [1] Web Application");
501 println!(" [2] Library/Framework");
502 println!(" [3] System Tool/CLI");
503 println!(" [4] Game Development");
504 println!(" [5] Mobile Application");
505 println!(" [6] Data Science/Analytics");
506 println!(" [7] Machine Learning/AI");
507 println!(" [8] Embedded Systems");
508 println!(" [9] Other");
509
510 print!("Project type (1-9): ");
511 io::stdout().flush()?;
512
513 let mut input = String::new();
514 io::stdin().read_line(&mut input)?;
515
516 let project_type = match input.trim() {
517 "1" => ProjectType::WebApplication,
518 "2" => ProjectType::Library,
519 "3" => ProjectType::SystemTool,
520 "4" => ProjectType::Game,
521 "5" => ProjectType::Mobile,
522 "6" => ProjectType::DataScience,
523 "7" => ProjectType::MachineLearning,
524 "8" => ProjectType::Embedded,
525 "9" => {
526 print!("Enter custom project type: ");
527 io::stdout().flush()?;
528 let mut custom = String::new();
529 io::stdin().read_line(&mut custom)?;
530 ProjectType::Other(custom.trim().to_string())
531 }
532 _ => ProjectType::Library,
533 };
534
535 println!("โ
Project type set to: {:?}", project_type);
536 Ok(())
537 }
538
539 fn handle_agent_testing(&mut self) -> Result<()> {
540 println!("\n๐งช Agent Testing & Validation");
541 println!("{}", "=".repeat(30));
542 println!("Test your configured agents with sample scenarios.");
543
544 let personalities = self.config_system.get_personalities();
545 if personalities.is_empty() {
546 println!("โ No personalities available for testing.");
547 println!("Create a personality first in the Personality Management section.");
548 self.current_view = ConfigView::MainMenu;
549 return Ok(());
550 }
551
552 println!("\nAvailable test scenarios:");
553 println!(" [1] Performance optimization scenario");
554 println!(" [2] Code readability improvement");
555 println!(" [3] Security vulnerability assessment");
556 println!(" [4] Custom test scenario");
557 println!(" [b] Back to main menu");
558
559 print!("Select test (1-4, b): ");
560 io::stdout().flush()?;
561
562 let mut input = String::new();
563 io::stdin().read_line(&mut input)?;
564
565 match input.trim() {
566 "1" => self.run_performance_test()?,
567 "2" => self.run_readability_test()?,
568 "3" => self.run_security_test()?,
569 "4" => self.run_custom_test()?,
570 "b" => self.current_view = ConfigView::MainMenu,
571 _ => println!("โ Invalid option"),
572 }
573
574 Ok(())
575 }
576
577 fn run_performance_test(&self) -> Result<()> {
578 println!("\nโก Performance Optimization Test");
579 println!("Testing agent response to performance optimization scenarios...");
580
581 println!("โ
Test completed! Agent suggestions would appear here.");
583 println!("In a full implementation, this would show:");
584 println!(" โข Agent's suggested optimizations");
585 println!(" โข Confidence scores");
586 println!(" โข Reasoning and explanations");
587 println!(" โข Performance impact estimates");
588
589 Ok(())
590 }
591
592 fn run_readability_test(&self) -> Result<()> {
593 println!("\n๐ Readability Improvement Test");
594 println!("Testing agent response to code clarity scenarios...");
595 println!("โ
Test completed! Readability suggestions would appear here.");
596 Ok(())
597 }
598
599 fn run_security_test(&self) -> Result<()> {
600 println!("\n๐ Security Assessment Test");
601 println!("Testing agent response to security scenarios...");
602 println!("โ
Test completed! Security recommendations would appear here.");
603 Ok(())
604 }
605
606 fn run_custom_test(&self) -> Result<()> {
607 println!("\n๐ฏ Custom Test Scenario");
608 print!("Enter your test scenario description: ");
609 io::stdout().flush()?;
610
611 let mut scenario = String::new();
612 io::stdin().read_line(&mut scenario)?;
613
614 println!("โ
Custom test '{}' completed!", scenario.trim());
615 println!("Agent response would be generated based on configured personality.");
616 Ok(())
617 }
618
619 fn set_active_personality(&mut self) -> Result<()> {
620 let personalities = self.config_system.get_personalities();
621 let personality_list: Vec<_> = personalities.keys().collect();
622
623 if personality_list.is_empty() {
624 println!("No personalities available.");
625 return Ok(());
626 }
627
628 println!("Select active personality:");
629 for (i, name) in personality_list.iter().enumerate() {
630 println!(" [{}] {}", i + 1, name);
631 }
632
633 print!("Enter number: ");
634 io::stdout().flush()?;
635
636 let mut input = String::new();
637 io::stdin().read_line(&mut input)?;
638
639 if let Ok(index) = input.trim().parse::<usize>() {
640 if index > 0 && index <= personality_list.len() {
641 let selected = personality_list[index - 1].clone();
642 self.config_system.set_active_configuration(selected.clone());
643 self.config_system.save_to_file()?;
644 println!("โ
Active personality set to: {}", selected);
645 } else {
646 println!("โ Invalid selection.");
647 }
648 } else {
649 println!("โ Invalid input.");
650 }
651
652 Ok(())
653 }
654
655 fn show_current_configuration(&self) -> Result<()> {
656 println!("\n๐ Current Configuration");
657 println!("{}", "=".repeat(25));
658
659 if let Some(active) = self.config_system.get_active_configuration() {
660 println!("๐ฏ Active Personality: {}", active);
661
662 if let Some(personality) = self.config_system.get_personalities().get(active) {
663 println!(" Description: {}", personality.description);
664 println!(" Focus Areas: {}", personality.focus_areas.join(", "));
665 println!(" Risk Tolerance: {:?}", personality.risk_tolerance);
666 println!(" Communication: {:?}", personality.communication_style);
667
668 println!("\nโ๏ธ Priority Weights:");
669 println!(" Performance: {:.2}", personality.priority_weights.performance);
670 println!(" Readability: {:.2}", personality.priority_weights.readability);
671 println!(" Maintainability: {:.2}", personality.priority_weights.maintainability);
672 println!(" Security: {:.2}", personality.priority_weights.security);
673 println!(" Testing: {:.2}", personality.priority_weights.testing);
674 println!(" Documentation: {:.2}", personality.priority_weights.documentation);
675 }
676 } else {
677 println!("โ No active personality set.");
678 }
679
680 let total_personalities = self.config_system.get_personalities().len();
681 println!("\n๐ Statistics:");
682 println!(" Total Personalities: {}", total_personalities);
683 println!(" Learning Data: Available");
684 println!(" Configuration Status: โ
Loaded");
685
686 Ok(())
687 }
688
689 fn save_and_export_configuration(&mut self) -> Result<()> {
690 println!("\n๐พ Save & Export Configuration");
691 println!("{}", "=".repeat(30));
692
693 self.config_system.save_to_file()?;
695 println!("โ
Configuration saved successfully!");
696
697 println!("\nExport options:");
698 println!(" [1] Export to JSON file");
699 println!(" [2] Export personality summary");
700 println!(" [3] Export learning data");
701 println!(" [b] Back to main menu");
702
703 print!("Your choice: ");
704 io::stdout().flush()?;
705
706 let mut input = String::new();
707 io::stdin().read_line(&mut input)?;
708
709 match input.trim() {
710 "1" => println!("๐ JSON export (feature coming soon)"),
711 "2" => println!("๐ Personality summary export (feature coming soon)"),
712 "3" => println!("๐ Learning data export (feature coming soon)"),
713 "b" => {},
714 _ => println!("โ Invalid option"),
715 }
716
717 Ok(())
718 }
719
720 pub fn record_interaction(&mut self, edit: &ModifiableEdit, action: UserAction) -> Result<()> {
722 self.config_system.record_user_interaction(
723 edit.base_edit.reason.clone(),
724 format!("File: {}, Lines: {}-{}",
725 edit.base_edit.file,
726 edit.base_edit.line_range.0,
727 edit.base_edit.line_range.1),
728 edit.base_edit.confidence,
729 action,
730 "current_project".to_string(),
731 );
732
733 self.config_system.save_to_file()?;
734 Ok(())
735 }
736}
737
738pub fn quick_agent_config() -> Result<()> {
740 let mut cli = CustomAgentConfigCLI::new()?;
741 cli.start_interactive_session()
742}