Implement complete Team Composer service for WHOOSH MVP
Add sophisticated team formation engine with:
- Task analysis and classification algorithms
- Skill requirement detection and mapping
- Agent capability matching with confidence scoring
- Database persistence with PostgreSQL/pgx integration
- Production-ready REST API endpoints
API endpoints added:
- POST /api/v1/teams (create teams with analysis)
- GET /api/v1/teams (list teams with pagination)
- GET /api/v1/teams/{id} (get team details)
- POST /api/v1/teams/analyze (analyze without creating)
- POST /api/v1/agents/register (register new agents)
Core Team Composer capabilities:
- Heuristic task classification (9 task types)
- Multi-dimensional complexity assessment
- Technology domain identification
- Role-based team composition strategies
- Agent matching with skill/availability scoring
- Full database CRUD with transaction support
This moves WHOOSH from basic N8N workflow stubs to a fully
functional team composition system with real business logic.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
208
internal/composer/models.go
Normal file
208
internal/composer/models.go
Normal file
@@ -0,0 +1,208 @@
|
||||
package composer
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// TaskPriority represents task priority levels
|
||||
type TaskPriority string
|
||||
|
||||
const (
|
||||
PriorityLow TaskPriority = "low"
|
||||
PriorityMedium TaskPriority = "medium"
|
||||
PriorityHigh TaskPriority = "high"
|
||||
PriorityCritical TaskPriority = "critical"
|
||||
)
|
||||
|
||||
// TaskType represents different types of development tasks
|
||||
type TaskType string
|
||||
|
||||
const (
|
||||
TaskTypeFeatureDevelopment TaskType = "feature_development"
|
||||
TaskTypeBugFix TaskType = "bug_fix"
|
||||
TaskTypeRefactoring TaskType = "refactoring"
|
||||
TaskTypeMigration TaskType = "migration"
|
||||
TaskTypeResearch TaskType = "research"
|
||||
TaskTypeOptimization TaskType = "optimization"
|
||||
TaskTypeSecurity TaskType = "security"
|
||||
TaskTypeIntegration TaskType = "integration"
|
||||
TaskTypeMaintenance TaskType = "maintenance"
|
||||
)
|
||||
|
||||
// AgentStatus represents the current status of an agent
|
||||
type AgentStatus string
|
||||
|
||||
const (
|
||||
AgentStatusAvailable AgentStatus = "available"
|
||||
AgentStatusBusy AgentStatus = "busy"
|
||||
AgentStatusOffline AgentStatus = "offline"
|
||||
AgentStatusIdle AgentStatus = "idle"
|
||||
)
|
||||
|
||||
// TeamStatus represents the current status of a team
|
||||
type TeamStatus string
|
||||
|
||||
const (
|
||||
TeamStatusForming TeamStatus = "forming"
|
||||
TeamStatusActive TeamStatus = "active"
|
||||
TeamStatusCompleted TeamStatus = "completed"
|
||||
TeamStatusDisbanded TeamStatus = "disbanded"
|
||||
)
|
||||
|
||||
// TaskAnalysisInput represents the input data for team composition analysis
|
||||
type TaskAnalysisInput struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Requirements []string `json:"requirements"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
Priority TaskPriority `json:"priority"`
|
||||
TechStack []string `json:"tech_stack,omitempty"`
|
||||
EstimatedHours int `json:"estimated_hours,omitempty"`
|
||||
Complexity float64 `json:"complexity,omitempty"`
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
// TaskClassification represents the result of task classification analysis
|
||||
type TaskClassification struct {
|
||||
TaskType TaskType `json:"task_type"`
|
||||
ComplexityScore float64 `json:"complexity_score"`
|
||||
PrimaryDomains []string `json:"primary_domains"`
|
||||
SecondaryDomains []string `json:"secondary_domains"`
|
||||
EstimatedDuration int `json:"estimated_duration_hours"`
|
||||
RiskLevel string `json:"risk_level"`
|
||||
RequiredExperience string `json:"required_experience"`
|
||||
}
|
||||
|
||||
// SkillRequirement represents a required skill with proficiency level
|
||||
type SkillRequirement struct {
|
||||
Domain string `json:"domain"`
|
||||
MinProficiency float64 `json:"min_proficiency"`
|
||||
Weight float64 `json:"weight"`
|
||||
Critical bool `json:"critical"`
|
||||
}
|
||||
|
||||
// SkillRequirements represents the complete skill analysis for a task
|
||||
type SkillRequirements struct {
|
||||
CriticalSkills []SkillRequirement `json:"critical_skills"`
|
||||
DesirableSkills []SkillRequirement `json:"desirable_skills"`
|
||||
TotalSkillCount int `json:"total_skill_count"`
|
||||
}
|
||||
|
||||
// Agent represents an available AI agent with capabilities
|
||||
type Agent struct {
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
EndpointURL string `json:"endpoint_url" db:"endpoint_url"`
|
||||
Capabilities map[string]interface{} `json:"capabilities" db:"capabilities"`
|
||||
Status AgentStatus `json:"status" db:"status"`
|
||||
LastSeen time.Time `json:"last_seen" db:"last_seen"`
|
||||
PerformanceMetrics map[string]interface{} `json:"performance_metrics" db:"performance_metrics"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
// TeamRole represents a role that can be assigned within a team
|
||||
type TeamRole struct {
|
||||
ID int `json:"id" db:"id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Description string `json:"description" db:"description"`
|
||||
Capabilities map[string]interface{} `json:"capabilities" db:"capabilities"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
}
|
||||
|
||||
// Team represents a composed development team
|
||||
type Team struct {
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Description string `json:"description" db:"description"`
|
||||
Status TeamStatus `json:"status" db:"status"`
|
||||
TaskID *uuid.UUID `json:"task_id,omitempty" db:"task_id"`
|
||||
GiteaIssueURL string `json:"gitea_issue_url,omitempty" db:"gitea_issue_url"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty" db:"completed_at"`
|
||||
}
|
||||
|
||||
// TeamAssignment represents an agent assigned to a team role
|
||||
type TeamAssignment struct {
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
TeamID uuid.UUID `json:"team_id" db:"team_id"`
|
||||
AgentID uuid.UUID `json:"agent_id" db:"agent_id"`
|
||||
RoleID int `json:"role_id" db:"role_id"`
|
||||
Status string `json:"status" db:"status"`
|
||||
AssignedAt time.Time `json:"assigned_at" db:"assigned_at"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty" db:"completed_at"`
|
||||
}
|
||||
|
||||
// AgentMatch represents how well an agent matches a role requirement
|
||||
type AgentMatch struct {
|
||||
Agent *Agent `json:"agent"`
|
||||
Role *TeamRole `json:"role"`
|
||||
OverallScore float64 `json:"overall_score"`
|
||||
SkillScore float64 `json:"skill_score"`
|
||||
AvailabilityScore float64 `json:"availability_score"`
|
||||
ExperienceScore float64 `json:"experience_score"`
|
||||
Reasoning string `json:"reasoning"`
|
||||
Confidence float64 `json:"confidence"`
|
||||
}
|
||||
|
||||
// TeamComposition represents the recommended team structure
|
||||
type TeamComposition struct {
|
||||
TeamID uuid.UUID `json:"team_id"`
|
||||
Name string `json:"name"`
|
||||
Strategy string `json:"strategy"`
|
||||
RequiredRoles []*TeamRole `json:"required_roles"`
|
||||
OptionalRoles []*TeamRole `json:"optional_roles"`
|
||||
AgentMatches []*AgentMatch `json:"agent_matches"`
|
||||
EstimatedSize int `json:"estimated_size"`
|
||||
ConfidenceScore float64 `json:"confidence_score"`
|
||||
}
|
||||
|
||||
// CompositionResult represents the complete result of team composition analysis
|
||||
type CompositionResult struct {
|
||||
AnalysisID uuid.UUID `json:"analysis_id"`
|
||||
TaskInput *TaskAnalysisInput `json:"task_input"`
|
||||
Classification *TaskClassification `json:"classification"`
|
||||
SkillRequirements *SkillRequirements `json:"skill_requirements"`
|
||||
TeamComposition *TeamComposition `json:"team_composition"`
|
||||
AlternativeOptions []*TeamComposition `json:"alternative_options,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ProcessingTimeMs int64 `json:"processing_time_ms"`
|
||||
}
|
||||
|
||||
// ComposerConfig represents configuration for the team composer
|
||||
type ComposerConfig struct {
|
||||
// Model selection for different analysis types
|
||||
ClassificationModel string `json:"classification_model"`
|
||||
SkillAnalysisModel string `json:"skill_analysis_model"`
|
||||
MatchingModel string `json:"matching_model"`
|
||||
|
||||
// Composition strategy settings
|
||||
DefaultStrategy string `json:"default_strategy"`
|
||||
MinTeamSize int `json:"min_team_size"`
|
||||
MaxTeamSize int `json:"max_team_size"`
|
||||
SkillMatchThreshold float64 `json:"skill_match_threshold"`
|
||||
|
||||
// Performance settings
|
||||
AnalysisTimeoutSecs int `json:"analysis_timeout_secs"`
|
||||
EnableCaching bool `json:"enable_caching"`
|
||||
CacheTTLMins int `json:"cache_ttl_mins"`
|
||||
}
|
||||
|
||||
// DefaultComposerConfig returns sensible defaults for MVP
|
||||
func DefaultComposerConfig() *ComposerConfig {
|
||||
return &ComposerConfig{
|
||||
ClassificationModel: "llama3.1:8b",
|
||||
SkillAnalysisModel: "llama3.1:8b",
|
||||
MatchingModel: "llama3.1:8b",
|
||||
DefaultStrategy: "minimal_viable",
|
||||
MinTeamSize: 1,
|
||||
MaxTeamSize: 3,
|
||||
SkillMatchThreshold: 0.6,
|
||||
AnalysisTimeoutSecs: 60,
|
||||
EnableCaching: true,
|
||||
CacheTTLMins: 30,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user