package agent import ( "fmt" "path/filepath" "strings" "sync" ) // AgentRole represents different agent roles in the system type AgentRole string const ( BackendRole AgentRole = "backend" FrontendRole AgentRole = "frontend" DevOpsRole AgentRole = "devops" QARole AgentRole = "qa" TestingRole AgentRole = "testing" GeneralRole AgentRole = "general" ) // RoleCapability represents capabilities of an agent role type RoleCapability struct { Name string Description string Weight float64 } // DirectoryScope represents directory patterns for context filtering type DirectoryScope struct { Patterns []string Description string } // RoleConfig holds configuration for an agent role type RoleConfig struct { Role AgentRole DisplayName string Description string Capabilities []RoleCapability DirectoryScopes DirectoryScope TaskTypes []string Priority int // Context filtering parameters ContextWeight float64 FeedbackWeight float64 LearningRate float64 } // RoleManager manages agent roles and their configurations type RoleManager struct { roles map[AgentRole]*RoleConfig agentRoles map[string]AgentRole // Maps agent ID to role mu sync.RWMutex } // NewRoleManager creates a new role manager with default configurations func NewRoleManager() *RoleManager { rm := &RoleManager{ roles: make(map[AgentRole]*RoleConfig), agentRoles: make(map[string]AgentRole), } rm.initializeDefaultRoles() return rm } // initializeDefaultRoles sets up default role configurations func (rm *RoleManager) initializeDefaultRoles() { // Backend role configuration rm.roles[BackendRole] = &RoleConfig{ Role: BackendRole, DisplayName: "Backend Developer", Description: "Specializes in server-side development, APIs, databases, and backend services", Capabilities: []RoleCapability{ {Name: "api_development", Description: "REST/GraphQL API development", Weight: 1.0}, {Name: "database_design", Description: "Database schema and query optimization", Weight: 0.9}, {Name: "server_architecture", Description: "Server architecture and microservices", Weight: 0.9}, {Name: "authentication", Description: "Authentication and authorization systems", Weight: 0.8}, {Name: "caching", Description: "Caching strategies and implementation", Weight: 0.8}, }, DirectoryScopes: DirectoryScope{ Patterns: []string{ "*/backend/*", "*/api/*", "*/services/*", "*/server/*", "*/core/*", "*/models/*", "*/controllers/*", "*/middleware/*", }, Description: "Backend-related directories and server-side code", }, TaskTypes: []string{ "api_development", "database_migration", "backend_optimization", "server_configuration", "authentication_setup", }, Priority: 5, ContextWeight: 1.0, FeedbackWeight: 0.3, LearningRate: 0.1, } // Frontend role configuration rm.roles[FrontendRole] = &RoleConfig{ Role: FrontendRole, DisplayName: "Frontend Developer", Description: "Specializes in user interfaces, client-side logic, and user experience", Capabilities: []RoleCapability{ {Name: "ui_development", Description: "User interface development", Weight: 1.0}, {Name: "responsive_design", Description: "Responsive and mobile-first design", Weight: 0.9}, {Name: "state_management", Description: "Client-side state management", Weight: 0.8}, {Name: "component_architecture", Description: "Component-based architecture", Weight: 0.9}, {Name: "accessibility", Description: "Web accessibility implementation", Weight: 0.7}, }, DirectoryScopes: DirectoryScope{ Patterns: []string{ "*/frontend/*", "*/ui/*", "*/client/*", "*/web/*", "*/components/*", "*/pages/*", "*/styles/*", "*/assets/*", }, Description: "Frontend-related directories and client-side code", }, TaskTypes: []string{ "ui_implementation", "component_development", "responsive_design", "frontend_optimization", "user_experience", }, Priority: 4, ContextWeight: 0.8, FeedbackWeight: 0.3, LearningRate: 0.1, } // DevOps role configuration rm.roles[DevOpsRole] = &RoleConfig{ Role: DevOpsRole, DisplayName: "DevOps Engineer", Description: "Specializes in deployment, infrastructure, CI/CD, and system operations", Capabilities: []RoleCapability{ {Name: "infrastructure", Description: "Infrastructure as Code", Weight: 1.0}, {Name: "containerization", Description: "Docker and container orchestration", Weight: 0.9}, {Name: "ci_cd", Description: "Continuous Integration/Deployment", Weight: 0.9}, {Name: "monitoring", Description: "System monitoring and alerting", Weight: 0.8}, {Name: "security", Description: "Security and compliance", Weight: 0.8}, }, DirectoryScopes: DirectoryScope{ Patterns: []string{ "*/deploy/*", "*/config/*", "*/docker/*", "*/k8s/*", "*/kubernetes/*", "*/infrastructure/*", "*/scripts/*", "*/ci/*", "*.yml", "*.yaml", "Dockerfile*", "docker-compose*", }, Description: "DevOps-related configuration and deployment files", }, TaskTypes: []string{ "deployment", "infrastructure_setup", "ci_cd_pipeline", "system_monitoring", "security_configuration", }, Priority: 5, ContextWeight: 1.0, FeedbackWeight: 0.4, LearningRate: 0.1, } // QA role configuration rm.roles[QARole] = &RoleConfig{ Role: QARole, DisplayName: "Quality Assurance", Description: "Specializes in quality assurance, code review, and process improvement", Capabilities: []RoleCapability{ {Name: "code_review", Description: "Code review and quality assessment", Weight: 1.0}, {Name: "process_improvement", Description: "Development process improvement", Weight: 0.9}, {Name: "quality_metrics", Description: "Quality metrics and reporting", Weight: 0.8}, {Name: "best_practices", Description: "Best practices enforcement", Weight: 0.9}, {Name: "documentation", Description: "Documentation quality assurance", Weight: 0.7}, }, DirectoryScopes: DirectoryScope{ Patterns: []string{ "*/tests/*", "*/quality/*", "*/review/*", "*/docs/*", "*/documentation/*", "*", // QA role gets broader access for review purposes }, Description: "All directories for quality assurance and code review", }, TaskTypes: []string{ "code_review", "quality_assessment", "process_improvement", "documentation_review", "compliance_check", }, Priority: 4, ContextWeight: 0.7, FeedbackWeight: 0.5, LearningRate: 0.2, } // Testing role configuration rm.roles[TestingRole] = &RoleConfig{ Role: TestingRole, DisplayName: "Test Engineer", Description: "Specializes in automated testing, test frameworks, and test strategy", Capabilities: []RoleCapability{ {Name: "unit_testing", Description: "Unit test development", Weight: 1.0}, {Name: "integration_testing", Description: "Integration test development", Weight: 0.9}, {Name: "e2e_testing", Description: "End-to-end test automation", Weight: 0.9}, {Name: "test_frameworks", Description: "Test framework setup and maintenance", Weight: 0.8}, {Name: "performance_testing", Description: "Performance and load testing", Weight: 0.7}, }, DirectoryScopes: DirectoryScope{ Patterns: []string{ "*/tests/*", "*/spec/*", "*/test/*", "*/e2e/*", "*/integration/*", "*/__tests__/*", "*.test.*", "*.spec.*", }, Description: "Test-related directories and files", }, TaskTypes: []string{ "unit_testing", "integration_testing", "e2e_testing", "test_automation", "performance_testing", }, Priority: 4, ContextWeight: 0.6, FeedbackWeight: 0.4, LearningRate: 0.15, } // General role configuration rm.roles[GeneralRole] = &RoleConfig{ Role: GeneralRole, DisplayName: "General Developer", Description: "General-purpose development with broad capabilities", Capabilities: []RoleCapability{ {Name: "general_development", Description: "General software development", Weight: 0.7}, {Name: "problem_solving", Description: "General problem solving", Weight: 0.8}, {Name: "documentation", Description: "Documentation writing", Weight: 0.6}, {Name: "code_maintenance", Description: "Code maintenance and refactoring", Weight: 0.7}, {Name: "research", Description: "Technical research and analysis", Weight: 0.8}, }, DirectoryScopes: DirectoryScope{ Patterns: []string{ "*", // General role has access to all directories }, Description: "All directories for general development tasks", }, TaskTypes: []string{ "general_development", "documentation", "code_maintenance", "research", "bug_fixes", }, Priority: 2, ContextWeight: 0.5, FeedbackWeight: 0.2, LearningRate: 0.1, } } // AssignRole assigns a role to an agent func (rm *RoleManager) AssignRole(agentID string, role AgentRole) error { rm.mu.Lock() defer rm.mu.Unlock() if _, exists := rm.roles[role]; !exists { return fmt.Errorf("role %s does not exist", role) } rm.agentRoles[agentID] = role return nil } // GetAgentRole returns the role assigned to an agent func (rm *RoleManager) GetAgentRole(agentID string) (AgentRole, bool) { rm.mu.RLock() defer rm.mu.RUnlock() role, exists := rm.agentRoles[agentID] return role, exists } // GetRoleConfig returns the configuration for a specific role func (rm *RoleManager) GetRoleConfig(role AgentRole) (*RoleConfig, bool) { rm.mu.RLock() defer rm.mu.RUnlock() config, exists := rm.roles[role] return config, exists } // GetAllRoles returns all available roles func (rm *RoleManager) GetAllRoles() map[AgentRole]*RoleConfig { rm.mu.RLock() defer rm.mu.RUnlock() result := make(map[AgentRole]*RoleConfig) for role, config := range rm.roles { // Create a copy to avoid race conditions configCopy := *config result[role] = &configCopy } return result } // MatchesDirectoryScope checks if a directory path matches the agent's scope func (rm *RoleManager) MatchesDirectoryScope(agentID, directory string) bool { role, exists := rm.GetAgentRole(agentID) if !exists { return false } config, exists := rm.GetRoleConfig(role) if !exists { return false } return rm.matchesPatterns(directory, config.DirectoryScopes.Patterns) } // GetRelevanceScore calculates context relevance score for an agent and directory func (rm *RoleManager) GetRelevanceScore(agentID, directory string) float64 { role, exists := rm.GetAgentRole(agentID) if !exists { return 0.1 // Low default score } config, exists := rm.GetRoleConfig(role) if !exists { return 0.1 } if rm.matchesPatterns(directory, config.DirectoryScopes.Patterns) { return config.ContextWeight } return 0.1 // Low score for non-matching directories } // matchesPatterns checks if a directory matches any of the given patterns func (rm *RoleManager) matchesPatterns(directory string, patterns []string) bool { if directory == "" { return false } directory = strings.ToLower(directory) for _, pattern := range patterns { pattern = strings.ToLower(pattern) // Handle wildcard patterns if pattern == "*" { return true } // Handle glob-style patterns if matched, _ := filepath.Match(pattern, directory); matched { return true } // Handle substring matching for directory paths if strings.Contains(directory, strings.Trim(pattern, "*")) { return true } } return false } // UpdateRoleWeight updates the context weight for a role (for RL learning) func (rm *RoleManager) UpdateRoleWeight(role AgentRole, newWeight float64) error { rm.mu.Lock() defer rm.mu.Unlock() config, exists := rm.roles[role] if !exists { return fmt.Errorf("role %s does not exist", role) } // Clamp weight to reasonable bounds if newWeight < 0.1 { newWeight = 0.1 } if newWeight > 2.0 { newWeight = 2.0 } config.ContextWeight = newWeight return nil } // GetAgentsByRole returns all agents assigned to a specific role func (rm *RoleManager) GetAgentsByRole(role AgentRole) []string { rm.mu.RLock() defer rm.mu.RUnlock() var agents []string for agentID, agentRole := range rm.agentRoles { if agentRole == role { agents = append(agents, agentID) } } return agents } // GetCapabilitiesForRole returns capabilities for a specific role func (rm *RoleManager) GetCapabilitiesForRole(role AgentRole) ([]RoleCapability, bool) { config, exists := rm.GetRoleConfig(role) if !exists { return nil, false } return config.Capabilities, true } // CanHandleTaskType checks if a role can handle a specific task type func (rm *RoleManager) CanHandleTaskType(role AgentRole, taskType string) bool { config, exists := rm.GetRoleConfig(role) if !exists { return false } for _, supportedType := range config.TaskTypes { if supportedType == taskType { return true } } return false } // GetBestRoleForDirectory returns the best role for a given directory func (rm *RoleManager) GetBestRoleForDirectory(directory string) (AgentRole, float64) { bestRole := GeneralRole bestScore := 0.0 for role, config := range rm.roles { if rm.matchesPatterns(directory, config.DirectoryScopes.Patterns) { score := config.ContextWeight * float64(config.Priority) / 5.0 if score > bestScore { bestScore = score bestRole = role } } } return bestRole, bestScore } // String returns string representation of AgentRole func (ar AgentRole) String() string { return string(ar) } // IsValid checks if the agent role is valid func (ar AgentRole) IsValid() bool { switch ar { case BackendRole, FrontendRole, DevOpsRole, QARole, TestingRole, GeneralRole: return true default: return false } }