Implement initial scan logic and council formation for WHOOSH project kickoffs
- Replace incremental sync with full scan for new repositories - Add initial_scan status to bypass Since parameter filtering - Implement council formation detection for Design Brief issues - Add version display to WHOOSH UI header for debugging - Fix Docker token authentication with trailing newline removal - Add comprehensive council orchestration with Docker Swarm integration - Include BACKBEAT prototype integration for distributed timing - Support council-specific agent roles and deployment strategies - Transition repositories to active status after content discovery Key architectural improvements: - Full scan approach for new project detection vs incremental sync - Council formation triggered by chorus-entrypoint labeled Design Briefs - Proper token handling and authentication for Gitea API calls - Support for both initial discovery and ongoing task monitoring This enables autonomous project kickoff workflows where Design Brief issues automatically trigger formation of specialized agent councils for new projects. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,12 +11,15 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/chorus-services/whoosh/internal/agents"
|
||||
"github.com/chorus-services/whoosh/internal/backbeat"
|
||||
"github.com/chorus-services/whoosh/internal/composer"
|
||||
"github.com/chorus-services/whoosh/internal/config"
|
||||
"github.com/chorus-services/whoosh/internal/council"
|
||||
"github.com/chorus-services/whoosh/internal/database"
|
||||
"github.com/chorus-services/whoosh/internal/gitea"
|
||||
"github.com/chorus-services/whoosh/internal/monitor"
|
||||
"github.com/chorus-services/whoosh/internal/orchestrator"
|
||||
"github.com/chorus-services/whoosh/internal/p2p"
|
||||
"github.com/chorus-services/whoosh/internal/tasks"
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -27,6 +30,14 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// Global version variable set by main package
|
||||
var version = "development"
|
||||
|
||||
// SetVersion sets the global version variable
|
||||
func SetVersion(v string) {
|
||||
version = v
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
config *config.Config
|
||||
db *database.DB
|
||||
@@ -35,11 +46,15 @@ type Server struct {
|
||||
giteaClient *gitea.Client
|
||||
webhookHandler *gitea.WebhookHandler
|
||||
p2pDiscovery *p2p.Discovery
|
||||
agentRegistry *agents.Registry
|
||||
backbeat *backbeat.Integration
|
||||
teamComposer *composer.Service
|
||||
councilComposer *council.CouncilComposer
|
||||
taskService *tasks.Service
|
||||
giteaIntegration *tasks.GiteaIntegration
|
||||
repoMonitor *monitor.Monitor
|
||||
swarmManager *orchestrator.SwarmManager
|
||||
agentDeployer *orchestrator.AgentDeployer
|
||||
}
|
||||
|
||||
func NewServer(cfg *config.Config, db *database.DB) (*Server, error) {
|
||||
@@ -47,19 +62,49 @@ func NewServer(cfg *config.Config, db *database.DB) (*Server, error) {
|
||||
taskService := tasks.NewService(db.Pool)
|
||||
giteaIntegration := tasks.NewGiteaIntegration(taskService, gitea.NewClient(cfg.GITEA), nil)
|
||||
|
||||
// Initialize repository monitor
|
||||
repoMonitor := monitor.NewMonitor(db.Pool, cfg.GITEA)
|
||||
// Initialize P2P discovery and agent registry
|
||||
p2pDiscovery := p2p.NewDiscovery()
|
||||
agentRegistry := agents.NewRegistry(db.Pool, p2pDiscovery)
|
||||
|
||||
// Initialize team composer
|
||||
teamComposer := composer.NewService(db.Pool, nil) // Use default config
|
||||
|
||||
// Initialize council composer for project kickoffs
|
||||
councilComposer := council.NewCouncilComposer(db.Pool)
|
||||
|
||||
// Initialize Docker Swarm orchestrator services conditionally
|
||||
var swarmManager *orchestrator.SwarmManager
|
||||
var agentDeployer *orchestrator.AgentDeployer
|
||||
|
||||
if cfg.Docker.Enabled {
|
||||
var err error
|
||||
swarmManager, err = orchestrator.NewSwarmManager("", "registry.home.deepblack.cloud")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create swarm manager: %w", err)
|
||||
}
|
||||
|
||||
agentDeployer = orchestrator.NewAgentDeployer(swarmManager, db.Pool, "registry.home.deepblack.cloud")
|
||||
} else {
|
||||
log.Warn().Msg("🐳 Docker integration disabled - council agent deployment unavailable")
|
||||
}
|
||||
|
||||
// Initialize repository monitor with team composer, council composer, and agent deployer
|
||||
repoMonitor := monitor.NewMonitor(db.Pool, cfg.GITEA, teamComposer, councilComposer, agentDeployer)
|
||||
|
||||
s := &Server{
|
||||
config: cfg,
|
||||
db: db,
|
||||
giteaClient: gitea.NewClient(cfg.GITEA),
|
||||
webhookHandler: gitea.NewWebhookHandler(cfg.GITEA.WebhookToken),
|
||||
p2pDiscovery: p2p.NewDiscovery(),
|
||||
teamComposer: composer.NewService(db.Pool, nil), // Use default config
|
||||
p2pDiscovery: p2pDiscovery,
|
||||
agentRegistry: agentRegistry,
|
||||
teamComposer: teamComposer,
|
||||
councilComposer: councilComposer,
|
||||
taskService: taskService,
|
||||
giteaIntegration: giteaIntegration,
|
||||
repoMonitor: repoMonitor,
|
||||
swarmManager: swarmManager,
|
||||
agentDeployer: agentDeployer,
|
||||
}
|
||||
|
||||
// Initialize BACKBEAT integration if enabled
|
||||
@@ -206,6 +251,11 @@ func (s *Server) Start(ctx context.Context) error {
|
||||
return fmt.Errorf("failed to start P2P discovery: %w", err)
|
||||
}
|
||||
|
||||
// Start agent registry service
|
||||
if err := s.agentRegistry.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start agent registry: %w", err)
|
||||
}
|
||||
|
||||
// Start repository monitoring service
|
||||
if s.repoMonitor != nil {
|
||||
go func() {
|
||||
@@ -237,6 +287,11 @@ func (s *Server) Shutdown(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Stop agent registry service
|
||||
if err := s.agentRegistry.Stop(); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to stop agent registry service")
|
||||
}
|
||||
|
||||
// Stop P2P discovery service
|
||||
if err := s.p2pDiscovery.Stop(); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to stop P2P discovery service")
|
||||
@@ -1778,7 +1833,10 @@ func (s *Server) dashboardHandler(w http.ResponseWriter, r *http.Request) {
|
||||
<body>
|
||||
<div class="header">
|
||||
<div class="header-content">
|
||||
<div class="logo">🎭 WHOOSH</div>
|
||||
<div style="display: flex; align-items: center;">
|
||||
<div class="logo">🎭 WHOOSH</div>
|
||||
<div style="margin-left: 16px; font-size: 14px; opacity: 0.8;">v` + version + `</div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center;">
|
||||
<span class="status-dot"></span>
|
||||
<span>System Online</span>
|
||||
|
||||
Reference in New Issue
Block a user