Skip to main content

soma_core/agents/
custom_agent_config.rs

1// Custom Agent Configuration System for SOMA-CORE
2// Issue #30: User-defined agent personalities, custom prompting, and behavior modification
3// All comments in English (US) per coding_guidelines.md
4
5#![allow(dead_code)] // Keep API for future expansion
6
7use crate::agents::gpt4_agent::{CognitiveAgent, ProposedEdit, Insight, ExecutionTrace};
8use crate::memory::SymbolicContext;
9use crate::dag::Node;
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12use std::fs;
13use std::path::Path;
14use anyhow::{anyhow, Result};
15
16/// Configuration for a custom agent personality
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct AgentPersonality {
19    pub name: String,
20    pub description: String,
21    pub focus_areas: Vec<String>,
22    pub coding_style: CodingStyle,
23    pub risk_tolerance: RiskTolerance,
24    pub communication_style: CommunicationStyle,
25    pub priority_weights: PriorityWeights,
26}
27
28/// Coding style preferences for the agent
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct CodingStyle {
31    pub prefers_verbose_comments: bool,
32    pub prefers_short_functions: bool,
33    pub prefers_explicit_types: bool,
34    pub prefers_error_handling: ErrorHandlingStyle,
35    pub formatting_preferences: FormattingPreferences,
36}
37
38/// Error handling style preferences
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub enum ErrorHandlingStyle {
41    Explicit,    // Always use Result<T, E>
42    Panic,       // Use unwrap() and expect()
43    Optional,    // Use Option<T> where possible
44    Hybrid,      // Mix based on context
45}
46
47/// Code formatting preferences
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct FormattingPreferences {
50    pub max_line_length: usize,
51    pub prefer_single_line_blocks: bool,
52    pub indent_style: IndentStyle,
53    pub brace_style: BraceStyle,
54}
55
56/// Indentation style
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub enum IndentStyle {
59    Spaces(usize),
60    Tabs,
61}
62
63/// Brace placement style
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub enum BraceStyle {
66    SameLine,    // K&R style
67    NextLine,    // Allman style
68    Mixed,       // Context-dependent
69}
70
71/// Risk tolerance for suggesting changes
72#[derive(Debug, Clone, Serialize, Deserialize)]
73pub enum RiskTolerance {
74    Conservative,  // Only suggest safe, well-tested changes
75    Moderate,      // Balance between safety and innovation
76    Aggressive,    // Suggest bold improvements even if risky
77    Adaptive,      // Adjust based on project context
78}
79
80/// Communication style for explanations
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub enum CommunicationStyle {
83    Concise,      // Brief, to-the-point explanations
84    Detailed,     // Comprehensive explanations with examples
85    Tutorial,     // Educational style with learning focus
86    Professional, // Formal, business-oriented tone
87    Friendly,     // Casual, approachable tone
88}
89
90/// Priority weights for different improvement aspects
91#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct PriorityWeights {
93    pub performance: f64,
94    pub readability: f64,
95    pub maintainability: f64,
96    pub security: f64,
97    pub testing: f64,
98    pub documentation: f64,
99}
100
101/// Custom prompting configuration
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct CustomPromptConfig {
104    pub base_prompt: String,
105    pub context_templates: HashMap<String, String>,
106    pub response_format_preferences: ResponseFormatPreferences,
107    pub custom_instructions: Vec<String>,
108}
109
110/// Response format preferences
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct ResponseFormatPreferences {
113    pub include_confidence_scores: bool,
114    pub include_reasoning_steps: bool,
115    pub include_alternative_options: bool,
116    pub preferred_explanation_length: ExplanationLength,
117}
118
119/// Preferred explanation length
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub enum ExplanationLength {
122    Minimal,     // One-line explanations
123    Brief,       // 1-2 sentences
124    Standard,    // 2-3 sentences
125    Detailed,    // Paragraph-length
126    Comprehensive, // Multiple paragraphs
127}
128
129/// User preference learning and adaptation
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct PreferenceLearning {
132    pub accepted_suggestions: Vec<SuggestionRecord>,
133    pub rejected_suggestions: Vec<SuggestionRecord>,
134    pub modification_patterns: Vec<ModificationPattern>,
135    pub learned_preferences: LearnedPreferences,
136}
137
138/// Record of a suggestion and user action
139#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct SuggestionRecord {
141    pub suggestion_type: String,
142    pub context: String,
143    pub confidence: f64,
144    pub user_action: UserAction,
145    pub timestamp: String,
146    pub project_context: String,
147}
148
149/// User action on a suggestion
150#[derive(Debug, Clone, Serialize, Deserialize)]
151pub enum UserAction {
152    Accepted,
153    Rejected,
154    Modified,
155    Deferred,
156}
157
158/// Pattern in how user modifies suggestions
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct ModificationPattern {
161    pub pattern_type: String,
162    pub frequency: usize,
163    pub description: String,
164    pub confidence: f64,
165}
166
167/// Learned preferences from user interactions
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct LearnedPreferences {
170    pub preferred_suggestion_types: HashMap<String, f64>,
171    pub disliked_patterns: Vec<String>,
172    pub context_specific_preferences: HashMap<String, ContextualPreference>,
173    pub optimal_confidence_thresholds: HashMap<String, f64>,
174}
175
176/// Context-specific preferences
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct ContextualPreference {
179    pub context: String,
180    pub preference_adjustments: PriorityWeights,
181    pub specific_instructions: Vec<String>,
182}
183
184/// Project-specific context configuration
185#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct ProjectContext {
187    pub project_name: String,
188    pub project_type: ProjectType,
189    pub languages: Vec<String>,
190    pub frameworks: Vec<String>,
191    pub coding_standards: Vec<String>,
192    pub specific_constraints: Vec<String>,
193    pub team_preferences: Option<TeamPreferences>,
194}
195
196/// Type of software project
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub enum ProjectType {
199    WebApplication,
200    Library,
201    SystemTool,
202    Game,
203    Mobile,
204    DataScience,
205    MachineLearning,
206    Embedded,
207    Other(String),
208}
209
210/// Team-wide preferences and standards
211#[derive(Debug, Clone, Serialize, Deserialize)]
212pub struct TeamPreferences {
213    pub shared_coding_style: CodingStyle,
214    pub review_requirements: ReviewRequirements,
215    pub testing_standards: TestingStandards,
216    pub documentation_requirements: DocumentationRequirements,
217}
218
219/// Code review requirements
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct ReviewRequirements {
222    pub require_peer_review: bool,
223    pub minimum_reviewers: usize,
224    pub require_security_review: bool,
225    pub require_performance_review: bool,
226}
227
228/// Testing standards and requirements
229#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct TestingStandards {
231    pub minimum_coverage: f64,
232    pub require_unit_tests: bool,
233    pub require_integration_tests: bool,
234    pub test_naming_convention: String,
235}
236
237/// Documentation requirements
238#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct DocumentationRequirements {
240    pub require_function_docs: bool,
241    pub require_module_docs: bool,
242    pub require_examples: bool,
243    pub documentation_style: DocumentationStyle,
244}
245
246/// Style of documentation
247#[derive(Debug, Clone, Serialize, Deserialize)]
248pub enum DocumentationStyle {
249    Minimal,      // Basic function signatures
250    Standard,     // Function descriptions and parameters
251    Comprehensive, // Full examples and edge cases
252    Tutorial,     // Learning-focused documentation
253}
254
255/// Main custom agent configuration system
256pub struct CustomAgentConfigurationSystem {
257    personalities: HashMap<String, AgentPersonality>,
258    prompt_configs: HashMap<String, CustomPromptConfig>,
259    preference_learning: PreferenceLearning,
260    project_contexts: HashMap<String, ProjectContext>,
261    active_configuration: Option<String>,
262    config_file_path: String,
263}
264
265impl CustomAgentConfigurationSystem {
266    /// Create a new configuration system
267    pub fn new(config_dir: &str) -> Self {
268        let config_file_path = format!("{}/agent_configurations.json", config_dir);
269        
270        Self {
271            personalities: HashMap::new(),
272            prompt_configs: HashMap::new(),
273            preference_learning: PreferenceLearning::new(),
274            project_contexts: HashMap::new(),
275            active_configuration: None,
276            config_file_path,
277        }
278    }
279
280    /// Load configuration from file
281    pub fn load_from_file(&mut self) -> Result<()> {
282        if Path::new(&self.config_file_path).exists() {
283            let content = fs::read_to_string(&self.config_file_path)?;
284            let config: SavedConfiguration = serde_json::from_str(&content)?;
285            
286            self.personalities = config.personalities;
287            self.prompt_configs = config.prompt_configs;
288            self.preference_learning = config.preference_learning;
289            self.project_contexts = config.project_contexts;
290            self.active_configuration = config.active_configuration;
291        } else {
292            // Create default configuration
293            self.create_default_personalities();
294            self.create_default_prompt_configs();
295            self.save_to_file()?;
296        }
297        
298        Ok(())
299    }
300
301    /// Save configuration to file
302    pub fn save_to_file(&self) -> Result<()> {
303        let config = SavedConfiguration {
304            personalities: self.personalities.clone(),
305            prompt_configs: self.prompt_configs.clone(),
306            preference_learning: self.preference_learning.clone(),
307            project_contexts: self.project_contexts.clone(),
308            active_configuration: self.active_configuration.clone(),
309        };
310        
311        let content = serde_json::to_string_pretty(&config)?;
312        
313        // Ensure directory exists
314        if let Some(parent) = Path::new(&self.config_file_path).parent() {
315            fs::create_dir_all(parent)?;
316        }
317        
318        fs::write(&self.config_file_path, content)?;
319        Ok(())
320    }
321
322    /// Create default agent personalities
323    fn create_default_personalities(&mut self) {
324        // Performance-focused agent
325        let performance_agent = AgentPersonality {
326            name: "PerformanceOptimizer".to_string(),
327            description: "Focuses on code performance, efficiency, and optimization".to_string(),
328            focus_areas: vec![
329                "algorithm_optimization".to_string(),
330                "memory_usage".to_string(),
331                "cpu_efficiency".to_string(),
332                "caching_strategies".to_string(),
333            ],
334            coding_style: CodingStyle {
335                prefers_verbose_comments: false,
336                prefers_short_functions: true,
337                prefers_explicit_types: true,
338                prefers_error_handling: ErrorHandlingStyle::Explicit,
339                formatting_preferences: FormattingPreferences {
340                    max_line_length: 100,
341                    prefer_single_line_blocks: true,
342                    indent_style: IndentStyle::Spaces(4),
343                    brace_style: BraceStyle::SameLine,
344                },
345            },
346            risk_tolerance: RiskTolerance::Moderate,
347            communication_style: CommunicationStyle::Professional,
348            priority_weights: PriorityWeights {
349                performance: 0.4,
350                readability: 0.15,
351                maintainability: 0.2,
352                security: 0.1,
353                testing: 0.1,
354                documentation: 0.05,
355            },
356        };
357
358        // Readability-focused agent
359        let readability_agent = AgentPersonality {
360            name: "ReadabilityExpert".to_string(),
361            description: "Emphasizes code clarity, readability, and maintainability".to_string(),
362            focus_areas: vec![
363                "code_clarity".to_string(),
364                "naming_conventions".to_string(),
365                "code_structure".to_string(),
366                "documentation".to_string(),
367            ],
368            coding_style: CodingStyle {
369                prefers_verbose_comments: true,
370                prefers_short_functions: true,
371                prefers_explicit_types: true,
372                prefers_error_handling: ErrorHandlingStyle::Explicit,
373                formatting_preferences: FormattingPreferences {
374                    max_line_length: 80,
375                    prefer_single_line_blocks: false,
376                    indent_style: IndentStyle::Spaces(4),
377                    brace_style: BraceStyle::NextLine,
378                },
379            },
380            risk_tolerance: RiskTolerance::Conservative,
381            communication_style: CommunicationStyle::Tutorial,
382            priority_weights: PriorityWeights {
383                performance: 0.1,
384                readability: 0.4,
385                maintainability: 0.3,
386                security: 0.05,
387                testing: 0.1,
388                documentation: 0.05,
389            },
390        };
391
392        // Security-focused agent
393        let security_agent = AgentPersonality {
394            name: "SecuritySpecialist".to_string(),
395            description: "Prioritizes security, safety, and robust error handling".to_string(),
396            focus_areas: vec![
397                "input_validation".to_string(),
398                "memory_safety".to_string(),
399                "secure_coding".to_string(),
400                "error_handling".to_string(),
401            ],
402            coding_style: CodingStyle {
403                prefers_verbose_comments: true,
404                prefers_short_functions: true,
405                prefers_explicit_types: true,
406                prefers_error_handling: ErrorHandlingStyle::Explicit,
407                formatting_preferences: FormattingPreferences {
408                    max_line_length: 100,
409                    prefer_single_line_blocks: false,
410                    indent_style: IndentStyle::Spaces(4),
411                    brace_style: BraceStyle::SameLine,
412                },
413            },
414            risk_tolerance: RiskTolerance::Conservative,
415            communication_style: CommunicationStyle::Detailed,
416            priority_weights: PriorityWeights {
417                performance: 0.1,
418                readability: 0.2,
419                maintainability: 0.2,
420                security: 0.4,
421                testing: 0.05,
422                documentation: 0.05,
423            },
424        };
425
426        self.personalities.insert("performance_optimizer".to_string(), performance_agent);
427        self.personalities.insert("readability_expert".to_string(), readability_agent);
428        self.personalities.insert("security_specialist".to_string(), security_agent);
429    }
430
431    /// Create default prompt configurations
432    fn create_default_prompt_configs(&mut self) {
433        let performance_prompt = CustomPromptConfig {
434            base_prompt: "You are a performance optimization expert. Focus on improving code efficiency, reducing memory usage, and optimizing algorithms. Always consider the performance implications of your suggestions.".to_string(),
435            context_templates: {
436                let mut templates = HashMap::new();
437                templates.insert("file_analysis".to_string(), 
438                    "Analyze the following code for performance optimization opportunities: {code}".to_string());
439                templates.insert("function_optimization".to_string(), 
440                    "Optimize this function for better performance: {function}".to_string());
441                templates
442            },
443            response_format_preferences: ResponseFormatPreferences {
444                include_confidence_scores: true,
445                include_reasoning_steps: true,
446                include_alternative_options: true,
447                preferred_explanation_length: ExplanationLength::Standard,
448            },
449            custom_instructions: vec![
450                "Always measure before optimizing".to_string(),
451                "Consider algorithmic complexity first".to_string(),
452                "Profile memory usage patterns".to_string(),
453            ],
454        };
455
456        let readability_prompt = CustomPromptConfig {
457            base_prompt: "You are a code readability expert. Focus on making code clear, well-documented, and easy to understand. Prioritize maintainability and developer experience.".to_string(),
458            context_templates: {
459                let mut templates = HashMap::new();
460                templates.insert("file_analysis".to_string(), 
461                    "Review the following code for readability improvements: {code}".to_string());
462                templates.insert("naming_review".to_string(), 
463                    "Suggest better naming for variables and functions in: {code}".to_string());
464                templates
465            },
466            response_format_preferences: ResponseFormatPreferences {
467                include_confidence_scores: false,
468                include_reasoning_steps: true,
469                include_alternative_options: true,
470                preferred_explanation_length: ExplanationLength::Detailed,
471            },
472            custom_instructions: vec![
473                "Prefer descriptive names over short ones".to_string(),
474                "Add comments for complex logic".to_string(),
475                "Break down large functions".to_string(),
476            ],
477        };
478
479        self.prompt_configs.insert("performance_optimizer".to_string(), performance_prompt);
480        self.prompt_configs.insert("readability_expert".to_string(), readability_prompt);
481    }
482
483    /// Create a custom agent with the specified personality
484    pub fn create_custom_agent(&self, personality_name: &str) -> Result<CustomAgent> {
485        let personality = self.personalities.get(personality_name)
486            .ok_or_else(|| anyhow!("Personality '{}' not found", personality_name))?;
487        
488        let prompt_config = self.prompt_configs.get(personality_name);
489        
490        Ok(CustomAgent {
491            personality: personality.clone(),
492            prompt_config: prompt_config.cloned(),
493            learned_preferences: self.preference_learning.learned_preferences.clone(),
494        })
495    }
496
497    /// Add a new custom personality
498    pub fn add_personality(&mut self, name: String, personality: AgentPersonality) {
499        self.personalities.insert(name, personality);
500    }
501
502    /// Update preference learning based on user interaction
503    pub fn record_user_interaction(&mut self, suggestion_type: String, context: String, 
504                                 confidence: f64, action: UserAction, project_context: String) {
505        let record = SuggestionRecord {
506            suggestion_type: suggestion_type.clone(),
507            context,
508            confidence,
509            user_action: action.clone(),
510            timestamp: chrono::Utc::now().to_rfc3339(),
511            project_context,
512        };
513
514        match action {
515            UserAction::Accepted => self.preference_learning.accepted_suggestions.push(record),
516            UserAction::Rejected => self.preference_learning.rejected_suggestions.push(record),
517            _ => {} // Handle other actions as needed
518        }
519
520        // Update learned preferences
521        self.update_learned_preferences(&suggestion_type, &action);
522    }
523
524    /// Update learned preferences based on user actions
525    fn update_learned_preferences(&mut self, suggestion_type: &str, action: &UserAction) {
526        let current_score = self.preference_learning.learned_preferences
527            .preferred_suggestion_types
528            .get(suggestion_type)
529            .unwrap_or(&0.5);
530
531        let adjustment = match action {
532            UserAction::Accepted => 0.1,
533            UserAction::Rejected => -0.1,
534            UserAction::Modified => 0.05,
535            UserAction::Deferred => -0.02,
536        };
537
538        let new_score = (current_score + adjustment).clamp(0.0, 1.0);
539        self.preference_learning.learned_preferences
540            .preferred_suggestion_types
541            .insert(suggestion_type.to_string(), new_score);
542    }
543
544    /// Get available personalities
545    pub fn get_personalities(&self) -> &HashMap<String, AgentPersonality> {
546        &self.personalities
547    }
548
549    /// Set active configuration
550    pub fn set_active_configuration(&mut self, personality_name: String) {
551        self.active_configuration = Some(personality_name);
552    }
553
554    /// Get active configuration
555    pub fn get_active_configuration(&self) -> Option<&String> {
556        self.active_configuration.as_ref()
557    }
558}
559
560/// Serializable configuration for saving/loading
561#[derive(Debug, Serialize, Deserialize)]
562struct SavedConfiguration {
563    personalities: HashMap<String, AgentPersonality>,
564    prompt_configs: HashMap<String, CustomPromptConfig>,
565    preference_learning: PreferenceLearning,
566    project_contexts: HashMap<String, ProjectContext>,
567    active_configuration: Option<String>,
568}
569
570/// Custom agent implementation with configurable personality
571pub struct CustomAgent {
572    personality: AgentPersonality,
573    prompt_config: Option<CustomPromptConfig>,
574    learned_preferences: LearnedPreferences,
575}
576
577impl CognitiveAgent for CustomAgent {
578    fn propose_edit(&self, ctx: &SymbolicContext) -> ProposedEdit {
579        let task = ctx.resolve_or_default("current_task", "general improvement");
580        let file = ctx.resolve_or_default("target_file", "src/main.rs");
581
582        // Apply personality-driven logic
583        let confidence_modifier = match self.personality.risk_tolerance {
584            RiskTolerance::Conservative => -0.1,
585            RiskTolerance::Moderate => 0.0,
586            RiskTolerance::Aggressive => 0.1,
587            RiskTolerance::Adaptive => self.calculate_adaptive_modifier(ctx),
588        };
589
590        // Generate edit based on personality focus areas
591        let edit = if self.personality.focus_areas.contains(&"performance".to_string()) {
592            self.generate_performance_edit(&task, &file)
593        } else if self.personality.focus_areas.contains(&"code_clarity".to_string()) {
594            self.generate_readability_edit(&task, &file)
595        } else if self.personality.focus_areas.contains(&"input_validation".to_string()) {
596            self.generate_security_edit(&task, &file)
597        } else {
598            self.generate_general_edit(&task, &file)
599        };
600
601        // Adjust confidence based on personality and learned preferences
602        let mut adjusted_edit = edit;
603        adjusted_edit.confidence = (adjusted_edit.confidence + confidence_modifier).clamp(0.0, 1.0);
604
605        // Apply learned preferences
606        if let Some(preference_score) = self.learned_preferences.preferred_suggestion_types.get(&adjusted_edit.reason) {
607            adjusted_edit.confidence = (adjusted_edit.confidence * preference_score).clamp(0.0, 1.0);
608        }
609
610        adjusted_edit
611    }
612
613    fn reason_about_code(&self, file: &str, lines: &[String]) -> Insight {
614        let analysis = self.analyze_code_with_personality(lines);
615        
616        Insight {
617            summary: format!("{} analysis of {} ({} lines)", 
618                self.personality.name, file, lines.len()),
619            details: analysis,
620            confidence: self.calculate_reasoning_confidence(lines),
621        }
622    }
623
624    fn simulate(&self, phase: &str, dag: &[Node]) -> Vec<ExecutionTrace> {
625        dag.iter()
626            .map(|node| ExecutionTrace {
627                phase: phase.to_string(),
628                node_id: node.id.clone(),
629                result: format!("{} simulation result", self.personality.name),
630            })
631            .collect()
632    }
633}
634
635impl CustomAgent {
636    fn calculate_adaptive_modifier(&self, _ctx: &SymbolicContext) -> f64 {
637        // Implement adaptive risk calculation based on context
638        0.0
639    }
640
641    fn generate_performance_edit(&self, task: &str, file: &str) -> ProposedEdit {
642        ProposedEdit {
643            file: file.to_string(),
644            line_range: (10, 15),
645            new_code: format!("// {}: Performance optimization\n// {}\npub fn optimized_implementation() {{\n    // More efficient approach\n}}", 
646                self.personality.name, task),
647            reason: "performance_optimization".to_string(),
648            confidence: 0.85,
649        }
650    }
651
652    fn generate_readability_edit(&self, task: &str, file: &str) -> ProposedEdit {
653        ProposedEdit {
654            file: file.to_string(),
655            line_range: (20, 25),
656            new_code: format!("// {}: Readability improvement\n// {}\n/// Clear documentation for better understanding\npub fn well_documented_function() {{\n    // Self-explanatory implementation\n}}", 
657                self.personality.name, task),
658            reason: "readability_improvement".to_string(),
659            confidence: 0.90,
660        }
661    }
662
663    fn generate_security_edit(&self, task: &str, file: &str) -> ProposedEdit {
664        ProposedEdit {
665            file: file.to_string(),
666            line_range: (30, 35),
667            new_code: format!("// {}: Security enhancement\n// {}\npub fn secure_function(input: &str) -> Result<String, SecurityError> {{\n    validate_input(input)?;\n    // Secure processing\n    Ok(processed_result)\n}}", 
668                self.personality.name, task),
669            reason: "security_enhancement".to_string(),
670            confidence: 0.88,
671        }
672    }
673
674    fn generate_general_edit(&self, task: &str, file: &str) -> ProposedEdit {
675        ProposedEdit {
676            file: file.to_string(),
677            line_range: (40, 45),
678            new_code: format!("// {}: General improvement\n// {}\npub fn improved_function() {{\n    // Enhanced implementation\n}}", 
679                self.personality.name, task),
680            reason: "general_improvement".to_string(),
681            confidence: 0.75,
682        }
683    }
684
685    fn analyze_code_with_personality(&self, lines: &[String]) -> String {
686        let focus = self.personality.focus_areas.join(", ");
687        match self.personality.communication_style {
688            CommunicationStyle::Concise => format!("Focused on: {}", focus),
689            CommunicationStyle::Detailed => format!("Comprehensive analysis focusing on {}. Code structure appears well-organized with {} lines analyzed.", focus, lines.len()),
690            CommunicationStyle::Tutorial => format!("Let's examine this code with focus on {}. We have {} lines to analyze, which allows us to understand the structure and identify improvement opportunities.", focus, lines.len()),
691            CommunicationStyle::Professional => format!("Professional assessment: The code base consists of {} lines with analysis focus on {}. Initial review indicates standard implementation patterns.", lines.len(), focus),
692            CommunicationStyle::Friendly => format!("Hey! Looking at this code with {} in mind. We've got {} lines here - let's see what we can improve together!", focus, lines.len()),
693        }
694    }
695
696    fn calculate_reasoning_confidence(&self, lines: &[String]) -> f64 {
697        let base_confidence = match self.personality.risk_tolerance {
698            RiskTolerance::Conservative => 0.7,
699            RiskTolerance::Moderate => 0.8,
700            RiskTolerance::Aggressive => 0.9,
701            RiskTolerance::Adaptive => 0.75,
702        };
703
704        // Adjust based on code complexity
705        let complexity_factor: f64 = if lines.len() > 100 { -0.1 } else { 0.0 };
706        
707        (base_confidence + complexity_factor).clamp(0.0, 1.0)
708    }
709}
710
711impl PreferenceLearning {
712    pub fn new() -> Self {
713        Self {
714            accepted_suggestions: Vec::new(),
715            rejected_suggestions: Vec::new(),
716            modification_patterns: Vec::new(),
717            learned_preferences: LearnedPreferences {
718                preferred_suggestion_types: HashMap::new(),
719                disliked_patterns: Vec::new(),
720                context_specific_preferences: HashMap::new(),
721                optimal_confidence_thresholds: HashMap::new(),
722            },
723        }
724    }
725}
726
727impl Default for PriorityWeights {
728    fn default() -> Self {
729        Self {
730            performance: 0.2,
731            readability: 0.2,
732            maintainability: 0.2,
733            security: 0.15,
734            testing: 0.15,
735            documentation: 0.1,
736        }
737    }
738}
739
740#[cfg(test)]
741mod tests {
742    use super::*;
743    use tempfile::TempDir;
744
745    #[test]
746    fn test_custom_agent_configuration_system_creation() {
747        let temp_dir = TempDir::new().unwrap();
748        let config_dir = temp_dir.path().to_str().unwrap();
749        
750        let mut system = CustomAgentConfigurationSystem::new(config_dir);
751        assert!(system.load_from_file().is_ok());
752        assert_eq!(system.personalities.len(), 3); // Default personalities
753        assert!(!system.personalities.is_empty());
754    }
755
756    #[test]
757    fn test_personality_creation_and_retrieval() {
758        let temp_dir = TempDir::new().unwrap();
759        let config_dir = temp_dir.path().to_str().unwrap();
760        
761        let mut system = CustomAgentConfigurationSystem::new(config_dir);
762        system.load_from_file().unwrap();
763        
764        // Test retrieving default personalities
765        let personalities = system.get_personalities();
766        assert!(personalities.contains_key("performance_optimizer"));
767        assert!(personalities.contains_key("readability_expert"));
768        assert!(personalities.contains_key("security_specialist"));
769    }
770
771    #[test]
772    fn test_custom_agent_creation() {
773        let temp_dir = TempDir::new().unwrap();
774        let config_dir = temp_dir.path().to_str().unwrap();
775        
776        let mut system = CustomAgentConfigurationSystem::new(config_dir);
777        system.load_from_file().unwrap();
778        
779        let agent = system.create_custom_agent("performance_optimizer").unwrap();
780        assert_eq!(agent.personality.name, "PerformanceOptimizer");
781        assert_eq!(agent.personality.priority_weights.performance, 0.4);
782    }
783
784    #[test]
785    fn test_user_interaction_recording() {
786        let temp_dir = TempDir::new().unwrap();
787        let config_dir = temp_dir.path().to_str().unwrap();
788        
789        let mut system = CustomAgentConfigurationSystem::new(config_dir);
790        system.load_from_file().unwrap();
791        
792        system.record_user_interaction(
793            "performance_optimization".to_string(),
794            "loop optimization".to_string(),
795            0.9,
796            UserAction::Accepted,
797            "rust_project".to_string(),
798        );
799        
800        assert_eq!(system.preference_learning.accepted_suggestions.len(), 1);
801        let learned_score = system.preference_learning.learned_preferences
802            .preferred_suggestion_types
803            .get("performance_optimization")
804            .unwrap();
805        assert!(*learned_score > 0.5);
806    }
807
808    #[test]
809    fn test_save_and_load_configuration() {
810        let temp_dir = TempDir::new().unwrap();
811        let config_dir = temp_dir.path().to_str().unwrap();
812        
813        let mut system = CustomAgentConfigurationSystem::new(config_dir);
814        system.load_from_file().unwrap();
815        system.set_active_configuration("performance_optimizer".to_string());
816        
817        // Save configuration
818        assert!(system.save_to_file().is_ok());
819        
820        // Create new system and load
821        let mut new_system = CustomAgentConfigurationSystem::new(config_dir);
822        assert!(new_system.load_from_file().is_ok());
823        assert_eq!(new_system.get_active_configuration(), Some(&"performance_optimizer".to_string()));
824    }
825}