 03d938037a
			
		
	
	03d938037a
	
	
	
		
			
			## Additional Changes: - Add test configurations and deployment artifacts - Update web assets and build manifests - Add version management scripts - Include local test configs (.bzzz/ directory) - Update internal runtime and agent configurations - Refresh Next.js build artifacts ## Final State: - Complete deployment system working end-to-end - ironwood successfully deployed and operational - All hardcoded values removed from codebase - Config generation and validation fully functional 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			184 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package runtime
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 
 | |
| 	"chorus.services/bzzz/pkg/config"
 | |
| )
 | |
| 
 | |
| // ConfigValidator validates configuration for specific binary types
 | |
| type ConfigValidator struct {
 | |
| 	binaryType BinaryType
 | |
| }
 | |
| 
 | |
| // NewConfigValidator creates a new config validator
 | |
| func NewConfigValidator(binaryType BinaryType) *ConfigValidator {
 | |
| 	return &ConfigValidator{
 | |
| 		binaryType: binaryType,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // ValidateForBinary validates configuration for the specified binary type
 | |
| func (v *ConfigValidator) ValidateForBinary(cfg *config.Config) error {
 | |
| 	// Common validation
 | |
| 	if err := v.validateCommonConfig(cfg); err != nil {
 | |
| 		return fmt.Errorf("common config validation failed: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	// Binary-specific validation
 | |
| 	switch v.binaryType {
 | |
| 	case BinaryTypeAgent:
 | |
| 		return v.validateAgentConfig(cfg)
 | |
| 	case BinaryTypeHAP:
 | |
| 		return v.validateHAPConfig(cfg)
 | |
| 	default:
 | |
| 		return fmt.Errorf("unknown binary type: %v", v.binaryType)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // validateCommonConfig validates common configuration for all binary types
 | |
| func (v *ConfigValidator) validateCommonConfig(cfg *config.Config) error {
 | |
| 	if cfg == nil {
 | |
| 		return fmt.Errorf("configuration is nil")
 | |
| 	}
 | |
| 
 | |
| 	// Validate agent configuration
 | |
| 	if cfg.Agent.ID == "" {
 | |
| 		return fmt.Errorf("agent ID is required")
 | |
| 	}
 | |
| 
 | |
| 	// Validate basic capabilities
 | |
| 	if len(cfg.Agent.Capabilities) == 0 {
 | |
| 		return fmt.Errorf("at least one capability is required")
 | |
| 	}
 | |
| 
 | |
| 	// P2P validation is handled in the main config validation
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // validateAgentConfig validates agent-specific configuration
 | |
| func (v *ConfigValidator) validateAgentConfig(cfg *config.Config) error {
 | |
| 	// Agent needs models for task execution
 | |
| 	if len(cfg.Agent.Models) == 0 {
 | |
| 		return fmt.Errorf("agent requires at least one model")
 | |
| 	}
 | |
| 
 | |
| 	// Agent needs specialization
 | |
| 	if cfg.Agent.Specialization == "" {
 | |
| 		return fmt.Errorf("agent specialization is required")
 | |
| 	}
 | |
| 
 | |
| 	// Validate max tasks
 | |
| 	if cfg.Agent.MaxTasks <= 0 {
 | |
| 		return fmt.Errorf("agent max_tasks must be greater than 0")
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // validateHAPConfig validates HAP-specific configuration
 | |
| func (v *ConfigValidator) validateHAPConfig(cfg *config.Config) error {
 | |
| 	// HAP has different requirements than agent
 | |
| 	// Models are optional for HAP (it facilitates human interaction)
 | |
| 	
 | |
| 	// HAP should have role configuration for proper P2P participation
 | |
| 	if cfg.Agent.Role == "" {
 | |
| 		return fmt.Errorf("HAP requires a role for P2P participation")
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // ValidateMultiBinaryDeployment validates that agent and HAP configs are compatible
 | |
| func ValidateMultiBinaryDeployment(agentConfig, hapConfig *config.Config) error {
 | |
| 	validators := []func(*config.Config, *config.Config) error{
 | |
| 		validateP2PCompatibility,
 | |
| 		validatePortAssignments,
 | |
| 		validateAgentIdentities,
 | |
| 		validateEncryptionKeys,
 | |
| 	}
 | |
| 
 | |
| 	for _, validator := range validators {
 | |
| 		if err := validator(agentConfig, hapConfig); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // validateP2PCompatibility ensures both configs can participate in same P2P mesh
 | |
| func validateP2PCompatibility(agentConfig, hapConfig *config.Config) error {
 | |
| 	// Check bootstrap peers compatibility for V2 DHT
 | |
| 	if len(agentConfig.V2.DHT.BootstrapPeers) != len(hapConfig.V2.DHT.BootstrapPeers) {
 | |
| 		return fmt.Errorf("bootstrap peers configuration differs between agent and HAP")
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // validatePortAssignments ensures no port conflicts
 | |
| func validatePortAssignments(agentConfig, hapConfig *config.Config) error {
 | |
| 	// Check UCXI ports if enabled
 | |
| 	if agentConfig.UCXL.Enabled && hapConfig.UCXL.Enabled {
 | |
| 		if agentConfig.UCXL.Server.Port == hapConfig.UCXL.Server.Port {
 | |
| 			return fmt.Errorf("UCXI port conflict: both configs use port %d", agentConfig.UCXL.Server.Port)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // validateAgentIdentities ensures agent IDs don't conflict
 | |
| func validateAgentIdentities(agentConfig, hapConfig *config.Config) error {
 | |
| 	if agentConfig.Agent.ID == hapConfig.Agent.ID {
 | |
| 		return fmt.Errorf("agent ID conflict: both configs use ID %s", agentConfig.Agent.ID)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // validateEncryptionKeys ensures encryption compatibility
 | |
| func validateEncryptionKeys(agentConfig, hapConfig *config.Config) error {
 | |
| 	// TODO: Implement encryption validation when V2 Security is available
 | |
| 	// Both should use same encryption settings for compatibility
 | |
| 	// if agentConfig.V2.Security.EncryptionEnabled != hapConfig.V2.Security.EncryptionEnabled {
 | |
| 	//	return fmt.Errorf("encryption settings mismatch")
 | |
| 	// }
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // CheckForRunningInstance checks if another instance is already running
 | |
| func CheckForRunningInstance(agentID string, binaryType BinaryType) error {
 | |
| 	lockFile := fmt.Sprintf("/tmp/bzzz-%s-%s.lock", agentID, binaryType)
 | |
| 
 | |
| 	if _, err := os.Stat(lockFile); err == nil {
 | |
| 		return fmt.Errorf("instance already running: %s %s", binaryType, agentID)
 | |
| 	}
 | |
| 
 | |
| 	// Create lock file
 | |
| 	return os.WriteFile(lockFile, []byte(fmt.Sprintf("%d", os.Getpid())), 0644)
 | |
| }
 | |
| 
 | |
| // RemoveInstanceLock removes the instance lock file
 | |
| func RemoveInstanceLock(agentID string, binaryType BinaryType) error {
 | |
| 	lockFile := fmt.Sprintf("/tmp/bzzz-%s-%s.lock", agentID, binaryType)
 | |
| 	return os.Remove(lockFile)
 | |
| }
 | |
| 
 | |
| // GetConfigPath determines the configuration file path
 | |
| func GetConfigPath() string {
 | |
| 	configPath := os.Getenv("BZZZ_CONFIG_PATH")
 | |
| 	if configPath == "" {
 | |
| 		configPath = ".bzzz/config.yaml"
 | |
| 	}
 | |
| 	return configPath
 | |
| }
 | |
| 
 | |
| // NeedsSetup checks if the system needs to run setup mode
 | |
| func NeedsSetup() bool {
 | |
| 	configPath := GetConfigPath()
 | |
| 	return config.IsSetupRequired(configPath)
 | |
| } |