use crate::agents::custom_agent_config::{
CustomAgentConfigurationSystem, AgentPersonality, CodingStyle, RiskTolerance,
CommunicationStyle, PriorityWeights, ErrorHandlingStyle, FormattingPreferences,
IndentStyle, BraceStyle, UserAction, ProjectType
};
use crate::edit_control::ModifiableEdit;
use std::io::{self, Write};
use anyhow::Result;
pub struct CustomAgentConfigCLI {
config_system: CustomAgentConfigurationSystem,
current_view: ConfigView,
}
#[derive(Debug, Clone)]
pub enum ConfigView {
MainMenu,
PersonalityManagement,
PersonalityCreation,
PreferenceLearning,
ProjectConfiguration,
AgentTesting,
}
impl CustomAgentConfigCLI {
pub fn new() -> Result<Self> {
let config_dir = ".soma_config";
let mut config_system = CustomAgentConfigurationSystem::new(config_dir);
config_system.load_from_file()?;
Ok(Self {
config_system,
current_view: ConfigView::MainMenu,
})
}
pub fn start_interactive_session(&mut self) -> Result<()> {
self.print_welcome();
loop {
match &self.current_view {
ConfigView::MainMenu => {
if !self.handle_main_menu()? {
break;
}
}
ConfigView::PersonalityManagement => {
self.handle_personality_management()?;
}
ConfigView::PersonalityCreation => {
self.handle_personality_creation()?;
}
ConfigView::PreferenceLearning => {
self.handle_preference_learning()?;
}
ConfigView::ProjectConfiguration => {
self.handle_project_configuration()?;
}
ConfigView::AgentTesting => {
self.handle_agent_testing()?;
}
}
}
Ok(())
}
fn print_welcome(&self) {
println!("{}", "=".repeat(70));
println!("🤖 SOMA-CORE Custom Agent Configuration");
println!("{}", "=".repeat(70));
println!("Configure personalized AI agents for your development workflow!");
println!("Create custom personalities, set preferences, and optimize agent behavior.\n");
}
fn handle_main_menu(&mut self) -> Result<bool> {
println!("\n📋 Custom Agent Configuration - Main Menu");
println!("{}", "=".repeat(50));
println!(" [1] 🎭 Personality Management");
println!(" [2] 📊 Preference Learning & Analytics");
println!(" [3] 🏗️ Project Configuration");
println!(" [4] 🧪 Agent Testing & Validation");
println!(" [5] 📈 View Current Configuration");
println!(" [6] 💾 Save & Export Configuration");
println!(" [0] 🚪 Exit");
print!("\nSelect option (0-6): ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
match input.trim() {
"1" => {
self.current_view = ConfigView::PersonalityManagement;
Ok(true)
}
"2" => {
self.current_view = ConfigView::PreferenceLearning;
Ok(true)
}
"3" => {
self.current_view = ConfigView::ProjectConfiguration;
Ok(true)
}
"4" => {
self.current_view = ConfigView::AgentTesting;
Ok(true)
}
"5" => {
self.show_current_configuration()?;
Ok(true)
}
"6" => {
self.save_and_export_configuration()?;
Ok(true)
}
"0" => {
println!("\n👋 Configuration saved. Thank you for using SOMA-CORE!");
Ok(false)
}
_ => {
println!("❌ Invalid option. Please try again.");
Ok(true)
}
}
}
fn handle_personality_management(&mut self) -> Result<()> {
println!("\n🎭 Personality Management");
println!("{}", "=".repeat(30));
let personalities = self.config_system.get_personalities();
if personalities.is_empty() {
println!("No custom personalities found. Let's create your first one!");
self.current_view = ConfigView::PersonalityCreation;
return Ok(());
}
println!("Available personalities:");
let mut personality_list: Vec<_> = personalities.iter().collect();
personality_list.sort_by_key(|(name, _)| *name);
for (i, (_name, personality)) in personality_list.iter().enumerate() {
println!(" [{}] {} - {}", i + 1, personality.name, personality.description);
}
println!("\nOptions:");
println!(" [c] Create new personality");
println!(" [s] Set active personality");
println!(" [b] Back to main menu");
print!("\nYour choice: ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
match input.trim().to_lowercase().as_str() {
"c" => {
self.current_view = ConfigView::PersonalityCreation;
}
"s" => {
self.set_active_personality()?;
}
"b" => {
self.current_view = ConfigView::MainMenu;
}
_ => {
println!("❌ Invalid option. Please try again.");
}
}
Ok(())
}
fn handle_personality_creation(&mut self) -> Result<()> {
println!("\n🎨 Create New Agent Personality");
println!("{}", "=".repeat(35));
print!("Enter personality name: ");
io::stdout().flush()?;
let mut name = String::new();
io::stdin().read_line(&mut name)?;
let name = name.trim().to_string();
if name.is_empty() {
println!("❌ Name cannot be empty. Returning to personality management.");
self.current_view = ConfigView::PersonalityManagement;
return Ok(());
}
print!("Enter description: ");
io::stdout().flush()?;
let mut description = String::new();
io::stdin().read_line(&mut description)?;
let description = description.trim().to_string();
println!("\nSelect focus areas (comma-separated):");
println!(" performance, readability, security, testing, documentation, architecture");
print!("Focus areas: ");
io::stdout().flush()?;
let mut focus_input = String::new();
io::stdin().read_line(&mut focus_input)?;
let focus_areas: Vec<String> = focus_input
.trim()
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
println!("\nSelect risk tolerance:");
println!(" [1] Conservative - Only safe, well-tested changes");
println!(" [2] Moderate - Balance between safety and innovation");
println!(" [3] Aggressive - Bold improvements even if risky");
println!(" [4] Adaptive - Adjust based on project context");
print!("Risk tolerance (1-4): ");
io::stdout().flush()?;
let mut risk_input = String::new();
io::stdin().read_line(&mut risk_input)?;
let risk_tolerance = match risk_input.trim() {
"1" => RiskTolerance::Conservative,
"2" => RiskTolerance::Moderate,
"3" => RiskTolerance::Aggressive,
"4" => RiskTolerance::Adaptive,
_ => RiskTolerance::Moderate,
};
println!("\nSelect communication style:");
println!(" [1] Concise - Brief, to-the-point explanations");
println!(" [2] Detailed - Comprehensive explanations with examples");
println!(" [3] Tutorial - Educational style with learning focus");
println!(" [4] Professional - Formal, business-oriented tone");
println!(" [5] Friendly - Casual, approachable tone");
print!("Communication style (1-5): ");
io::stdout().flush()?;
let mut comm_input = String::new();
io::stdin().read_line(&mut comm_input)?;
let communication_style = match comm_input.trim() {
"1" => CommunicationStyle::Concise,
"2" => CommunicationStyle::Detailed,
"3" => CommunicationStyle::Tutorial,
"4" => CommunicationStyle::Professional,
"5" => CommunicationStyle::Friendly,
_ => CommunicationStyle::Professional,
};
let priority_weights = self.configure_priority_weights()?;
let coding_style = self.configure_coding_style()?;
let personality = AgentPersonality {
name: name.clone(),
description,
focus_areas,
coding_style,
risk_tolerance,
communication_style,
priority_weights,
};
self.config_system.add_personality(name.clone(), personality);
self.config_system.save_to_file()?;
println!("\n✅ Personality '{}' created successfully!", name);
println!("You can now test it or set it as active.");
self.current_view = ConfigView::PersonalityManagement;
Ok(())
}
fn configure_priority_weights(&self) -> Result<PriorityWeights> {
println!("\n⚖️ Configure Priority Weights (0.0 to 1.0, total should sum to 1.0):");
let mut weights = PriorityWeights::default();
print!("Performance weight [{}]: ", weights.performance);
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
if let Ok(val) = input.trim().parse::<f64>() {
weights.performance = val.clamp(0.0, 1.0);
}
print!("Readability weight [{}]: ", weights.readability);
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
if let Ok(val) = input.trim().parse::<f64>() {
weights.readability = val.clamp(0.0, 1.0);
}
print!("Maintainability weight [{}]: ", weights.maintainability);
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
if let Ok(val) = input.trim().parse::<f64>() {
weights.maintainability = val.clamp(0.0, 1.0);
}
print!("Security weight [{}]: ", weights.security);
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
if let Ok(val) = input.trim().parse::<f64>() {
weights.security = val.clamp(0.0, 1.0);
}
print!("Testing weight [{}]: ", weights.testing);
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
if let Ok(val) = input.trim().parse::<f64>() {
weights.testing = val.clamp(0.0, 1.0);
}
print!("Documentation weight [{}]: ", weights.documentation);
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
if let Ok(val) = input.trim().parse::<f64>() {
weights.documentation = val.clamp(0.0, 1.0);
}
let total = weights.performance + weights.readability + weights.maintainability
+ weights.security + weights.testing + weights.documentation;
if total > 0.0 {
weights.performance /= total;
weights.readability /= total;
weights.maintainability /= total;
weights.security /= total;
weights.testing /= total;
weights.documentation /= total;
}
println!("✅ Weights normalized. Total: 1.0");
Ok(weights)
}
fn configure_coding_style(&self) -> Result<CodingStyle> {
println!("\n🎨 Configure Coding Style Preferences:");
print!("Prefer verbose comments? (y/n) [y]: ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
let prefers_verbose_comments = !matches!(input.trim().to_lowercase().as_str(), "n" | "no");
print!("Prefer short functions? (y/n) [y]: ");
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
let prefers_short_functions = !matches!(input.trim().to_lowercase().as_str(), "n" | "no");
print!("Prefer explicit types? (y/n) [y]: ");
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
let prefers_explicit_types = !matches!(input.trim().to_lowercase().as_str(), "n" | "no");
println!("Error handling style:");
println!(" [1] Explicit - Always use Result<T, E>");
println!(" [2] Panic - Use unwrap() and expect()");
println!(" [3] Optional - Use Option<T> where possible");
println!(" [4] Hybrid - Mix based on context");
print!("Choice (1-4) [1]: ");
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
let prefers_error_handling = match input.trim() {
"2" => ErrorHandlingStyle::Panic,
"3" => ErrorHandlingStyle::Optional,
"4" => ErrorHandlingStyle::Hybrid,
_ => ErrorHandlingStyle::Explicit,
};
print!("Maximum line length [100]: ");
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
let max_line_length = input.trim().parse().unwrap_or(100);
print!("Prefer single-line blocks? (y/n) [n]: ");
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
let prefer_single_line_blocks = matches!(input.trim().to_lowercase().as_str(), "y" | "yes");
let formatting_preferences = FormattingPreferences {
max_line_length,
prefer_single_line_blocks,
indent_style: IndentStyle::Spaces(4),
brace_style: BraceStyle::SameLine,
};
Ok(CodingStyle {
prefers_verbose_comments,
prefers_short_functions,
prefers_explicit_types,
prefers_error_handling,
formatting_preferences,
})
}
fn handle_preference_learning(&mut self) -> Result<()> {
println!("\n📊 Preference Learning & Analytics");
println!("{}", "=".repeat(35));
println!("This feature tracks your interactions with agent suggestions");
println!("to continuously improve agent behavior and recommendations.");
println!("\n📈 Learning Statistics:");
println!(" • Total interactions: 0 (new system)");
println!(" • Acceptance rate: N/A");
println!(" • Most preferred suggestion types: Learning...");
println!(" • Confidence improvement: Baseline");
println!("\n🔧 Learning Configuration:");
println!(" [1] Reset learning data");
println!(" [2] Export learning insights");
println!(" [3] Configure learning sensitivity");
println!(" [b] Back to main menu");
print!("Your choice: ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
match input.trim() {
"1" => println!("🔄 Learning data reset (feature coming soon)"),
"2" => println!("📤 Export insights (feature coming soon)"),
"3" => println!("⚙️ Configure sensitivity (feature coming soon)"),
"b" => self.current_view = ConfigView::MainMenu,
_ => println!("❌ Invalid option"),
}
Ok(())
}
fn handle_project_configuration(&mut self) -> Result<()> {
println!("\n🏗️ Project Configuration");
println!("{}", "=".repeat(25));
println!("Configure agent behavior for specific projects and contexts.");
println!("\nProject-specific settings:");
println!(" [1] Set project type and constraints");
println!(" [2] Configure team preferences");
println!(" [3] Set coding standards and guidelines");
println!(" [4] Configure review requirements");
println!(" [b] Back to main menu");
print!("Your choice: ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
match input.trim() {
"1" => self.configure_project_type()?,
"2" => println!("👥 Team preferences (feature coming soon)"),
"3" => println!("📋 Coding standards (feature coming soon)"),
"4" => println!("🔍 Review requirements (feature coming soon)"),
"b" => self.current_view = ConfigView::MainMenu,
_ => println!("❌ Invalid option"),
}
Ok(())
}
fn configure_project_type(&self) -> Result<()> {
println!("\n🎯 Project Type Configuration");
println!("Select your project type:");
println!(" [1] Web Application");
println!(" [2] Library/Framework");
println!(" [3] System Tool/CLI");
println!(" [4] Game Development");
println!(" [5] Mobile Application");
println!(" [6] Data Science/Analytics");
println!(" [7] Machine Learning/AI");
println!(" [8] Embedded Systems");
println!(" [9] Other");
print!("Project type (1-9): ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
let project_type = match input.trim() {
"1" => ProjectType::WebApplication,
"2" => ProjectType::Library,
"3" => ProjectType::SystemTool,
"4" => ProjectType::Game,
"5" => ProjectType::Mobile,
"6" => ProjectType::DataScience,
"7" => ProjectType::MachineLearning,
"8" => ProjectType::Embedded,
"9" => {
print!("Enter custom project type: ");
io::stdout().flush()?;
let mut custom = String::new();
io::stdin().read_line(&mut custom)?;
ProjectType::Other(custom.trim().to_string())
}
_ => ProjectType::Library,
};
println!("✅ Project type set to: {:?}", project_type);
Ok(())
}
fn handle_agent_testing(&mut self) -> Result<()> {
println!("\n🧪 Agent Testing & Validation");
println!("{}", "=".repeat(30));
println!("Test your configured agents with sample scenarios.");
let personalities = self.config_system.get_personalities();
if personalities.is_empty() {
println!("❌ No personalities available for testing.");
println!("Create a personality first in the Personality Management section.");
self.current_view = ConfigView::MainMenu;
return Ok(());
}
println!("\nAvailable test scenarios:");
println!(" [1] Performance optimization scenario");
println!(" [2] Code readability improvement");
println!(" [3] Security vulnerability assessment");
println!(" [4] Custom test scenario");
println!(" [b] Back to main menu");
print!("Select test (1-4, b): ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
match input.trim() {
"1" => self.run_performance_test()?,
"2" => self.run_readability_test()?,
"3" => self.run_security_test()?,
"4" => self.run_custom_test()?,
"b" => self.current_view = ConfigView::MainMenu,
_ => println!("❌ Invalid option"),
}
Ok(())
}
fn run_performance_test(&self) -> Result<()> {
println!("\n⚡ Performance Optimization Test");
println!("Testing agent response to performance optimization scenarios...");
println!("✅ Test completed! Agent suggestions would appear here.");
println!("In a full implementation, this would show:");
println!(" • Agent's suggested optimizations");
println!(" • Confidence scores");
println!(" • Reasoning and explanations");
println!(" • Performance impact estimates");
Ok(())
}
fn run_readability_test(&self) -> Result<()> {
println!("\n📖 Readability Improvement Test");
println!("Testing agent response to code clarity scenarios...");
println!("✅ Test completed! Readability suggestions would appear here.");
Ok(())
}
fn run_security_test(&self) -> Result<()> {
println!("\n🔒 Security Assessment Test");
println!("Testing agent response to security scenarios...");
println!("✅ Test completed! Security recommendations would appear here.");
Ok(())
}
fn run_custom_test(&self) -> Result<()> {
println!("\n🎯 Custom Test Scenario");
print!("Enter your test scenario description: ");
io::stdout().flush()?;
let mut scenario = String::new();
io::stdin().read_line(&mut scenario)?;
println!("✅ Custom test '{}' completed!", scenario.trim());
println!("Agent response would be generated based on configured personality.");
Ok(())
}
fn set_active_personality(&mut self) -> Result<()> {
let personalities = self.config_system.get_personalities();
let personality_list: Vec<_> = personalities.keys().collect();
if personality_list.is_empty() {
println!("No personalities available.");
return Ok(());
}
println!("Select active personality:");
for (i, name) in personality_list.iter().enumerate() {
println!(" [{}] {}", i + 1, name);
}
print!("Enter number: ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
if let Ok(index) = input.trim().parse::<usize>() {
if index > 0 && index <= personality_list.len() {
let selected = personality_list[index - 1].clone();
self.config_system.set_active_configuration(selected.clone());
self.config_system.save_to_file()?;
println!("✅ Active personality set to: {}", selected);
} else {
println!("❌ Invalid selection.");
}
} else {
println!("❌ Invalid input.");
}
Ok(())
}
fn show_current_configuration(&self) -> Result<()> {
println!("\n📋 Current Configuration");
println!("{}", "=".repeat(25));
if let Some(active) = self.config_system.get_active_configuration() {
println!("🎯 Active Personality: {}", active);
if let Some(personality) = self.config_system.get_personalities().get(active) {
println!(" Description: {}", personality.description);
println!(" Focus Areas: {}", personality.focus_areas.join(", "));
println!(" Risk Tolerance: {:?}", personality.risk_tolerance);
println!(" Communication: {:?}", personality.communication_style);
println!("\n⚖️ Priority Weights:");
println!(" Performance: {:.2}", personality.priority_weights.performance);
println!(" Readability: {:.2}", personality.priority_weights.readability);
println!(" Maintainability: {:.2}", personality.priority_weights.maintainability);
println!(" Security: {:.2}", personality.priority_weights.security);
println!(" Testing: {:.2}", personality.priority_weights.testing);
println!(" Documentation: {:.2}", personality.priority_weights.documentation);
}
} else {
println!("❌ No active personality set.");
}
let total_personalities = self.config_system.get_personalities().len();
println!("\n📊 Statistics:");
println!(" Total Personalities: {}", total_personalities);
println!(" Learning Data: Available");
println!(" Configuration Status: ✅ Loaded");
Ok(())
}
fn save_and_export_configuration(&mut self) -> Result<()> {
println!("\n💾 Save & Export Configuration");
println!("{}", "=".repeat(30));
self.config_system.save_to_file()?;
println!("✅ Configuration saved successfully!");
println!("\nExport options:");
println!(" [1] Export to JSON file");
println!(" [2] Export personality summary");
println!(" [3] Export learning data");
println!(" [b] Back to main menu");
print!("Your choice: ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
match input.trim() {
"1" => println!("📄 JSON export (feature coming soon)"),
"2" => println!("📋 Personality summary export (feature coming soon)"),
"3" => println!("📊 Learning data export (feature coming soon)"),
"b" => {},
_ => println!("❌ Invalid option"),
}
Ok(())
}
pub fn record_interaction(&mut self, edit: &ModifiableEdit, action: UserAction) -> Result<()> {
self.config_system.record_user_interaction(
edit.base_edit.reason.clone(),
format!("File: {}, Lines: {}-{}",
edit.base_edit.file,
edit.base_edit.line_range.0,
edit.base_edit.line_range.1),
edit.base_edit.confidence,
action,
"current_project".to_string(),
);
self.config_system.save_to_file()?;
Ok(())
}
}
pub fn quick_agent_config() -> Result<()> {
let mut cli = CustomAgentConfigCLI::new()?;
cli.start_interactive_session()
}