package repository import ( "context" "fmt" "strings" "github.com/anthonyrawlins/bzzz/gitea" "github.com/anthonyrawlins/bzzz/github" ) // DefaultProviderFactory implements ProviderFactory type DefaultProviderFactory struct{} // CreateProvider creates a task provider based on configuration func (f *DefaultProviderFactory) CreateProvider(ctx context.Context, config *Config) (TaskProvider, error) { switch strings.ToLower(config.Provider) { case "gitea": return f.createGiteaProvider(ctx, config) case "github": return f.createGitHubProvider(ctx, config) default: return nil, fmt.Errorf("unsupported provider: %s", config.Provider) } } // SupportedProviders returns list of supported providers func (f *DefaultProviderFactory) SupportedProviders() []string { return []string{"gitea", "github"} } // createGiteaProvider creates a Gitea task provider func (f *DefaultProviderFactory) createGiteaProvider(ctx context.Context, config *Config) (TaskProvider, error) { giteaConfig := &gitea.Config{ BaseURL: config.BaseURL, AccessToken: config.AccessToken, Owner: config.Owner, Repository: config.Repository, TaskLabel: config.TaskLabel, InProgressLabel: config.InProgressLabel, CompletedLabel: config.CompletedLabel, Assignee: config.Assignee, BaseBranch: config.BaseBranch, BranchPrefix: config.BranchPrefix, } client, err := gitea.NewClient(ctx, giteaConfig) if err != nil { return nil, fmt.Errorf("failed to create Gitea client: %w", err) } return &GiteaProvider{ client: client, config: config, }, nil } // createGitHubProvider creates a GitHub task provider func (f *DefaultProviderFactory) createGitHubProvider(ctx context.Context, config *Config) (TaskProvider, error) { githubConfig := &github.Config{ AccessToken: config.AccessToken, Owner: config.Owner, Repository: config.Repository, TaskLabel: config.TaskLabel, InProgressLabel: config.InProgressLabel, CompletedLabel: config.CompletedLabel, Assignee: config.Assignee, BaseBranch: config.BaseBranch, BranchPrefix: config.BranchPrefix, } client, err := github.NewClient(ctx, githubConfig) if err != nil { return nil, fmt.Errorf("failed to create GitHub client: %w", err) } return &GitHubProvider{ client: client, config: config, }, nil } // GiteaProvider adapts Gitea client to TaskProvider interface type GiteaProvider struct { client *gitea.Client config *Config } // ListAvailableTasks implements TaskProvider interface func (p *GiteaProvider) ListAvailableTasks() ([]*Task, error) { giteaTasks, err := p.client.ListAvailableTasks() if err != nil { return nil, err } tasks := make([]*Task, len(giteaTasks)) for i, gTask := range giteaTasks { tasks[i] = p.convertGiteaTask(gTask) } return tasks, nil } // ClaimTask implements TaskProvider interface func (p *GiteaProvider) ClaimTask(issueNumber int64, agentID string) (*Task, error) { gTask, err := p.client.ClaimTask(issueNumber, agentID) if err != nil { return nil, err } return p.convertGiteaTask(gTask), nil } // CompleteTask implements TaskProvider interface func (p *GiteaProvider) CompleteTask(issueNumber int64, agentID string, results map[string]interface{}) error { return p.client.CompleteTask(issueNumber, agentID, results) } // GetTask implements TaskProvider interface func (p *GiteaProvider) GetTask(issueNumber int64) (*Task, error) { // This would need to be implemented in the Gitea client return nil, fmt.Errorf("GetTask not yet implemented for Gitea provider") } // GetConfig implements TaskProvider interface func (p *GiteaProvider) GetConfig() *Config { return p.config } // convertGiteaTask converts a Gitea task to the unified Task format func (p *GiteaProvider) convertGiteaTask(gTask *gitea.Task) *Task { labels := make([]string, len(gTask.Labels)) for i, label := range gTask.Labels { labels[i] = label.Name } assignee := "" if gTask.Assignee != nil { assignee = gTask.Assignee.Login } return &Task{ ID: gTask.ID, Number: gTask.Number, Title: gTask.Title, Description: gTask.Description, State: gTask.State, Provider: "gitea", Repository: fmt.Sprintf("%s/%s", p.config.Owner, p.config.Repository), CreatedAt: gTask.CreatedAt, UpdatedAt: gTask.UpdatedAt, Assignee: assignee, Labels: labels, TaskType: gTask.TaskType, Priority: gTask.Priority, Requirements: gTask.Requirements, Deliverables: gTask.Deliverables, Context: gTask.Context, RequiredRole: gTask.RequiredRole, RequiredExpertise: gTask.RequiredExpertise, } } // GitHubProvider adapts GitHub client to TaskProvider interface type GitHubProvider struct { client *github.Client config *Config } // ListAvailableTasks implements TaskProvider interface func (p *GitHubProvider) ListAvailableTasks() ([]*Task, error) { githubTasks, err := p.client.ListAvailableTasks() if err != nil { return nil, err } tasks := make([]*Task, len(githubTasks)) for i, gTask := range githubTasks { tasks[i] = p.convertGitHubTask(gTask) } return tasks, nil } // ClaimTask implements TaskProvider interface func (p *GitHubProvider) ClaimTask(issueNumber int64, agentID string) (*Task, error) { gTask, err := p.client.ClaimTask(int(issueNumber), agentID) if err != nil { return nil, err } return p.convertGitHubTask(gTask), nil } // CompleteTask implements TaskProvider interface func (p *GitHubProvider) CompleteTask(issueNumber int64, agentID string, results map[string]interface{}) error { return p.client.CompleteTask(int(issueNumber), agentID, results) } // GetTask implements TaskProvider interface func (p *GitHubProvider) GetTask(issueNumber int64) (*Task, error) { // This would need to be implemented in the GitHub client return nil, fmt.Errorf("GetTask not yet implemented for GitHub provider") } // GetConfig implements TaskProvider interface func (p *GitHubProvider) GetConfig() *Config { return p.config } // convertGitHubTask converts a GitHub task to the unified Task format func (p *GitHubProvider) convertGitHubTask(gTask *github.Task) *Task { return &Task{ ID: gTask.ID, Number: int64(gTask.Number), Title: gTask.Title, Description: gTask.Description, State: gTask.State, Provider: "github", Repository: fmt.Sprintf("%s/%s", p.config.Owner, p.config.Repository), CreatedAt: gTask.CreatedAt, UpdatedAt: gTask.UpdatedAt, Assignee: gTask.Assignee, Labels: gTask.Labels, TaskType: gTask.TaskType, Priority: gTask.Priority, Requirements: gTask.Requirements, Deliverables: gTask.Deliverables, Context: gTask.Context, RequiredRole: "", // Would need to be parsed from GitHub task RequiredExpertise: []string{}, // Would need to be parsed from GitHub task } }