Refactor everything
Change-Id: Ic3a37c38cfecba943c91f6ae545ce1c5b551c0d5
diff --git a/server/agent/manager.go b/server/agent/manager.go
index 191d42e..ea7474d 100644
--- a/server/agent/manager.go
+++ b/server/agent/manager.go
@@ -1,17 +1,11 @@
package agent
import (
- "context"
"fmt"
"log/slog"
- "os"
- "os/exec"
- "path/filepath"
- "strings"
"time"
"github.com/iomodo/staff/config"
- "github.com/iomodo/staff/git"
"github.com/iomodo/staff/llm"
_ "github.com/iomodo/staff/llm/providers" // Auto-register all providers
"github.com/iomodo/staff/task"
@@ -20,70 +14,31 @@
// Manager manages multiple AI agents with Git operations and task processing
type Manager struct {
- config *config.Config
- agents map[string]*Agent
- taskManager tm.TaskManager
- autoAssigner *task.AutoAssigner
- prProvider git.PullRequestProvider
- cloneManager *git.CloneManager
- subtaskService *task.SubtaskService
- isRunning map[string]bool
- stopChannels map[string]chan struct{}
- logger *slog.Logger
+ config *config.Config
+ agents map[string]*Agent
+ taskManager tm.TaskManager
+ autoAssigner *task.AutoAssigner
+ isRunning map[string]bool
+ roles []string
+ logger *slog.Logger
}
// NewManager creates a new agent manager
func NewManager(cfg *config.Config, taskManager tm.TaskManager, logger *slog.Logger) (*Manager, error) {
- if logger == nil {
- logger = slog.Default()
- }
- // Create auto-assigner
autoAssigner := task.NewAutoAssigner(cfg.Agents)
- // Create PR provider based on configuration
- var prProvider git.PullRequestProvider
- var repoURL string
-
- switch cfg.GetPrimaryGitProvider() {
- case "github":
- githubConfig := git.GitHubConfig{
- Token: cfg.GitHub.Token,
- Logger: logger,
- }
- prProvider = git.NewGitHubPullRequestProvider(cfg.GitHub.Owner, cfg.GitHub.Repo, githubConfig)
- repoURL = fmt.Sprintf("https://github.com/%s/%s.git", cfg.GitHub.Owner, cfg.GitHub.Repo)
- logger.Info("Using GitHub as pull request provider",
- slog.String("owner", cfg.GitHub.Owner),
- slog.String("repo", cfg.GitHub.Repo))
- case "gerrit":
- gerritConfig := git.GerritConfig{
- Username: cfg.Gerrit.Username,
- Password: cfg.Gerrit.Password,
- BaseURL: cfg.Gerrit.BaseURL,
- Logger: logger,
- }
- prProvider = git.NewGerritPullRequestProvider(cfg.Gerrit.Project, gerritConfig)
- repoURL = fmt.Sprintf("%s/%s", cfg.Gerrit.BaseURL, cfg.Gerrit.Project)
- logger.Info("Using Gerrit as pull request provider",
- slog.String("base_url", cfg.Gerrit.BaseURL),
- slog.String("project", cfg.Gerrit.Project))
- default:
- return nil, fmt.Errorf("no valid Git provider configured")
+ agentRoles := make([]string, 0, len(cfg.Agents))
+ for _, agentConfig := range cfg.Agents {
+ agentRoles = append(agentRoles, agentConfig.Role)
}
- // Create clone manager for per-agent Git repositories
- workspacePath := filepath.Join(".", "workspace")
- cloneManager := git.NewCloneManager(repoURL, workspacePath)
-
manager := &Manager{
config: cfg,
agents: make(map[string]*Agent),
taskManager: taskManager,
autoAssigner: autoAssigner,
- prProvider: prProvider,
- cloneManager: cloneManager,
isRunning: make(map[string]bool),
- stopChannels: make(map[string]chan struct{}),
+ roles: agentRoles,
logger: logger,
}
@@ -92,18 +47,19 @@
return nil, fmt.Errorf("failed to initialize agents: %w", err)
}
- // Initialize subtask service after agents are created
- if err := manager.initializeSubtaskService(); err != nil {
- return nil, fmt.Errorf("failed to initialize subtask service: %w", err)
- }
-
return manager, nil
}
// initializeAgents creates agent instances from configuration
func (m *Manager) initializeAgents() error {
+ llmConfig := llm.Config{
+ Provider: llm.ProviderFake, // Use fake provider for testing
+ APIKey: m.config.OpenAI.APIKey,
+ BaseURL: m.config.OpenAI.BaseURL,
+ Timeout: m.config.OpenAI.Timeout,
+ }
for _, agentConfig := range m.config.Agents {
- agent, err := m.createAgent(agentConfig)
+ agent, err := NewAgent(agentConfig, llmConfig, m.taskManager, m.roles, m.logger)
if err != nil {
return fmt.Errorf("failed to create agent %s: %w", agentConfig.Name, err)
}
@@ -112,95 +68,25 @@
return nil
}
-// initializeSubtaskService creates the subtask service with available agent roles
-func (m *Manager) initializeSubtaskService() error {
- // Get agent roles from configuration
- agentRoles := make([]string, 0, len(m.config.Agents))
- for _, agentConfig := range m.config.Agents {
- agentRoles = append(agentRoles, agentConfig.Name)
+func (m *Manager) StartAllAgents() {
+ // Start all configured agents with a default loop interval
+ defaultInterval := 1 * time.Second
+
+ for _, a := range m.agents {
+ m.logger.Info("Starting agent",
+ slog.String("name", a.Name),
+ slog.String("role", a.Role),
+ slog.String("model", a.Model))
+ if err := a.Start(defaultInterval); err != nil {
+ m.logger.Error("Failed to start agent",
+ slog.String("agent", a.Name),
+ slog.String("error", err.Error()))
+ continue
+ }
+ m.isRunning[a.Name] = true
}
-
- // Use the first agent's LLM provider for subtask analysis
- if len(m.agents) == 0 {
- return fmt.Errorf("no agents available for subtask service")
- }
-
- var firstAgent *Agent
- for _, agent := range m.agents {
- firstAgent = agent
- break
- }
-
- // Get owner and repo for subtask service based on provider
- var owner, repo string
- switch m.config.GetPrimaryGitProvider() {
- case "github":
- owner = m.config.GitHub.Owner
- repo = m.config.GitHub.Repo
- case "gerrit":
- owner = m.config.Gerrit.Project
- repo = m.config.Gerrit.Project
- }
-
- m.subtaskService = task.NewSubtaskService(
- firstAgent.Provider,
- m.taskManager,
- agentRoles,
- m.prProvider,
- owner,
- repo,
- m.cloneManager,
- m.logger,
- )
-
- return nil
}
-// createAgent creates a single agent instance
-func (m *Manager) createAgent(agentConfig config.AgentConfig) (*Agent, error) {
- // Load system prompt
- systemPrompt, err := m.loadSystemPrompt(agentConfig.SystemPromptFile)
- if err != nil {
- return nil, fmt.Errorf("failed to load system prompt: %w", err)
- }
-
- // Create LLM provider
- llmConfig := llm.Config{
- Provider: llm.ProviderFake, // Use fake provider for testing
- APIKey: m.config.OpenAI.APIKey,
- BaseURL: m.config.OpenAI.BaseURL,
- Timeout: m.config.OpenAI.Timeout,
- }
-
- provider, err := llm.CreateProvider(llmConfig)
- if err != nil {
- return nil, fmt.Errorf("failed to create LLM provider: %w", err)
- }
-
- agent := &Agent{
- Name: agentConfig.Name,
- Role: agentConfig.Role,
- Model: agentConfig.Model,
- SystemPrompt: systemPrompt,
- Provider: provider,
- MaxTokens: agentConfig.MaxTokens,
- Temperature: agentConfig.Temperature,
- Stats: AgentStats{},
- }
-
- return agent, nil
-}
-
-// loadSystemPrompt loads the system prompt from file
-func (m *Manager) loadSystemPrompt(filePath string) (string, error) {
- content, err := os.ReadFile(filePath)
- if err != nil {
- return "", fmt.Errorf("failed to read system prompt file %s: %w", filePath, err)
- }
- return string(content), nil
-}
-
-// StartAgent starts an agent to process tasks in a loop
func (m *Manager) StartAgent(agentName string, loopInterval time.Duration) error {
agent, exists := m.agents[agentName]
if !exists {
@@ -211,409 +97,28 @@
return fmt.Errorf("agent %s is already running", agentName)
}
- stopChan := make(chan struct{})
- m.stopChannels[agentName] = stopChan
+ agent.Start(loopInterval)
m.isRunning[agentName] = true
-
- go m.runAgentLoop(agent, loopInterval, stopChan)
-
- m.logger.Info("Started agent",
- slog.String("name", agentName),
- slog.String("role", agent.Role),
- slog.String("model", agent.Model))
return nil
}
// StopAgent stops a running agent
func (m *Manager) StopAgent(agentName string) error {
+ agent, exists := m.agents[agentName]
+ if !exists {
+ return fmt.Errorf("agent %s not found", agentName)
+ }
if !m.isRunning[agentName] {
return fmt.Errorf("agent %s is not running", agentName)
}
- close(m.stopChannels[agentName])
- delete(m.stopChannels, agentName)
+ agent.Stop()
m.isRunning[agentName] = false
m.logger.Info("Stopped agent", slog.String("name", agentName))
return nil
}
-// runAgentLoop runs the main processing loop for an agent
-func (m *Manager) runAgentLoop(agent *Agent, interval time.Duration, stopChan <-chan struct{}) {
- ticker := time.NewTicker(interval)
- defer ticker.Stop()
-
- for {
- select {
- case <-stopChan:
- m.logger.Info("Agent stopping", slog.String("name", agent.Name))
- return
- case <-ticker.C:
- if err := m.processAgentTasks(agent); err != nil {
- m.logger.Error("Error processing tasks for agent",
- slog.String("agent", agent.Name),
- slog.String("error", err.Error()))
- }
- }
- }
-}
-
-// processAgentTasks processes all assigned tasks for an agent
-func (m *Manager) processAgentTasks(agent *Agent) error {
- if agent.CurrentTask != nil {
- return nil
- }
-
- // Get tasks assigned to this agent
- tasks, err := m.taskManager.GetTasksByAssignee(agent.Name)
- if err != nil {
- return fmt.Errorf("failed to get tasks for agent %s: %w", agent.Name, err)
- }
-
- m.logger.Info("Processing tasks for agent",
- slog.Int("task_count", len(tasks)),
- slog.String("agent", agent.Name))
-
- for _, task := range tasks {
- if task.Status == tm.StatusToDo {
- if err := m.processTask(agent, task); err != nil {
- m.logger.Error("Error processing task",
- slog.String("task_id", task.ID),
- slog.String("error", err.Error()))
- // Mark task as failed
- task.Status = tm.StatusFailed
- if err := m.taskManager.UpdateTask(task); err != nil {
- m.logger.Error("Error updating failed task",
- slog.String("task_id", task.ID),
- slog.String("error", err.Error()))
- }
- agent.Stats.TasksFailed++
- } else {
- agent.Stats.TasksCompleted++
- }
- // Update success rate
- total := agent.Stats.TasksCompleted + agent.Stats.TasksFailed
- if total > 0 {
- agent.Stats.SuccessRate = float64(agent.Stats.TasksCompleted) / float64(total) * 100
- }
- }
- }
-
- return nil
-}
-
-// processTask processes a single task with an agent
-func (m *Manager) processTask(agent *Agent, task *tm.Task) error {
- ctx := context.Background()
- startTime := time.Now()
-
- m.logger.Info("Agent processing task",
- slog.String("agent", agent.Name),
- slog.String("task_id", task.ID),
- slog.String("title", task.Title))
-
- // Mark task as in progress
- task.Status = tm.StatusInProgress
- agent.CurrentTask = &task.ID
-
- // Check if this task should generate subtasks (with LLM decision)
- if m.shouldGenerateSubtasks(task) {
- m.logger.Info("LLM determined task should generate subtasks", slog.String("task_id", task.ID))
- if err := m.generateSubtasksForTask(ctx, task); err != nil {
- m.logger.Warn("Failed to generate subtasks for task",
- slog.String("task_id", task.ID),
- slog.String("error", err.Error()))
- } else {
- m.logger.Info("Task converted to subtasks by agent using LLM analysis",
- slog.String("task_id", task.ID),
- slog.String("agent", agent.Name))
- return nil
- }
- }
-
- // Generate solution using LLM
- solution, err := m.generateSolution(ctx, agent, task)
- if err != nil {
- return fmt.Errorf("failed to generate solution: %w", err)
- }
-
- // Create Git branch and commit solution
- branchName := m.generateBranchName(task)
- if err := m.createAndCommitSolution(branchName, task, solution, agent); err != nil {
- return fmt.Errorf("failed to commit solution: %w", err)
- }
-
- // Create pull request
- prURL, err := m.createPullRequest(ctx, task, solution, agent, branchName)
- if err != nil {
- return fmt.Errorf("failed to create pull request: %w", err)
- }
-
- // Update agent stats
- duration := time.Since(startTime)
- if agent.Stats.AvgTime == 0 {
- agent.Stats.AvgTime = duration.Milliseconds()
- } else {
- agent.Stats.AvgTime = (agent.Stats.AvgTime + duration.Milliseconds()) / 2
- }
-
- m.logger.Info("Task completed by agent",
- slog.String("task_id", task.ID),
- slog.String("agent", agent.Name),
- slog.Duration("duration", duration),
- slog.String("pr_url", prURL))
- return nil
-}
-
-// generateSolution uses the agent's LLM to generate a solution
-func (m *Manager) generateSolution(ctx context.Context, agent *Agent, task *tm.Task) (string, error) {
- prompt := m.buildTaskPrompt(task)
-
- req := llm.ChatCompletionRequest{
- Model: agent.Model,
- Messages: []llm.Message{
- {
- Role: llm.RoleSystem,
- Content: agent.SystemPrompt,
- },
- {
- Role: llm.RoleUser,
- Content: prompt,
- },
- },
- MaxTokens: agent.MaxTokens,
- Temperature: agent.Temperature,
- }
-
- resp, err := agent.Provider.ChatCompletion(ctx, req)
- if err != nil {
- return "", fmt.Errorf("LLM request failed: %w", err)
- }
-
- if len(resp.Choices) == 0 {
- return "", fmt.Errorf("no response from LLM")
- }
-
- return resp.Choices[0].Message.Content, nil
-}
-
-// buildTaskPrompt creates a detailed prompt for the LLM
-func (m *Manager) buildTaskPrompt(task *tm.Task) string {
- return fmt.Sprintf(`Task: %s
-
-Priority: %s
-Description: %s
-
-Please provide a complete solution for this task. Include:
-1. Detailed implementation plan
-2. Code changes needed (if applicable)
-3. Files to be created or modified
-4. Testing considerations
-5. Any dependencies or prerequisites
-
-Your response should be comprehensive and actionable.`,
- task.Title,
- task.Priority,
- task.Description)
-}
-
-// generateBranchName creates a Git branch name for the task
-func (m *Manager) generateBranchName(task *tm.Task) string {
- // Clean title for use in branch name
- cleanTitle := strings.ToLower(task.Title)
- cleanTitle = strings.ReplaceAll(cleanTitle, " ", "-")
- cleanTitle = strings.ReplaceAll(cleanTitle, "/", "-")
- // Remove special characters
- var result strings.Builder
- for _, r := range cleanTitle {
- if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' {
- result.WriteRune(r)
- }
- }
- cleanTitle = result.String()
-
- // Limit length
- if len(cleanTitle) > 40 {
- cleanTitle = cleanTitle[:40]
- }
-
- return fmt.Sprintf("%s%s-%s", m.config.Git.BranchPrefix, task.ID, cleanTitle)
-}
-
-// createAndCommitSolution creates a Git branch and commits the solution using per-agent clones
-func (m *Manager) createAndCommitSolution(branchName string, task *tm.Task, solution string, agent *Agent) error {
- ctx := context.Background()
-
- // Get agent's dedicated Git clone
- clonePath, err := m.cloneManager.GetAgentClonePath(agent.Name)
- if err != nil {
- return fmt.Errorf("failed to get agent clone: %w", err)
- }
-
- m.logger.Info("Agent working in clone",
- slog.String("agent", agent.Name),
- slog.String("clone_path", clonePath))
-
- // Refresh the clone with latest changes
- if err := m.cloneManager.RefreshAgentClone(agent.Name); err != nil {
- m.logger.Warn("Failed to refresh clone for agent",
- slog.String("agent", agent.Name),
- slog.String("error", err.Error()))
- }
-
- // All Git operations use the agent's clone directory
- gitCmd := func(args ...string) *exec.Cmd {
- return exec.CommandContext(ctx, "git", append([]string{"-C", clonePath}, args...)...)
- }
-
- // Ensure we're on main branch before creating new branch
- cmd := gitCmd("checkout", "main")
- if err := cmd.Run(); err != nil {
- // Try master branch if main doesn't exist
- cmd = gitCmd("checkout", "master")
- if err := cmd.Run(); err != nil {
- return fmt.Errorf("failed to checkout main/master branch: %w", err)
- }
- }
-
- // Create branch
- cmd = gitCmd("checkout", "-b", branchName)
- if err := cmd.Run(); err != nil {
- return fmt.Errorf("failed to create branch: %w", err)
- }
-
- // Create solution file in agent's clone
- solutionDir := filepath.Join(clonePath, "tasks", "solutions")
- if err := os.MkdirAll(solutionDir, 0755); err != nil {
- return fmt.Errorf("failed to create solution directory: %w", err)
- }
-
- solutionFile := filepath.Join(solutionDir, fmt.Sprintf("%s-solution.md", task.ID))
- solutionContent := fmt.Sprintf(`# Solution for Task: %s
-
-**Agent:** %s (%s)
-**Model:** %s
-**Completed:** %s
-
-## Task Description
-%s
-
-## Solution
-%s
-
----
-*Generated by Staff AI Agent System*
-`, task.Title, agent.Name, agent.Role, agent.Model, time.Now().Format(time.RFC3339), task.Description, solution)
-
- if err := os.WriteFile(solutionFile, []byte(solutionContent), 0644); err != nil {
- return fmt.Errorf("failed to write solution file: %w", err)
- }
-
- // Stage files
- relativeSolutionFile := filepath.Join("tasks", "solutions", fmt.Sprintf("%s-solution.md", task.ID))
- cmd = gitCmd("add", relativeSolutionFile)
- if err := cmd.Run(); err != nil {
- return fmt.Errorf("failed to stage files: %w", err)
- }
-
- // Commit changes
- commitMsg := m.buildCommitMessage(task, agent)
- cmd = gitCmd("commit", "-m", commitMsg)
- if err := cmd.Run(); err != nil {
- return fmt.Errorf("failed to commit: %w", err)
- }
-
- // Push branch
- cmd = gitCmd("push", "-u", "origin", branchName)
- if err := cmd.Run(); err != nil {
- return fmt.Errorf("failed to push branch: %w", err)
- }
-
- m.logger.Info("Agent successfully pushed branch",
- slog.String("agent", agent.Name),
- slog.String("branch", branchName))
- return nil
-}
-
-// buildCommitMessage creates a commit message from template
-func (m *Manager) buildCommitMessage(task *tm.Task, agent *Agent) string {
- template := m.config.Git.CommitMessageTemplate
-
- replacements := map[string]string{
- "{task_id}": task.ID,
- "{task_title}": task.Title,
- "{agent_name}": agent.Name,
- "{solution}": "See solution file for details",
- }
-
- result := template
- for placeholder, value := range replacements {
- result = strings.ReplaceAll(result, placeholder, value)
- }
-
- return result
-}
-
-// createPullRequest creates a GitHub pull request
-func (m *Manager) createPullRequest(ctx context.Context, task *tm.Task, solution string, agent *Agent, branchName string) (string, error) {
- title := fmt.Sprintf("Task %s: %s", task.ID, task.Title)
-
- // Build PR description from template
- description := m.buildPRDescription(task, solution, agent)
-
- options := git.PullRequestOptions{
- Title: title,
- Description: description,
- HeadBranch: branchName,
- BaseBranch: "main",
- Labels: []string{"ai-generated", "staff-agent", strings.ToLower(agent.Role)},
- Draft: false,
- }
-
- pr, err := m.prProvider.CreatePullRequest(ctx, options)
- if err != nil {
- return "", fmt.Errorf("failed to create PR: %w", err)
- }
-
- // Generate provider-specific PR URL
- switch m.config.GetPrimaryGitProvider() {
- case "github":
- return fmt.Sprintf("https://github.com/%s/%s/pull/%d", m.config.GitHub.Owner, m.config.GitHub.Repo, pr.Number), nil
- case "gerrit":
- return fmt.Sprintf("%s/c/%s/+/%d", m.config.Gerrit.BaseURL, m.config.Gerrit.Project, pr.Number), nil
- default:
- return "", fmt.Errorf("unknown git provider")
- }
-}
-
-// buildPRDescription creates PR description from template
-func (m *Manager) buildPRDescription(task *tm.Task, solution string, agent *Agent) string {
- template := m.config.Git.PRTemplate
-
- // Truncate solution for PR if too long
- truncatedSolution := solution
- if len(solution) > 1000 {
- truncatedSolution = solution[:1000] + "...\n\n*See solution file for complete details*"
- }
-
- replacements := map[string]string{
- "{task_id}": task.ID,
- "{task_title}": task.Title,
- "{task_description}": task.Description,
- "{agent_name}": fmt.Sprintf("%s (%s)", agent.Name, agent.Role),
- "{priority}": string(task.Priority),
- "{solution}": truncatedSolution,
- "{files_changed}": fmt.Sprintf("- `tasks/solutions/%s-solution.md`", task.ID),
- }
-
- result := template
- for placeholder, value := range replacements {
- result = strings.ReplaceAll(result, placeholder, value)
- }
-
- return result
-}
-
// AutoAssignTask automatically assigns a task to the best matching agent
func (m *Manager) AutoAssignTask(taskID string) error {
task, err := m.taskManager.GetTask(taskID)
@@ -640,108 +145,6 @@
return nil
}
-// GetAgentStatus returns the status of all agents
-func (m *Manager) GetAgentStatus() map[string]AgentInfo {
- status := make(map[string]AgentInfo)
-
- for name, agent := range m.agents {
- agentStatus := StatusIdle
- if m.isRunning[name] {
- if agent.CurrentTask != nil {
- agentStatus = StatusRunning
- }
- } else {
- agentStatus = StatusStopped
- }
-
- status[name] = AgentInfo{
- Name: agent.Name,
- Role: agent.Role,
- Model: agent.Model,
- Status: agentStatus,
- CurrentTask: agent.CurrentTask,
- Stats: agent.Stats,
- }
- }
-
- return status
-}
-
-// shouldGenerateSubtasks determines if a task should be broken down into subtasks using LLM
-func (m *Manager) shouldGenerateSubtasks(task *tm.Task) bool {
- // Don't generate subtasks for subtasks
- if task.ParentTaskID != "" {
- return false
- }
-
- // Don't generate if already evaluated
- if task.SubtasksEvaluated {
- return false
- }
-
- // Ask LLM to decide
- ctx := context.Background()
- decision, err := m.subtaskService.ShouldGenerateSubtasks(ctx, task)
- if err != nil {
- m.logger.Warn("Failed to get LLM subtask decision for task",
- slog.String("task_id", task.ID),
- slog.String("error", err.Error()))
- // Fallback to simple heuristics
- return task.Priority == tm.PriorityHigh || len(task.Description) > 200
- }
-
- task.SubtasksEvaluated = true
- m.logger.Info("LLM subtask decision for task",
- slog.String("task_id", task.ID),
- slog.Bool("needs_subtasks", decision.NeedsSubtasks),
- slog.Int("complexity_score", decision.ComplexityScore),
- slog.String("reasoning", decision.Reasoning))
-
- return decision.NeedsSubtasks
-}
-
-// generateSubtasksForTask analyzes a task and creates a PR with proposed subtasks
-func (m *Manager) generateSubtasksForTask(ctx context.Context, task *tm.Task) error {
- if m.subtaskService == nil {
- return fmt.Errorf("subtask service not initialized")
- }
-
- // Analyze the task for subtasks
- analysis, err := m.subtaskService.AnalyzeTaskForSubtasks(ctx, task)
- if err != nil {
- return fmt.Errorf("failed to analyze task for subtasks: %w", err)
- }
-
- // Generate a PR with the subtask proposals
- prURL, err := m.subtaskService.GenerateSubtaskPR(ctx, analysis)
- if err != nil {
- return fmt.Errorf("failed to generate subtask PR: %w", err)
- }
-
- // Update the task with subtask information
- task.SubtasksPRURL = prURL
- task.SubtasksGenerated = true
-
- m.logger.Info("Generated subtask PR for task",
- slog.String("task_id", task.ID),
- slog.String("pr_url", prURL))
- m.logger.Info("Proposed subtasks and new agents for task",
- slog.String("task_id", task.ID),
- slog.Int("subtask_count", len(analysis.Subtasks)),
- slog.Int("new_agent_count", len(analysis.AgentCreations)))
-
- // Log proposed new agents if any
- if len(analysis.AgentCreations) > 0 {
- for _, agent := range analysis.AgentCreations {
- m.logger.Info("Proposed new agent",
- slog.String("role", agent.Role),
- slog.Any("skills", agent.Skills))
- }
- }
-
- return nil
-}
-
// IsAgentRunning checks if an agent is currently running
func (m *Manager) IsAgentRunning(agentName string) bool {
return m.isRunning[agentName]
@@ -764,18 +167,5 @@
slog.String("error", err.Error()))
}
}
-
- // Cleanup all agent Git clones
- if err := m.cloneManager.CleanupAllClones(); err != nil {
- m.logger.Error("Error cleaning up agent clones", slog.String("error", err.Error()))
- }
-
- // Cleanup subtask service
- if m.subtaskService != nil {
- if err := m.subtaskService.Close(); err != nil {
- m.logger.Error("Error closing subtask service", slog.String("error", err.Error()))
- }
- }
-
return nil
}