#!/usr/bin/env python3 """ User Preference Learning Learns from user's choices to provide better recommendations over time """ import json from pathlib import Path from datetime import datetime from typing import Dict, List, Optional from collections import defaultdict class UserPreferences: """Learns and stores user preferences for automation""" def __init__(self, storage_path: str = ".claude/meta-automation/user_preferences.json"): self.storage_path = Path(storage_path) self.storage_path.parent.mkdir(parents=True, exist_ok=True) self.preferences = self._load() def _load(self) -> Dict: """Load existing preferences or create new""" if self.storage_path.exists(): try: with open(self.storage_path, 'r') as f: return json.load(f) except: return self._create_new() return self._create_new() def _create_new(self) -> Dict: """Create new preferences structure""" return { 'version': '1.0', 'created_at': datetime.now().isoformat(), 'projects_analyzed': 0, 'automation_mode_preferences': { 'quick': 0, 'focused': 0, 'comprehensive': 0 }, 'agent_usage': {}, 'skill_usage': {}, 'project_type_history': {}, 'time_saved_total': 0, 'cost_spent_total': 0, 'satisfaction_ratings': [], 'most_valuable_automations': [], 'rarely_used': [], 'integration_preferences': { 'focus_on_gaps': 0, 'enhance_existing': 0, 'independent': 0 }, 'sessions': [] } def _save(self): """Save preferences to disk""" with open(self.storage_path, 'w') as f: json.dump(self.preferences, f, indent=2) def record_session(self, session_data: Dict): """ Record a new automation session Args: session_data: { 'session_id': str, 'project_type': str, 'mode': 'quick|focused|comprehensive', 'agents_used': List[str], 'skills_generated': List[str], 'time_spent_minutes': int, 'cost': float, 'time_saved_estimate': int, # hours 'user_satisfaction': int, # 1-5 'integration_choice': str, # gaps|enhance|independent } """ # Update counts self.preferences['projects_analyzed'] += 1 # Record mode preference mode = session_data.get('mode', 'quick') self.preferences['automation_mode_preferences'][mode] += 1 # Record agent usage for agent in session_data.get('agents_used', []): if agent not in self.preferences['agent_usage']: self.preferences['agent_usage'][agent] = 0 self.preferences['agent_usage'][agent] += 1 # Record skill usage for skill in session_data.get('skills_generated', []): if skill not in self.preferences['skill_usage']: self.preferences['skill_usage'][skill] = 0 self.preferences['skill_usage'][skill] += 1 # Record project type project_type = session_data.get('project_type', 'unknown') if project_type not in self.preferences['project_type_history']: self.preferences['project_type_history'][project_type] = 0 self.preferences['project_type_history'][project_type] += 1 # Track totals self.preferences['time_saved_total'] += session_data.get('time_saved_estimate', 0) self.preferences['cost_spent_total'] += session_data.get('cost', 0) # Track satisfaction satisfaction = session_data.get('user_satisfaction') if satisfaction: self.preferences['satisfaction_ratings'].append({ 'session_id': session_data.get('session_id'), 'rating': satisfaction, 'date': datetime.now().isoformat() }) # Track integration preference integration = session_data.get('integration_choice') if integration in self.preferences['integration_preferences']: self.preferences['integration_preferences'][integration] += 1 # Store full session self.preferences['sessions'].append({ **session_data, 'recorded_at': datetime.now().isoformat() }) self._save() def get_recommended_mode(self) -> str: """Get recommended automation mode based on history""" prefs = self.preferences['automation_mode_preferences'] if self.preferences['projects_analyzed'] == 0: return 'quick' # Default for first-time users # Return mode user uses most return max(prefs.items(), key=lambda x: x[1])[0] def get_recommended_agents(self, project_type: str, count: int = 5) -> List[str]: """Get recommended agents based on past usage and project type""" # Get agents user has used agent_usage = self.preferences['agent_usage'] if not agent_usage: # Default recommendations for new users defaults = { 'programming': ['project-analyzer', 'security-analyzer', 'test-coverage-analyzer'], 'academic_writing': ['project-analyzer', 'latex-structure-analyzer', 'citation-analyzer'], 'educational': ['project-analyzer', 'learning-path-analyzer', 'assessment-analyzer'], } return defaults.get(project_type, ['project-analyzer']) # Sort by usage count sorted_agents = sorted(agent_usage.items(), key=lambda x: x[1], reverse=True) return [agent for agent, _ in sorted_agents[:count]] def get_rarely_used(self) -> List[str]: """Get agents/skills that user never finds valuable""" rarely_used = [] # Check for agents used only once or twice for agent, count in self.preferences['agent_usage'].items(): if count <= 2 and self.preferences['projects_analyzed'] > 5: rarely_used.append(agent) return rarely_used def should_skip_agent(self, agent_name: str) -> bool: """Check if this agent is rarely useful for this user""" rarely_used = self.get_rarely_used() return agent_name in rarely_used def get_integration_preference(self) -> str: """Get preferred integration approach""" prefs = self.preferences['integration_preferences'] if sum(prefs.values()) == 0: return 'focus_on_gaps' # Default return max(prefs.items(), key=lambda x: x[1])[0] def get_statistics(self) -> Dict: """Get usage statistics""" total_sessions = self.preferences['projects_analyzed'] if total_sessions == 0: return { 'total_sessions': 0, 'message': 'No automation sessions yet' } avg_satisfaction = 0 if self.preferences['satisfaction_ratings']: avg_satisfaction = sum(r['rating'] for r in self.preferences['satisfaction_ratings']) / len(self.preferences['satisfaction_ratings']) return { 'total_sessions': total_sessions, 'time_saved_total_hours': self.preferences['time_saved_total'], 'cost_spent_total': round(self.preferences['cost_spent_total'], 2), 'average_satisfaction': round(avg_satisfaction, 1), 'preferred_mode': self.get_recommended_mode(), 'most_used_agents': sorted( self.preferences['agent_usage'].items(), key=lambda x: x[1], reverse=True )[:5], 'project_types': self.preferences['project_type_history'], 'roi': round(self.preferences['time_saved_total'] / max(1, self.preferences['cost_spent_total'] * 60), 1) } def get_recommendations_for_user(self, project_type: str) -> Dict: """Get personalized recommendations""" stats = self.get_statistics() if stats['total_sessions'] == 0: return { 'recommended_mode': 'quick', 'reason': 'First time - start with quick analysis to see how it works', 'recommended_agents': ['project-analyzer'], 'skip_agents': [] } return { 'recommended_mode': self.get_recommended_mode(), 'reason': f"You've used {self.get_recommended_mode()} mode {self.preferences['automation_mode_preferences'][self.get_recommended_mode()]} times", 'recommended_agents': self.get_recommended_agents(project_type), 'skip_agents': self.get_rarely_used(), 'integration_preference': self.get_integration_preference(), 'stats': { 'total_time_saved': f"{stats['time_saved_total_hours']} hours", 'average_satisfaction': stats.get('average_satisfaction', 0), 'roi': f"{stats.get('roi', 0)}x return on investment" } } def export_report(self) -> str: """Export usage report""" stats = self.get_statistics() report = f""" # Meta-Automation Usage Report ## Overview - **Total Sessions:** {stats['total_sessions']} - **Time Saved:** {stats.get('time_saved_total_hours', 0)} hours - **Cost Spent:** ${stats.get('cost_spent_total', 0):.2f} - **ROI:** {stats.get('roi', 0)}x (hours saved per dollar spent × 60) - **Avg Satisfaction:** {stats.get('average_satisfaction', 0)}/5 ## Your Preferences - **Preferred Mode:** {stats.get('preferred_mode', 'quick')} - **Integration Style:** {self.get_integration_preference()} ## Most Used Agents """ for agent, count in stats.get('most_used_agents', []): report += f"- {agent}: {count} times\n" report += "\n## Project Types\n" for ptype, count in self.preferences['project_type_history'].items(): report += f"- {ptype}: {count} projects\n" return report # Example usage if __name__ == '__main__': prefs = UserPreferences() # Simulate some sessions print("Simulating usage...\n") prefs.record_session({ 'session_id': 'session-1', 'project_type': 'programming', 'mode': 'quick', 'agents_used': ['project-analyzer'], 'skills_generated': [], 'time_spent_minutes': 5, 'cost': 0.03, 'time_saved_estimate': 10, 'user_satisfaction': 4, 'integration_choice': 'focus_on_gaps' }) prefs.record_session({ 'session_id': 'session-2', 'project_type': 'programming', 'mode': 'focused', 'agents_used': ['project-analyzer', 'security-analyzer', 'test-coverage-analyzer'], 'skills_generated': ['security-scanner', 'test-generator'], 'time_spent_minutes': 8, 'cost': 0.09, 'time_saved_estimate': 50, 'user_satisfaction': 5, 'integration_choice': 'focus_on_gaps' }) print(prefs.export_report()) print("\nRecommendations for next programming project:") recs = prefs.get_recommendations_for_user('programming') print(json.dumps(recs, indent=2))