Update logging
Change-Id: I13279582aa717edad5d56323866b941db1919404
diff --git a/server/agent/agent.go b/server/agent/agent.go
index 6de4784..ed4706d 100644
--- a/server/agent/agent.go
+++ b/server/agent/agent.go
@@ -3,7 +3,7 @@
import (
"context"
"fmt"
- "log"
+ "log/slog"
"os"
"path/filepath"
"strings"
@@ -11,6 +11,7 @@
"github.com/iomodo/staff/git"
"github.com/iomodo/staff/llm"
+ _ "github.com/iomodo/staff/llm/openai" // Import for side effects (registers provider)
"github.com/iomodo/staff/tm"
)
@@ -58,10 +59,11 @@
gitInterface git.GitInterface
ctx context.Context
cancel context.CancelFunc
+ logger *slog.Logger
}
// NewAgent creates a new agent instance
-func NewAgent(config AgentConfig) (*Agent, error) {
+func NewAgent(config AgentConfig, logger *slog.Logger) (*Agent, error) {
// Validate configuration
if err := validateConfig(config); err != nil {
return nil, fmt.Errorf("invalid config: %w", err)
@@ -89,7 +91,7 @@
Timeout: 30 * time.Second,
PullRequestProvider: gerritPRProvider,
}
- gitInterface = git.NewGitWithPullRequests(config.GitRepoPath, gitConfig, gerritPRProvider)
+ gitInterface = git.NewGitWithPullRequests(config.GitRepoPath, gitConfig, gerritPRProvider, logger)
} else {
// Use default git interface (GitHub)
gitInterface = git.DefaultGit(config.GitRepoPath)
@@ -104,6 +106,7 @@
gitInterface: gitInterface,
ctx: ctx,
cancel: cancel,
+ logger: logger,
}
return agent, nil
@@ -134,8 +137,8 @@
// Run starts the agent's main loop
func (a *Agent) Run() error {
- log.Printf("Starting agent %s (%s)", a.Config.Name, a.Config.Role)
- defer log.Printf("Agent %s stopped", a.Config.Name)
+ a.logger.Info("Starting agent", slog.String("name", a.Config.Name), slog.String("role", a.Config.Role))
+ defer a.logger.Info("Agent stopped", slog.String("name", a.Config.Name))
// Initialize git repository if needed
if err := a.initializeGit(); err != nil {
@@ -149,7 +152,7 @@
return a.ctx.Err()
default:
if err := a.processNextTask(); err != nil {
- log.Printf("Error processing task: %v", err)
+ a.logger.Error("Error processing task", slog.String("error", err.Error()))
// Continue running even if there's an error
time.Sleep(30 * time.Second)
}
@@ -159,7 +162,7 @@
// Stop stops the agent
func (a *Agent) Stop() {
- log.Printf("Stopping agent %s", a.Config.Name)
+ a.logger.Info("Stopping agent", slog.String("name", a.Config.Name))
a.cancel()
if a.llmProvider != nil {
a.llmProvider.Close()
@@ -248,7 +251,7 @@
}
}
} else {
- log.Printf("Already on target branch: %s", a.Config.GitBranch)
+ a.logger.Info("Already on target branch", slog.String("branch", a.Config.GitBranch))
}
}
@@ -280,7 +283,7 @@
return nil
}
- log.Printf("Processing task: %s - %s", taskToProcess.ID, taskToProcess.Title)
+ a.logger.Info("Processing task", slog.String("id", taskToProcess.ID), slog.String("title", taskToProcess.Title))
// Start the task
startedTask, err := a.Config.TaskManager.StartTask(ctx, taskToProcess.ID)
@@ -292,7 +295,7 @@
solution, err := a.processTaskWithLLM(startedTask)
if err != nil {
// Mark task as failed or retry
- log.Printf("Failed to process task with LLM: %v", err)
+ a.logger.Error("Failed to process task with LLM", slog.String("error", err.Error()))
return err
}
@@ -306,7 +309,7 @@
return fmt.Errorf("failed to complete task: %w", err)
}
- log.Printf("Successfully completed task: %s", startedTask.ID)
+ a.logger.Info("Successfully completed task", slog.String("id", startedTask.ID))
return nil
}
@@ -416,7 +419,7 @@
if err := a.gitInterface.Push(ctx, "origin", gerritRef, git.PushOptions{}); err != nil {
return fmt.Errorf("failed to push to Gerrit: %w", err)
}
- log.Printf("Created Gerrit change for task %s by pushing to %s", task.ID, gerritRef)
+ a.logger.Info("Created Gerrit change for task", slog.String("id", task.ID), slog.String("ref", gerritRef))
} else {
// For GitHub: Push branch and create PR
if err := a.gitInterface.Push(ctx, "origin", branchName, git.PushOptions{SetUpstream: true}); err != nil {
@@ -438,7 +441,7 @@
return fmt.Errorf("failed to create pull request: %w", err)
}
- log.Printf("Created pull request for task %s: %s (ID: %s)", task.ID, pr.Title, pr.ID)
+ a.logger.Info("Created pull request for task", slog.String("id", task.ID), slog.String("title", pr.Title), slog.String("pr_id", pr.ID))
}
return nil
diff --git a/server/agent/agent_test.go b/server/agent/agent_test.go
index 405e5b7..6ec2adc 100644
--- a/server/agent/agent_test.go
+++ b/server/agent/agent_test.go
@@ -2,6 +2,7 @@
import (
"context"
+ "log/slog"
"os"
"path/filepath"
"testing"
@@ -104,8 +105,11 @@
err = gitInterface.SetUserConfig(ctx, userConfig)
require.NoError(t, err)
+ // Create logger for testing
+ logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
// Create task manager
- taskManager := git_tm.NewGitTaskManager(gitInterface, tasksDir)
+ taskManager := git_tm.NewGitTaskManagerWithLogger(gitInterface, tasksDir, logger)
// Create LLM config (using a mock configuration)
llmConfig := llm.Config{
@@ -132,6 +136,9 @@
GitBranch: "main",
}
+ // Create logger for testing
+ logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
// Create agent with mock LLM provider
agent := &Agent{
Config: config,
@@ -139,6 +146,7 @@
gitInterface: git.DefaultGit(codeRepoDir),
ctx: context.Background(),
cancel: func() {},
+ logger: logger,
}
cleanup := func() {
@@ -150,8 +158,73 @@
}
func TestNewAgent(t *testing.T) {
- agent, cleanup := setupTestAgent(t)
- defer cleanup()
+ // Create temporary directories
+ tempDir, err := os.MkdirTemp("", "agent-test")
+ require.NoError(t, err)
+ defer os.RemoveAll(tempDir)
+
+ tasksDir := filepath.Join(tempDir, "tasks")
+ workspaceDir := filepath.Join(tempDir, "workspace")
+ codeRepoDir := filepath.Join(tempDir, "code-repo")
+
+ // Create directories
+ require.NoError(t, os.MkdirAll(tasksDir, 0755))
+ require.NoError(t, os.MkdirAll(workspaceDir, 0755))
+ require.NoError(t, os.MkdirAll(codeRepoDir, 0755))
+
+ // Initialize git repositories
+ gitInterface := git.DefaultGit(tasksDir)
+ ctx := context.Background()
+
+ err = gitInterface.Init(ctx, tasksDir)
+ require.NoError(t, err)
+
+ // Set git user config
+ userConfig := git.UserConfig{
+ Name: "Test User",
+ Email: "test@example.com",
+ }
+ err = gitInterface.SetUserConfig(ctx, userConfig)
+ require.NoError(t, err)
+
+ // Create logger for testing
+ logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
+ // Create task manager
+ taskManager := git_tm.NewGitTaskManagerWithLogger(gitInterface, tasksDir, logger)
+
+ // Create LLM config (using a mock configuration)
+ llmConfig := llm.Config{
+ Provider: llm.ProviderOpenAI,
+ APIKey: "test-key",
+ BaseURL: "https://api.openai.com/v1",
+ Timeout: 30 * time.Second,
+ }
+
+ // Create agent config
+ config := AgentConfig{
+ Name: "test-agent",
+ Role: "Test Engineer",
+ GitUsername: "test-agent",
+ GitEmail: "test-agent@test.com",
+ WorkingDir: workspaceDir,
+ LLMProvider: llm.ProviderOpenAI,
+ LLMModel: "gpt-3.5-turbo",
+ LLMConfig: llmConfig,
+ SystemPrompt: "You are a test agent. Provide simple, clear solutions.",
+ TaskManager: taskManager,
+ GitRepoPath: codeRepoDir,
+ GitRemote: "origin",
+ GitBranch: "main",
+ }
+
+ // Create logger for testing
+ logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
+ // Create agent using NewAgent function
+ agent, err := NewAgent(config, logger)
+ require.NoError(t, err)
+ defer agent.Stop()
assert.NotNil(t, agent)
assert.Equal(t, "test-agent", agent.Config.Name)
diff --git a/server/agent/example.go b/server/agent/example.go
index 1233bdc..a7faea9 100644
--- a/server/agent/example.go
+++ b/server/agent/example.go
@@ -2,7 +2,8 @@
import (
"context"
- "log"
+ "log/slog"
+ "os"
"time"
"github.com/iomodo/staff/git"
@@ -13,11 +14,14 @@
// ExampleAgent demonstrates how to create and run an agent
func ExampleAgent() {
+ // Create logger
+ logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
// Create git interface for task management
gitInterface := git.DefaultGit("./tasks-repo")
// Create task manager
- taskManager := git_tm.NewGitTaskManager(gitInterface, "./tasks-repo")
+ taskManager := git_tm.NewGitTaskManagerWithLogger(gitInterface, "./tasks-repo", logger)
// Create LLM configuration
llmConfig := llm.Config{
@@ -57,9 +61,10 @@
}
// Create agent
- agent, err := NewAgent(config)
+ agent, err := NewAgent(config, logger)
if err != nil {
- log.Fatalf("Failed to create agent: %v", err)
+ logger.Error("Failed to create agent", slog.String("error", err.Error()))
+ os.Exit(1)
}
// Create a sample task
@@ -71,15 +76,16 @@
Priority: tm.PriorityHigh,
})
if err != nil {
- log.Fatalf("Failed to create task: %v", err)
+ logger.Error("Failed to create task", slog.String("error", err.Error()))
+ os.Exit(1)
}
- log.Printf("Created task: %s", task.ID)
+ logger.Info("Created task", slog.String("id", task.ID))
// Run the agent (this will process tasks in an infinite loop)
go func() {
if err := agent.Run(); err != nil {
- log.Printf("Agent stopped with error: %v", err)
+ logger.Error("Agent stopped with error", slog.String("error", err.Error()))
}
}()
@@ -92,9 +98,12 @@
// ExampleMultipleAgents demonstrates how to create multiple agents with different roles
func ExampleMultipleAgents() {
+ // Create logger
+ logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
// Create shared git interface for task management
gitInterface := git.DefaultGit("./tasks-repo")
- taskManager := git_tm.NewGitTaskManager(gitInterface, "./tasks-repo")
+ taskManager := git_tm.NewGitTaskManagerWithLogger(gitInterface, "./tasks-repo", logger)
// Create agents with different roles
agents := []AgentConfig{
@@ -177,16 +186,16 @@
// Create and start all agents
for _, config := range agents {
- agent, err := NewAgent(config)
+ agent, err := NewAgent(config, logger)
if err != nil {
- log.Printf("Failed to create agent %s: %v", config.Name, err)
+ logger.Error("Failed to create agent", slog.String("name", config.Name), slog.String("error", err.Error()))
continue
}
go func(agent *Agent, name string) {
- log.Printf("Starting agent: %s", name)
+ logger.Info("Starting agent", slog.String("name", name))
if err := agent.Run(); err != nil {
- log.Printf("Agent %s stopped with error: %v", name, err)
+ logger.Error("Agent stopped with error", slog.String("name", name), slog.String("error", err.Error()))
}
}(agent, config.Name)
}