package main import ( "context" "fmt" "log" "net/http" "os" "path/filepath" "time" "chorus/api" "chorus/coordinator" "chorus/discovery" "chorus/internal/backbeat" "chorus/internal/licensing" "chorus/internal/logging" "chorus/p2p" "chorus/pkg/config" "chorus/pkg/dht" "chorus/pkg/election" "chorus/pkg/health" "chorus/pkg/shutdown" "chorus/pkg/ucxi" "chorus/pkg/ucxl" "chorus/pubsub" "chorus/reasoning" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" ) const ( AppName = "CHORUS" AppVersion = "0.1.0-dev" ) // SimpleLogger provides basic logging implementation type SimpleLogger struct{} func (l *SimpleLogger) Info(msg string, args ...interface{}) { log.Printf("[INFO] "+msg, args...) } func (l *SimpleLogger) Warn(msg string, args ...interface{}) { log.Printf("[WARN] "+msg, args...) } func (l *SimpleLogger) Error(msg string, args ...interface{}) { log.Printf("[ERROR] "+msg, args...) } // SimpleTaskTracker tracks active tasks for availability reporting type SimpleTaskTracker struct { maxTasks int activeTasks map[string]bool decisionPublisher *ucxl.DecisionPublisher } // GetActiveTasks returns list of active task IDs func (t *SimpleTaskTracker) GetActiveTasks() []string { tasks := make([]string, 0, len(t.activeTasks)) for taskID := range t.activeTasks { tasks = append(tasks, taskID) } return tasks } // GetMaxTasks returns maximum number of concurrent tasks func (t *SimpleTaskTracker) GetMaxTasks() int { return t.maxTasks } // AddTask marks a task as active func (t *SimpleTaskTracker) AddTask(taskID string) { t.activeTasks[taskID] = true } // RemoveTask marks a task as completed and publishes decision if publisher available func (t *SimpleTaskTracker) RemoveTask(taskID string) { delete(t.activeTasks, taskID) // Publish task completion decision if publisher is available if t.decisionPublisher != nil { t.publishTaskCompletion(taskID, true, "Task completed successfully", nil) } } // publishTaskCompletion publishes a task completion decision to DHT func (t *SimpleTaskTracker) publishTaskCompletion(taskID string, success bool, summary string, filesModified []string) { if t.decisionPublisher == nil { return } if err := t.decisionPublisher.PublishTaskCompletion(taskID, success, summary, filesModified); err != nil { fmt.Printf("⚠️ Failed to publish task completion for %s: %v\n", taskID, err) } else { fmt.Printf("πŸ“€ Published task completion decision for: %s\n", taskID) } } func main() { // Early CLI handling: print help/version without requiring env/config for _, a := range os.Args[1:] { switch a { case "--help", "-h", "help": fmt.Printf("%s %s\n\n", AppName, AppVersion) fmt.Println("Usage:") fmt.Printf(" %s [--help] [--version]\n\n", filepath.Base(os.Args[0])) fmt.Println("Environment (common):") fmt.Println(" CHORUS_LICENSE_ID (required)") fmt.Println(" CHORUS_AGENT_ID (optional; auto-generated if empty)") fmt.Println(" CHORUS_P2P_PORT (default 9000)") fmt.Println(" CHORUS_API_PORT (default 8080)") fmt.Println(" CHORUS_HEALTH_PORT (default 8081)") fmt.Println(" CHORUS_DHT_ENABLED (default true)") fmt.Println(" CHORUS_BOOTSTRAP_PEERS (comma-separated multiaddrs)") fmt.Println(" OLLAMA_ENDPOINT (default http://localhost:11434)") fmt.Println() fmt.Println("Example:") fmt.Println(" CHORUS_LICENSE_ID=dev-123 \\") fmt.Println(" CHORUS_AGENT_ID=chorus-dev \\") fmt.Println(" CHORUS_P2P_PORT=9000 CHORUS_API_PORT=8080 ./chorus") return case "--version", "-v": fmt.Printf("%s %s\n", AppName, AppVersion) return } } // Initialize container-optimized logger logger := &SimpleLogger{} ctx, cancel := context.WithCancel(context.Background()) defer cancel() logger.Info("🎭 Starting CHORUS v%s - Container-First P2P Task Coordination", AppVersion) logger.Info("πŸ“¦ Container deployment of proven CHORUS functionality") // Load configuration from environment (no config files in containers) logger.Info("πŸ“‹ Loading configuration from environment variables...") cfg, err := config.LoadFromEnvironment() if err != nil { logger.Error("❌ Configuration error: %v", err) os.Exit(1) } logger.Info("βœ… Configuration loaded successfully") logger.Info("πŸ€– Agent ID: %s", cfg.Agent.ID) logger.Info("🎯 Specialization: %s", cfg.Agent.Specialization) // CRITICAL: Validate license before any P2P operations logger.Info("πŸ” Validating CHORUS license with KACHING...") licenseValidator := licensing.NewValidator(licensing.LicenseConfig{ LicenseID: cfg.License.LicenseID, ClusterID: cfg.License.ClusterID, KachingURL: cfg.License.KachingURL, }) if err := licenseValidator.Validate(); err != nil { logger.Error("❌ License validation failed: %v", err) logger.Error("πŸ’° CHORUS requires a valid license to operate") logger.Error("πŸ“ž Contact chorus.services for licensing information") os.Exit(1) } logger.Info("βœ… License validation successful - CHORUS authorized to run") // Initialize AI provider configuration logger.Info("🧠 Configuring AI provider: %s", cfg.AI.Provider) if err := initializeAIProvider(cfg, logger); err != nil { logger.Error("❌ AI provider initialization failed: %v", err) os.Exit(1) } logger.Info("βœ… AI provider configured successfully") // Initialize BACKBEAT integration var backbeatIntegration *backbeat.Integration backbeatIntegration, err = backbeat.NewIntegration(cfg, cfg.Agent.ID, logger) if err != nil { logger.Warn("⚠️ BACKBEAT integration initialization failed: %v", err) logger.Info("πŸ“ P2P operations will run without beat synchronization") } else { if err := backbeatIntegration.Start(ctx); err != nil { logger.Warn("⚠️ Failed to start BACKBEAT integration: %v", err) backbeatIntegration = nil } else { logger.Info("🎡 BACKBEAT integration started successfully") } } defer func() { if backbeatIntegration != nil { backbeatIntegration.Stop() } }() // Initialize P2P node node, err := p2p.NewNode(ctx) if err != nil { log.Fatalf("Failed to create P2P node: %v", err) } defer node.Close() logger.Info("🐝 CHORUS node started successfully") logger.Info("πŸ“ Node ID: %s", node.ID().ShortString()) logger.Info("πŸ”— Listening addresses:") for _, addr := range node.Addresses() { logger.Info(" %s/p2p/%s", addr, node.ID()) } // Initialize Hypercore-style logger for P2P coordination hlog := logging.NewHypercoreLog(node.ID()) hlog.Append(logging.PeerJoined, map[string]interface{}{"status": "started"}) logger.Info("πŸ“ Hypercore logger initialized") // Initialize mDNS discovery mdnsDiscovery, err := discovery.NewMDNSDiscovery(ctx, node.Host(), "chorus-peer-discovery") if err != nil { log.Fatalf("Failed to create mDNS discovery: %v", err) } defer mdnsDiscovery.Close() // Initialize PubSub with hypercore logging ps, err := pubsub.NewPubSubWithLogger(ctx, node.Host(), "chorus/coordination/v1", "hmmm/meta-discussion/v1", hlog) if err != nil { log.Fatalf("Failed to create PubSub: %v", err) } defer ps.Close() logger.Info("πŸ“‘ PubSub system initialized") // Join role-based topics if role is configured if cfg.Agent.Role != "" { reportsTo := []string{} if cfg.Agent.ReportsTo != "" { reportsTo = []string{cfg.Agent.ReportsTo} } if err := ps.JoinRoleBasedTopics(cfg.Agent.Role, cfg.Agent.Expertise, reportsTo); err != nil { logger.Warn("⚠️ Failed to join role-based topics: %v", err) } else { logger.Info("🎯 Joined role-based collaboration topics") } } // === Admin Election System === electionManager := election.NewElectionManager(ctx, cfg, node.Host(), ps, node.ID().ShortString()) // Set election callbacks with BACKBEAT integration electionManager.SetCallbacks( func(oldAdmin, newAdmin string) { logger.Info("πŸ‘‘ Admin changed: %s -> %s", oldAdmin, newAdmin) // Track admin change with BACKBEAT if available if backbeatIntegration != nil { operationID := fmt.Sprintf("admin-change-%d", time.Now().Unix()) if err := backbeatIntegration.StartP2POperation(operationID, "admin_change", 2, map[string]interface{}{ "old_admin": oldAdmin, "new_admin": newAdmin, }); err == nil { // Complete immediately as this is a state change, not a long operation backbeatIntegration.CompleteP2POperation(operationID, 1) } } // If this node becomes admin, enable SLURP functionality if newAdmin == node.ID().ShortString() { logger.Info("🎯 This node is now admin - enabling SLURP functionality") cfg.Slurp.Enabled = true // Apply admin role configuration if err := cfg.ApplyRoleDefinition("admin"); err != nil { logger.Warn("⚠️ Failed to apply admin role: %v", err) } } }, func(winner string) { logger.Info("πŸ† Election completed, winner: %s", winner) // Track election completion with BACKBEAT if available if backbeatIntegration != nil { operationID := fmt.Sprintf("election-completed-%d", time.Now().Unix()) if err := backbeatIntegration.StartP2POperation(operationID, "election", 1, map[string]interface{}{ "winner": winner, "node_id": node.ID().ShortString(), }); err == nil { backbeatIntegration.CompleteP2POperation(operationID, 1) } } }, ) if err := electionManager.Start(); err != nil { logger.Error("❌ Failed to start election manager: %v", err) } else { logger.Info("βœ… Election manager started with automated heartbeat management") } defer electionManager.Stop() // === DHT Storage and Decision Publishing === var dhtNode *dht.LibP2PDHT var encryptedStorage *dht.EncryptedDHTStorage var decisionPublisher *ucxl.DecisionPublisher if cfg.V2.DHT.Enabled { // Create DHT dhtNode, err = dht.NewLibP2PDHT(ctx, node.Host()) if err != nil { logger.Warn("⚠️ Failed to create DHT: %v", err) } else { logger.Info("πŸ•ΈοΈ DHT initialized") // Bootstrap DHT with BACKBEAT tracking if backbeatIntegration != nil { operationID := fmt.Sprintf("dht-bootstrap-%d", time.Now().Unix()) if err := backbeatIntegration.StartP2POperation(operationID, "dht_bootstrap", 4, nil); err == nil { backbeatIntegration.UpdateP2POperationPhase(operationID, backbeat.PhaseConnecting, 0) } if err := dhtNode.Bootstrap(); err != nil { logger.Warn("⚠️ DHT bootstrap failed: %v", err) backbeatIntegration.FailP2POperation(operationID, err.Error()) } else { backbeatIntegration.CompleteP2POperation(operationID, 1) } } else { if err := dhtNode.Bootstrap(); err != nil { logger.Warn("⚠️ DHT bootstrap failed: %v", err) } } // Connect to bootstrap peers if configured for _, addrStr := range cfg.V2.DHT.BootstrapPeers { addr, err := multiaddr.NewMultiaddr(addrStr) if err != nil { logger.Warn("⚠️ Invalid bootstrap address %s: %v", addrStr, err) continue } // Extract peer info from multiaddr info, err := peer.AddrInfoFromP2pAddr(addr) if err != nil { logger.Warn("⚠️ Failed to parse peer info from %s: %v", addrStr, err) continue } // Track peer discovery with BACKBEAT if available if backbeatIntegration != nil { operationID := fmt.Sprintf("peer-discovery-%d", time.Now().Unix()) if err := backbeatIntegration.StartP2POperation(operationID, "peer_discovery", 2, map[string]interface{}{ "peer_addr": addrStr, }); err == nil { backbeatIntegration.UpdateP2POperationPhase(operationID, backbeat.PhaseConnecting, 0) if err := node.Host().Connect(ctx, *info); err != nil { logger.Warn("⚠️ Failed to connect to bootstrap peer %s: %v", addrStr, err) backbeatIntegration.FailP2POperation(operationID, err.Error()) } else { logger.Info("πŸ”— Connected to DHT bootstrap peer: %s", addrStr) backbeatIntegration.CompleteP2POperation(operationID, 1) } } } else { if err := node.Host().Connect(ctx, *info); err != nil { logger.Warn("⚠️ Failed to connect to bootstrap peer %s: %v", addrStr, err) } else { logger.Info("πŸ”— Connected to DHT bootstrap peer: %s", addrStr) } } } // Initialize encrypted storage encryptedStorage = dht.NewEncryptedDHTStorage( ctx, node.Host(), dhtNode, cfg, node.ID().ShortString(), ) // Start cache cleanup encryptedStorage.StartCacheCleanup(5 * time.Minute) logger.Info("πŸ” Encrypted DHT storage initialized") // Initialize decision publisher decisionPublisher = ucxl.NewDecisionPublisher( ctx, cfg, encryptedStorage, node.ID().ShortString(), cfg.Agent.ID, ) logger.Info("πŸ“€ Decision publisher initialized") } } else { logger.Info("βšͺ DHT disabled in configuration") } defer func() { if dhtNode != nil { dhtNode.Close() } }() // === Task Coordination Integration === taskCoordinator := coordinator.NewTaskCoordinator( ctx, ps, hlog, cfg, node.ID().ShortString(), nil, // HMMM router placeholder ) taskCoordinator.Start() logger.Info("βœ… Task coordination system active") // Start HTTP API server httpServer := api.NewHTTPServer(cfg.Network.APIPort, hlog, ps) go func() { logger.Info("🌐 HTTP API server starting on :%d", cfg.Network.APIPort) if err := httpServer.Start(); err != nil && err != http.ErrServerClosed { logger.Error("❌ HTTP server error: %v", err) } }() defer httpServer.Stop() // === UCXI Server Integration === var ucxiServer *ucxi.Server if cfg.UCXL.Enabled && cfg.UCXL.Server.Enabled { storageDir := cfg.UCXL.Storage.Directory if storageDir == "" { storageDir = filepath.Join(os.TempDir(), "chorus-ucxi-storage") } storage, err := ucxi.NewBasicContentStorage(storageDir) if err != nil { logger.Warn("⚠️ Failed to create UCXI storage: %v", err) } else { resolver := ucxi.NewBasicAddressResolver(node.ID().ShortString()) resolver.SetDefaultTTL(cfg.UCXL.Resolution.CacheTTL) ucxiConfig := ucxi.ServerConfig{ Port: cfg.UCXL.Server.Port, BasePath: cfg.UCXL.Server.BasePath, Resolver: resolver, Storage: storage, Logger: ucxi.SimpleLogger{}, } ucxiServer = ucxi.NewServer(ucxiConfig) go func() { logger.Info("πŸ”— UCXI server starting on :%d", cfg.UCXL.Server.Port) if err := ucxiServer.Start(); err != nil && err != http.ErrServerClosed { logger.Error("❌ UCXI server error: %v", err) } }() defer func() { if ucxiServer != nil { ucxiServer.Stop() } }() } } else { logger.Info("βšͺ UCXI server disabled") } // Create simple task tracker taskTracker := &SimpleTaskTracker{ maxTasks: cfg.Agent.MaxTasks, activeTasks: make(map[string]bool), } // Connect decision publisher to task tracker if available if decisionPublisher != nil { taskTracker.decisionPublisher = decisionPublisher logger.Info("πŸ“€ Task completion decisions will be published to DHT") } // Announce capabilities and role go announceAvailability(ps, node.ID().ShortString(), taskTracker, logger) go announceCapabilitiesOnChange(ps, node.ID().ShortString(), cfg, logger) go announceRoleOnStartup(ps, node.ID().ShortString(), cfg, logger) // Start status reporting go statusReporter(node, logger) logger.Info("πŸ” Listening for peers on container network...") logger.Info("πŸ“‘ Ready for task coordination and meta-discussion") logger.Info("🎯 HMMM collaborative reasoning enabled") // === Comprehensive Health Monitoring & Graceful Shutdown === shutdownManager := shutdown.NewManager(30*time.Second, &simpleLogger{logger: logger}) healthManager := health.NewManager(node.ID().ShortString(), AppVersion, &simpleLogger{logger: logger}) healthManager.SetShutdownManager(shutdownManager) // Register health checks setupHealthChecks(healthManager, ps, node, dhtNode, backbeatIntegration) // Register components for graceful shutdown setupGracefulShutdown(shutdownManager, healthManager, node, ps, mdnsDiscovery, electionManager, httpServer, ucxiServer, taskCoordinator, dhtNode) // Start health monitoring if err := healthManager.Start(); err != nil { logger.Error("❌ Failed to start health manager: %v", err) } else { logger.Info("❀️ Health monitoring started") } // Start health HTTP server if err := healthManager.StartHTTPServer(cfg.Network.HealthPort); err != nil { logger.Error("❌ Failed to start health HTTP server: %v", err) } else { logger.Info("πŸ₯ Health endpoints available at http://localhost:%d/health", cfg.Network.HealthPort) } // Start shutdown manager shutdownManager.Start() logger.Info("πŸ›‘οΈ Graceful shutdown manager started") logger.Info("βœ… CHORUS system fully operational with health monitoring") // Wait for graceful shutdown shutdownManager.Wait() logger.Info("βœ… CHORUS system shutdown completed") } // Rest of the functions (setupHealthChecks, etc.) would be adapted from CHORUS... // For brevity, I'll include key functions but the full implementation would port all CHORUS functionality // simpleLogger implements basic logging for shutdown and health systems type simpleLogger struct { logger logging.Logger } func (l *simpleLogger) Info(msg string, args ...interface{}) { l.logger.Info(msg, args...) } func (l *simpleLogger) Warn(msg string, args ...interface{}) { l.logger.Warn(msg, args...) } func (l *simpleLogger) Error(msg string, args ...interface{}) { l.logger.Error(msg, args...) } // announceAvailability broadcasts current working status for task assignment func announceAvailability(ps *pubsub.PubSub, nodeID string, taskTracker *SimpleTaskTracker, logger logging.Logger) { ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() for ; ; <-ticker.C { currentTasks := taskTracker.GetActiveTasks() maxTasks := taskTracker.GetMaxTasks() isAvailable := len(currentTasks) < maxTasks status := "ready" if len(currentTasks) >= maxTasks { status = "busy" } else if len(currentTasks) > 0 { status = "working" } availability := map[string]interface{}{ "node_id": nodeID, "available_for_work": isAvailable, "current_tasks": len(currentTasks), "max_tasks": maxTasks, "last_activity": time.Now().Unix(), "status": status, "timestamp": time.Now().Unix(), } if err := ps.PublishBzzzMessage(pubsub.AvailabilityBcast, availability); err != nil { logger.Error("❌ Failed to announce availability: %v", err) } } } // statusReporter provides periodic status updates func statusReporter(node *p2p.Node, logger logging.Logger) { ticker := time.NewTicker(60 * time.Second) defer ticker.Stop() for ; ; <-ticker.C { peers := node.ConnectedPeers() logger.Info("πŸ“Š Status: %d connected peers", peers) } } // Placeholder functions for full CHORUS port - these would be fully implemented func announceCapabilitiesOnChange(ps *pubsub.PubSub, nodeID string, cfg *config.Config, logger logging.Logger) { // Implementation from CHORUS would go here } func announceRoleOnStartup(ps *pubsub.PubSub, nodeID string, cfg *config.Config, logger logging.Logger) { // Implementation from CHORUS would go here } func setupHealthChecks(healthManager *health.Manager, ps *pubsub.PubSub, node *p2p.Node, dhtNode *dht.LibP2PDHT, backbeatIntegration *backbeat.Integration) { // Add BACKBEAT health check if backbeatIntegration != nil { backbeatCheck := &health.HealthCheck{ Name: "backbeat", Description: "BACKBEAT timing integration health", Interval: 30 * time.Second, Timeout: 10 * time.Second, Enabled: true, Critical: false, Checker: func(ctx context.Context) health.CheckResult { healthInfo := backbeatIntegration.GetHealth() connected, _ := healthInfo["connected"].(bool) result := health.CheckResult{ Healthy: connected, Details: healthInfo, Timestamp: time.Now(), } if connected { result.Message = "BACKBEAT integration healthy and connected" } else { result.Message = "BACKBEAT integration not connected" } return result }, } healthManager.RegisterCheck(backbeatCheck) } // Implementation from CHORUS would go here - other health checks } func setupGracefulShutdown(shutdownManager *shutdown.Manager, healthManager *health.Manager, node *p2p.Node, ps *pubsub.PubSub, mdnsDiscovery interface{}, electionManager interface{}, httpServer *api.HTTPServer, ucxiServer *ucxi.Server, taskCoordinator interface{}, dhtNode *dht.LibP2PDHT) { // Implementation from CHORUS would go here } // initializeAIProvider configures the reasoning engine with the appropriate AI provider func initializeAIProvider(cfg *config.Config, logger logging.Logger) error { // Set the AI provider reasoning.SetAIProvider(cfg.AI.Provider) // Configure the selected provider switch cfg.AI.Provider { case "resetdata": if cfg.AI.ResetData.APIKey == "" { return fmt.Errorf("RESETDATA_API_KEY environment variable is required for resetdata provider") } resetdataConfig := reasoning.ResetDataConfig{ BaseURL: cfg.AI.ResetData.BaseURL, APIKey: cfg.AI.ResetData.APIKey, Model: cfg.AI.ResetData.Model, Timeout: cfg.AI.ResetData.Timeout, } reasoning.SetResetDataConfig(resetdataConfig) logger.Info("🌐 ResetData AI provider configured - Endpoint: %s, Model: %s", cfg.AI.ResetData.BaseURL, cfg.AI.ResetData.Model) case "ollama": reasoning.SetOllamaEndpoint(cfg.AI.Ollama.Endpoint) logger.Info("πŸ¦™ Ollama AI provider configured - Endpoint: %s", cfg.AI.Ollama.Endpoint) default: logger.Warn("⚠️ Unknown AI provider '%s', defaulting to resetdata", cfg.AI.Provider) if cfg.AI.ResetData.APIKey == "" { return fmt.Errorf("RESETDATA_API_KEY environment variable is required for default resetdata provider") } resetdataConfig := reasoning.ResetDataConfig{ BaseURL: cfg.AI.ResetData.BaseURL, APIKey: cfg.AI.ResetData.APIKey, Model: cfg.AI.ResetData.Model, Timeout: cfg.AI.ResetData.Timeout, } reasoning.SetResetDataConfig(resetdataConfig) reasoning.SetAIProvider("resetdata") } // Configure model selection reasoning.SetModelConfig( cfg.Agent.Models, cfg.Agent.ModelSelectionWebhook, cfg.Agent.DefaultReasoningModel, ) return nil }