Enhance deployment system with retry functionality and improved UX

Major Improvements:
- Added retry deployment buttons in machine list for failed deployments
- Added retry button in SSH console modal footer for enhanced UX
- Enhanced deployment process with comprehensive cleanup of existing services
- Improved binary installation with password-based sudo authentication
- Updated configuration generation to include all required sections (agent, ai, network, security)
- Fixed deployment verification and error handling

Security Enhancements:
- Enhanced verifiedStopExistingServices with thorough cleanup process
- Improved binary copying with proper sudo authentication
- Added comprehensive configuration validation

UX Improvements:
- Users can retry deployments without re-running machine discovery
- Retry buttons available from both machine list and console modal
- Real-time deployment progress with detailed console output
- Clear error states with actionable retry options

Technical Changes:
- Modified ServiceDeployment.tsx with retry button components
- Enhanced api/setup_manager.go with improved deployment functions
- Updated main.go with command line argument support (--config, --setup)
- Added comprehensive zero-trust security validation system

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-08-31 10:23:27 +10:00
parent df4d98bf30
commit be761cfe20
234 changed files with 7508 additions and 38528 deletions

322
internal/hap/terminal.go Normal file
View File

@@ -0,0 +1,322 @@
package hap
import (
"bufio"
"context"
"fmt"
"os"
"strings"
"time"
"chorus.services/bzzz/internal/common/runtime"
"chorus.services/bzzz/logging"
)
// TerminalInterface provides a terminal-based interface for human agents
type TerminalInterface struct {
services *runtime.RuntimeServices
logger logging.Logger
running bool
scanner *bufio.Scanner
}
// NewTerminalInterface creates a new terminal interface
func NewTerminalInterface(services *runtime.RuntimeServices, logger logging.Logger) *TerminalInterface {
return &TerminalInterface{
services: services,
logger: logger,
running: false,
scanner: bufio.NewScanner(os.Stdin),
}
}
// Start begins the terminal interface
func (ti *TerminalInterface) Start(ctx context.Context) error {
if ti.running {
return fmt.Errorf("terminal interface is already running")
}
ti.logger.Info("👤 Starting Human Agent Portal terminal interface")
// Display welcome message
ti.displayWelcome()
// Start command processing in background
go ti.processCommands(ctx)
ti.running = true
ti.logger.Info("✅ Terminal interface ready for human interaction")
return nil
}
// Stop gracefully stops the terminal interface
func (ti *TerminalInterface) Stop(ctx context.Context) error {
if !ti.running {
return nil
}
ti.logger.Info("🛑 Stopping terminal interface")
ti.running = false
fmt.Println("\n👋 Human Agent Portal shutting down. Goodbye!")
return nil
}
// displayWelcome shows the welcome message and commands
func (ti *TerminalInterface) displayWelcome() {
fmt.Println("\n" + strings.Repeat("=", 60))
fmt.Println("🎯 BZZZ Human Agent Portal (HAP)")
fmt.Println(" Welcome to collaborative AI task coordination")
fmt.Println(strings.Repeat("=", 60))
if ti.services.Node != nil {
fmt.Printf("📍 Node ID: %s\n", ti.services.Node.ID().ShortString())
}
if ti.services.Config != nil {
fmt.Printf("🤖 Agent ID: %s\n", ti.services.Config.Agent.ID)
if ti.services.Config.Agent.Role != "" {
fmt.Printf("🎭 Role: %s\n", ti.services.Config.Agent.Role)
}
}
if ti.services.Node != nil {
fmt.Printf("🌐 Connected Peers: %d\n", ti.services.Node.ConnectedPeers())
}
fmt.Println("\n📋 Available Commands:")
fmt.Println(" status - Show system status")
fmt.Println(" peers - List connected peers")
fmt.Println(" send <msg> - Send message to coordination channel")
fmt.Println(" role - Show role information")
fmt.Println(" tasks - Show task information")
fmt.Println(" health - Show health status")
fmt.Println(" help - Show this help message")
fmt.Println(" quit/exit - Exit the interface")
fmt.Println(strings.Repeat("-", 60))
fmt.Print("HAP> ")
}
// processCommands handles user input and commands
func (ti *TerminalInterface) processCommands(ctx context.Context) {
for ti.running && ti.scanner.Scan() {
input := strings.TrimSpace(ti.scanner.Text())
if input == "" {
fmt.Print("HAP> ")
continue
}
// Parse command and arguments
parts := strings.Fields(input)
command := strings.ToLower(parts[0])
switch command {
case "quit", "exit":
ti.running = false
return
case "help":
ti.showHelp()
case "status":
ti.showStatus()
case "peers":
ti.showPeers()
case "role":
ti.showRole()
case "tasks":
ti.showTasks()
case "health":
ti.showHealth()
case "send":
if len(parts) < 2 {
fmt.Println("❌ Usage: send <message>")
} else {
message := strings.Join(parts[1:], " ")
ti.sendMessage(message)
}
default:
fmt.Printf("❌ Unknown command: %s (type 'help' for available commands)\n", command)
}
fmt.Print("HAP> ")
}
}
// showHelp displays the help message
func (ti *TerminalInterface) showHelp() {
fmt.Println("\n📋 HAP Commands:")
fmt.Println(" status - Show current system status")
fmt.Println(" peers - List all connected P2P peers")
fmt.Println(" send <msg> - Send message to coordination channel")
fmt.Println(" role - Display role and capability information")
fmt.Println(" tasks - Show active tasks (if any)")
fmt.Println(" health - Display system health status")
fmt.Println(" help - Show this help message")
fmt.Println(" quit/exit - Exit the Human Agent Portal")
}
// showStatus displays the current system status
func (ti *TerminalInterface) showStatus() {
fmt.Println("\n📊 System Status:")
fmt.Println(strings.Repeat("-", 40))
if ti.services.Node != nil {
fmt.Printf("🌐 P2P Status: Connected (%d peers)\n", ti.services.Node.ConnectedPeers())
fmt.Printf("📍 Node ID: %s\n", ti.services.Node.ID().ShortString())
}
if ti.services.Config != nil {
fmt.Printf("🤖 Agent ID: %s\n", ti.services.Config.Agent.ID)
fmt.Printf("🎭 Role: %s\n", ti.services.Config.Agent.Role)
fmt.Printf("🎯 Specialization: %s\n", ti.services.Config.Agent.Specialization)
}
// Service status
fmt.Printf("📡 PubSub: %s\n", ti.getServiceStatus("PubSub", ti.services.PubSub != nil))
fmt.Printf("🕸️ DHT: %s\n", ti.getServiceStatus("DHT", ti.services.DHT != nil))
fmt.Printf("🔗 UCXI: %s\n", ti.getServiceStatus("UCXI", ti.services.UCXIServer != nil))
fmt.Printf("🗳️ Elections: %s\n", ti.getServiceStatus("Elections", ti.services.ElectionManager != nil))
fmt.Printf("❤️ Health: %s\n", ti.getServiceStatus("Health", ti.services.HealthManager != nil))
fmt.Printf("⏰ Uptime: %s\n", time.Since(time.Now().Add(-5*time.Minute)).String()) // Placeholder
}
// showPeers displays connected peers
func (ti *TerminalInterface) showPeers() {
fmt.Println("\n🌐 Connected Peers:")
fmt.Println(strings.Repeat("-", 40))
if ti.services.Node != nil {
peerCount := ti.services.Node.ConnectedPeers()
fmt.Printf("Total Connected: %d\n", peerCount)
if peerCount == 0 {
fmt.Println("No peers currently connected")
fmt.Println("💡 Tip: Make sure other BZZZ nodes are running on your network")
} else {
fmt.Println("🔍 Use P2P tools to see detailed peer information")
}
} else {
fmt.Println("❌ P2P node not available")
}
}
// showRole displays role and capability information
func (ti *TerminalInterface) showRole() {
fmt.Println("\n🎭 Role Information:")
fmt.Println(strings.Repeat("-", 40))
if ti.services.Config != nil {
cfg := ti.services.Config
fmt.Printf("Role: %s\n", cfg.Agent.Role)
fmt.Printf("Expertise: %v\n", cfg.Agent.Expertise)
fmt.Printf("Reports To: %v\n", cfg.Agent.ReportsTo)
fmt.Printf("Deliverables: %v\n", cfg.Agent.Deliverables)
fmt.Printf("Capabilities: %v\n", cfg.Agent.Capabilities)
fmt.Printf("Specialization: %s\n", cfg.Agent.Specialization)
// Authority level
if authority, err := cfg.GetRoleAuthority(cfg.Agent.Role); err == nil {
fmt.Printf("Authority Level: %s\n", authority)
}
} else {
fmt.Println("❌ Configuration not available")
}
}
// showTasks displays task information
func (ti *TerminalInterface) showTasks() {
fmt.Println("\n📋 Task Information:")
fmt.Println(strings.Repeat("-", 40))
// HAP doesn't execute tasks like agents, but can show coordination status
fmt.Println("📝 HAP Role: Human interaction facilitator")
fmt.Println("🎯 Purpose: Coordinate with autonomous agents")
fmt.Println("💼 Current Mode: Interactive terminal")
if ti.services.TaskCoordinator != nil {
fmt.Println("✅ Task coordination system is active")
} else {
fmt.Println("❌ Task coordination system not available")
}
}
// showHealth displays health status
func (ti *TerminalInterface) showHealth() {
fmt.Println("\n❤ Health Status:")
fmt.Println(strings.Repeat("-", 40))
if ti.services.HealthManager != nil {
status := ti.services.HealthManager.GetOverallStatus()
healthIcon := "✅"
if !status.Healthy {
healthIcon = "❌"
}
fmt.Printf("%s Overall Health: %s\n", healthIcon, ti.boolToStatus(status.Healthy))
fmt.Printf("📋 Details: %s\n", status.Message)
fmt.Printf("⏰ Last Check: %s\n", status.Timestamp.Format(time.RFC3339))
} else {
fmt.Println("❌ Health manager not available")
}
}
// sendMessage sends a message to the coordination channel
func (ti *TerminalInterface) sendMessage(message string) {
if ti.services.PubSub == nil {
fmt.Println("❌ PubSub not available - cannot send message")
return
}
// Create a human-authored message
messageData := map[string]interface{}{
"type": "human_message",
"author": "human",
"node_id": ti.services.Node.ID().ShortString(),
"agent_id": ti.services.Config.Agent.ID,
"role": ti.services.Config.Agent.Role,
"message": message,
"timestamp": time.Now().Unix(),
}
// Send to coordination channel
if err := ti.services.PubSub.PublishBzzzMessage("coordination", messageData); err != nil {
fmt.Printf("❌ Failed to send message: %v\n", err)
} else {
fmt.Printf("📤 Message sent to coordination channel\n")
fmt.Printf("💬 \"%s\"\n", message)
}
}
// Helper functions
func (ti *TerminalInterface) getServiceStatus(serviceName string, available bool) string {
if available {
return "✅ Active"
}
return "❌ Inactive"
}
func (ti *TerminalInterface) boolToStatus(b bool) string {
if b {
return "Healthy"
}
return "Unhealthy"
}
// IsRunning returns whether the terminal interface is running
func (ti *TerminalInterface) IsRunning() bool {
return ti.running
}
// GetServices returns the runtime services
func (ti *TerminalInterface) GetServices() *runtime.RuntimeServices {
return ti.services
}