Fix GitHub branch detection and complete task execution workflow
- Added dynamic branch detection that falls back to repository default branch - Fixed sandbox image reference to use local Docker registry - Completed full task execution pipeline: discovery → claim → sandbox → execution - Enhanced GitHub client to verify base branch existence and auto-correct - Successfully tested end-to-end task claiming and execution 🎉 MAJOR MILESTONE: Full Bzzz task execution workflow now functional\! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -76,6 +76,11 @@ func NewClient(ctx context.Context, config *Config) (*Client, error) {
|
||||
return nil, fmt.Errorf("failed to verify GitHub access: %w", err)
|
||||
}
|
||||
|
||||
// Verify base branch exists and update if needed
|
||||
if err := client.verifyBaseBranch(); err != nil {
|
||||
return nil, fmt.Errorf("failed to verify base branch: %w", err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
@@ -89,6 +94,25 @@ func (c *Client) verifyAccess() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyBaseBranch checks if the base branch exists and updates to default if not
|
||||
func (c *Client) verifyBaseBranch() error {
|
||||
// Try to get the configured base branch
|
||||
_, _, err := c.client.Git.GetRef(c.ctx, c.config.Owner, c.config.Repository, "heads/"+c.config.BaseBranch)
|
||||
if err != nil {
|
||||
// If the branch doesn't exist, get the repository's default branch
|
||||
repo, _, err := c.client.Repositories.Get(c.ctx, c.config.Owner, c.config.Repository)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get repository info: %w", err)
|
||||
}
|
||||
|
||||
// Update config to use the default branch
|
||||
if repo.DefaultBranch != nil {
|
||||
c.config.BaseBranch = *repo.DefaultBranch
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Task represents a Bzzz task as a GitHub issue
|
||||
type Task struct {
|
||||
ID int64 `json:"id"`
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/anthonyrawlins/bzzz/pkg/hive"
|
||||
"github.com/anthonyrawlins/bzzz/pkg/types"
|
||||
"github.com/anthonyrawlins/bzzz/pubsub"
|
||||
"github.com/anthonyrawlins/bzzz/reasoning"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
)
|
||||
|
||||
@@ -116,6 +115,7 @@ func (hi *HiveIntegration) syncRepositories() {
|
||||
AccessToken: hi.githubToken,
|
||||
Owner: repo.Owner,
|
||||
Repository: repo.Repository,
|
||||
BaseBranch: repo.Branch,
|
||||
}
|
||||
|
||||
client, err := NewClient(hi.ctx, githubConfig)
|
||||
@@ -304,7 +304,7 @@ func (hi *HiveIntegration) claimAndExecuteTask(task *types.EnhancedTask) {
|
||||
}
|
||||
|
||||
// executeTask executes a claimed task with reasoning and coordination
|
||||
func (hi *HiveIntegration) executeTask(task *EnhancedTask, repoClient *RepositoryClient) {
|
||||
func (hi *HiveIntegration) executeTask(task *types.EnhancedTask, repoClient *RepositoryClient) {
|
||||
// Define the dynamic topic for this task
|
||||
taskTopic := fmt.Sprintf("bzzz/meta/issue/%d", task.Number)
|
||||
hi.pubsub.JoinDynamicTopic(taskTopic)
|
||||
@@ -344,7 +344,7 @@ func (hi *HiveIntegration) executeTask(task *EnhancedTask, repoClient *Repositor
|
||||
}
|
||||
|
||||
// requestAssistance publishes a help request to the task-specific topic.
|
||||
func (hi *HiveIntegration) requestAssistance(task *EnhancedTask, reason, topic string) {
|
||||
func (hi *HiveIntegration) requestAssistance(task *types.EnhancedTask, reason, topic string) {
|
||||
fmt.Printf("🆘 Agent %s is requesting assistance for task #%d: %s\n", hi.config.AgentID, task.Number, reason)
|
||||
hi.hlog.Append(logging.TaskHelpRequested, map[string]interface{}{
|
||||
"task_id": task.Number,
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
package sandbox
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultDockerImage is the image used if a task does not specify one.
|
||||
DefaultDockerImage = "bzzz-sandbox:latest"
|
||||
DefaultDockerImage = "registry.home.deepblack.cloud/tony/bzzz-sandbox:latest"
|
||||
)
|
||||
|
||||
// Sandbox represents a stateful, isolated execution environment for a single task.
|
||||
@@ -62,7 +66,7 @@ func CreateSandbox(ctx context.Context, taskImage string) (*Sandbox, error) {
|
||||
hostConfig := &container.HostConfig{
|
||||
Binds: []string{fmt.Sprintf("%s:/home/agent/work", hostPath)},
|
||||
Resources: container.Resources{
|
||||
CPUs: 2,
|
||||
NanoCPUs: 2 * 1000000000, // 2 CPUs
|
||||
Memory: 2 * 1024 * 1024 * 1024, // 2GB
|
||||
},
|
||||
}
|
||||
@@ -98,7 +102,7 @@ func (s *Sandbox) DestroySandbox() error {
|
||||
}
|
||||
|
||||
// Define a timeout for stopping the container
|
||||
timeout := 30 * time.Second
|
||||
timeout := 30 // seconds
|
||||
|
||||
// Stop the container
|
||||
fmt.Printf("🛑 Stopping sandbox container %s...\n", s.ID[:12])
|
||||
@@ -184,7 +188,40 @@ func (s *Sandbox) WriteFile(path string, content []byte) error {
|
||||
|
||||
// Copy the file into the container
|
||||
dstPath := filepath.Join(s.Workspace, path)
|
||||
return s.dockerCli.CopyToContainer(s.ctx, tmpfile.Name(), s.ID, dstPath)
|
||||
|
||||
// Create tar archive of the file
|
||||
tarBuf := new(bytes.Buffer)
|
||||
tw := tar.NewWriter(tarBuf)
|
||||
|
||||
fileInfo, err := os.Stat(tmpfile.Name())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to stat temp file: %w", err)
|
||||
}
|
||||
|
||||
header := &tar.Header{
|
||||
Name: filepath.Base(path),
|
||||
Size: fileInfo.Size(),
|
||||
Mode: 0644,
|
||||
}
|
||||
|
||||
if err := tw.WriteHeader(header); err != nil {
|
||||
return fmt.Errorf("failed to write tar header: %w", err)
|
||||
}
|
||||
|
||||
fileContent, err := os.ReadFile(tmpfile.Name())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read temp file: %w", err)
|
||||
}
|
||||
|
||||
if _, err := tw.Write(fileContent); err != nil {
|
||||
return fmt.Errorf("failed to write to tar: %w", err)
|
||||
}
|
||||
|
||||
if err := tw.Close(); err != nil {
|
||||
return fmt.Errorf("failed to close tar writer: %w", err)
|
||||
}
|
||||
|
||||
return s.dockerCli.CopyToContainer(s.ctx, s.ID, filepath.Dir(dstPath), tarBuf, container.CopyToContainerOptions{})
|
||||
}
|
||||
|
||||
// ReadFile reads the content of a file from the sandbox's workspace.
|
||||
|
||||
Reference in New Issue
Block a user