 c177363a19
			
		
	
	c177363a19
	
	
	
		
			
			🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			585 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			585 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package config
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"io/ioutil"
 | |
| 	"os"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	"gopkg.in/yaml.v2"
 | |
| )
 | |
| 
 | |
| // SecurityConfig holds cluster security and election configuration
 | |
| type SecurityConfig struct {
 | |
| 	// Admin key sharing
 | |
| 	AdminKeyShares  ShamirShare    `yaml:"admin_key_shares" json:"admin_key_shares"`
 | |
| 	ElectionConfig  ElectionConfig `yaml:"election_config" json:"election_config"`
 | |
| 	
 | |
| 	// Key management
 | |
| 	KeyRotationDays int    `yaml:"key_rotation_days,omitempty" json:"key_rotation_days,omitempty"`
 | |
| 	AuditLogging    bool   `yaml:"audit_logging" json:"audit_logging"`
 | |
| 	AuditPath       string `yaml:"audit_path,omitempty" json:"audit_path,omitempty"`
 | |
| }
 | |
| 
 | |
| // Config represents the complete configuration for a Bzzz agent
 | |
| type Config struct {
 | |
| 	WHOOSHAPI  WHOOSHAPIConfig  `yaml:"hive_api"`
 | |
| 	Agent    AgentConfig    `yaml:"agent"`
 | |
| 	GitHub   GitHubConfig   `yaml:"github"`
 | |
| 	P2P      P2PConfig      `yaml:"p2p"`
 | |
| 	Logging  LoggingConfig  `yaml:"logging"`
 | |
| 	HCFS     HCFSConfig     `yaml:"hcfs"`
 | |
| 	Slurp    SlurpConfig    `yaml:"slurp"`
 | |
| 	V2       V2Config       `yaml:"v2"`   // BZZZ v2 protocol settings
 | |
| 	UCXL     UCXLConfig     `yaml:"ucxl"` // UCXL protocol settings
 | |
| 	Security SecurityConfig `yaml:"security"` // Cluster security and elections
 | |
| }
 | |
| 
 | |
| // WHOOSHAPIConfig holds WHOOSH system integration settings
 | |
| type WHOOSHAPIConfig struct {
 | |
| 	BaseURL    string        `yaml:"base_url"`
 | |
| 	APIKey     string        `yaml:"api_key"`
 | |
| 	Timeout    time.Duration `yaml:"timeout"`
 | |
| 	RetryCount int           `yaml:"retry_count"`
 | |
| }
 | |
| 
 | |
| // CollaborationConfig holds role-based collaboration settings
 | |
| type CollaborationConfig struct {
 | |
| 	PreferredMessageTypes     []string          `yaml:"preferred_message_types"`
 | |
| 	AutoSubscribeToRoles      []string          `yaml:"auto_subscribe_to_roles"`
 | |
| 	AutoSubscribeToExpertise  []string          `yaml:"auto_subscribe_to_expertise"`
 | |
| 	ResponseTimeoutSeconds    int               `yaml:"response_timeout_seconds"`
 | |
| 	MaxCollaborationDepth     int               `yaml:"max_collaboration_depth"`
 | |
| 	EscalationThreshold       int               `yaml:"escalation_threshold"`
 | |
| 	CustomTopicSubscriptions  []string          `yaml:"custom_topic_subscriptions"`
 | |
| }
 | |
| 
 | |
| // AgentConfig holds agent-specific configuration
 | |
| type AgentConfig struct {
 | |
| 	ID                    string        `yaml:"id"`
 | |
| 	Capabilities          []string      `yaml:"capabilities"`
 | |
| 	PollInterval          time.Duration `yaml:"poll_interval"`
 | |
| 	MaxTasks              int           `yaml:"max_tasks"`
 | |
| 	Models                []string      `yaml:"models"`
 | |
| 	Specialization        string        `yaml:"specialization"`
 | |
| 	ModelSelectionWebhook string        `yaml:"model_selection_webhook"`
 | |
| 	DefaultReasoningModel string        `yaml:"default_reasoning_model"`
 | |
| 	SandboxImage          string        `yaml:"sandbox_image"`
 | |
| 	
 | |
| 	// Role-based configuration from Bees-AgenticWorkers
 | |
| 	Role         string            `yaml:"role"`
 | |
| 	SystemPrompt string            `yaml:"system_prompt"`
 | |
| 	ReportsTo    []string          `yaml:"reports_to"`
 | |
| 	Expertise    []string          `yaml:"expertise"`
 | |
| 	Deliverables []string          `yaml:"deliverables"`
 | |
| 	
 | |
| 	// Role-based collaboration settings
 | |
| 	CollaborationSettings CollaborationConfig `yaml:"collaboration"`
 | |
| }
 | |
| 
 | |
| // GitHubConfig holds GitHub integration settings
 | |
| type GitHubConfig struct {
 | |
| 	TokenFile    string        `yaml:"token_file"`
 | |
| 	UserAgent    string        `yaml:"user_agent"`
 | |
| 	Timeout      time.Duration `yaml:"timeout"`
 | |
| 	RateLimit    bool          `yaml:"rate_limit"`
 | |
| 	Assignee     string        `yaml:"assignee"`
 | |
| }
 | |
| 
 | |
| // P2PConfig holds P2P networking configuration
 | |
| type P2PConfig struct {
 | |
| 	ServiceTag       string        `yaml:"service_tag"`
 | |
| 	BzzzTopic        string        `yaml:"bzzz_topic"`
 | |
| 	HmmmTopic        string        `yaml:"hmmm_topic"`
 | |
| 	DiscoveryTimeout time.Duration `yaml:"discovery_timeout"`
 | |
| 	
 | |
| 	// Human escalation settings
 | |
| 	EscalationWebhook       string   `yaml:"escalation_webhook"`
 | |
| 	EscalationKeywords      []string `yaml:"escalation_keywords"`
 | |
| 	ConversationLimit       int      `yaml:"conversation_limit"`
 | |
| }
 | |
| 
 | |
| // LoggingConfig holds logging configuration
 | |
| type LoggingConfig struct {
 | |
| 	Level      string `yaml:"level"`
 | |
| 	Format     string `yaml:"format"`
 | |
| 	Output     string `yaml:"output"`
 | |
| 	Structured bool   `yaml:"structured"`
 | |
| }
 | |
| 
 | |
| // V2Config holds BZZZ v2 protocol configuration
 | |
| type V2Config struct {
 | |
| 	// Enable v2 protocol features
 | |
| 	Enabled bool `yaml:"enabled" json:"enabled"`
 | |
| 	
 | |
| 	// Protocol version
 | |
| 	ProtocolVersion string `yaml:"protocol_version" json:"protocol_version"`
 | |
| 	
 | |
| 	// URI resolution settings
 | |
| 	URIResolution URIResolutionConfig `yaml:"uri_resolution" json:"uri_resolution"`
 | |
| 	
 | |
| 	// DHT settings
 | |
| 	DHT DHTConfig `yaml:"dht" json:"dht"`
 | |
| 	
 | |
| 	// Semantic addressing
 | |
| 	SemanticAddressing SemanticAddressingConfig `yaml:"semantic_addressing" json:"semantic_addressing"`
 | |
| 	
 | |
| 	// Feature flags
 | |
| 	FeatureFlags map[string]bool `yaml:"feature_flags" json:"feature_flags"`
 | |
| }
 | |
| 
 | |
| // URIResolutionConfig holds URI resolution settings
 | |
| type URIResolutionConfig struct {
 | |
| 	CacheTTL          time.Duration `yaml:"cache_ttl" json:"cache_ttl"`
 | |
| 	MaxPeersPerResult int           `yaml:"max_peers_per_result" json:"max_peers_per_result"`
 | |
| 	DefaultStrategy   string        `yaml:"default_strategy" json:"default_strategy"`
 | |
| 	ResolutionTimeout time.Duration `yaml:"resolution_timeout" json:"resolution_timeout"`
 | |
| }
 | |
| 
 | |
| // DHTConfig holds DHT-specific configuration
 | |
| type DHTConfig struct {
 | |
| 	Enabled           bool          `yaml:"enabled" json:"enabled"`
 | |
| 	BootstrapPeers    []string      `yaml:"bootstrap_peers" json:"bootstrap_peers"`
 | |
| 	Mode              string        `yaml:"mode" json:"mode"` // "client", "server", "auto"
 | |
| 	ProtocolPrefix    string        `yaml:"protocol_prefix" json:"protocol_prefix"`
 | |
| 	BootstrapTimeout  time.Duration `yaml:"bootstrap_timeout" json:"bootstrap_timeout"`
 | |
| 	DiscoveryInterval time.Duration `yaml:"discovery_interval" json:"discovery_interval"`
 | |
| 	AutoBootstrap     bool          `yaml:"auto_bootstrap" json:"auto_bootstrap"`
 | |
| }
 | |
| 
 | |
| // SemanticAddressingConfig holds semantic addressing settings
 | |
| type SemanticAddressingConfig struct {
 | |
| 	EnableWildcards     bool   `yaml:"enable_wildcards" json:"enable_wildcards"`
 | |
| 	DefaultAgent        string `yaml:"default_agent" json:"default_agent"`
 | |
| 	DefaultRole         string `yaml:"default_role" json:"default_role"`
 | |
| 	DefaultProject      string `yaml:"default_project" json:"default_project"`
 | |
| 	EnableRoleHierarchy bool   `yaml:"enable_role_hierarchy" json:"enable_role_hierarchy"`
 | |
| }
 | |
| 
 | |
| // UCXLConfig holds UCXL protocol configuration
 | |
| type UCXLConfig struct {
 | |
| 	// Enable UCXL protocol
 | |
| 	Enabled bool `yaml:"enabled" json:"enabled"`
 | |
| 	
 | |
| 	// UCXI server configuration
 | |
| 	Server UCXIServerConfig `yaml:"server" json:"server"`
 | |
| 	
 | |
| 	// Address resolution settings
 | |
| 	Resolution UCXLResolutionConfig `yaml:"resolution" json:"resolution"`
 | |
| 	
 | |
| 	// Storage settings
 | |
| 	Storage UCXLStorageConfig `yaml:"storage" json:"storage"`
 | |
| 	
 | |
| 	// P2P integration settings
 | |
| 	P2PIntegration UCXLP2PConfig `yaml:"p2p_integration" json:"p2p_integration"`
 | |
| }
 | |
| 
 | |
| // UCXIServerConfig holds UCXI server settings
 | |
| type UCXIServerConfig struct {
 | |
| 	Port     int    `yaml:"port" json:"port"`
 | |
| 	BasePath string `yaml:"base_path" json:"base_path"`
 | |
| 	Enabled  bool   `yaml:"enabled" json:"enabled"`
 | |
| }
 | |
| 
 | |
| // UCXLResolutionConfig holds address resolution settings
 | |
| type UCXLResolutionConfig struct {
 | |
| 	CacheTTL        time.Duration `yaml:"cache_ttl" json:"cache_ttl"`
 | |
| 	EnableWildcards bool          `yaml:"enable_wildcards" json:"enable_wildcards"`
 | |
| 	MaxResults      int           `yaml:"max_results" json:"max_results"`
 | |
| }
 | |
| 
 | |
| // UCXLStorageConfig holds storage settings
 | |
| type UCXLStorageConfig struct {
 | |
| 	Type      string `yaml:"type" json:"type"` // "filesystem", "memory"
 | |
| 	Directory string `yaml:"directory" json:"directory"`
 | |
| 	MaxSize   int64  `yaml:"max_size" json:"max_size"` // in bytes
 | |
| }
 | |
| 
 | |
| // UCXLP2PConfig holds P2P integration settings
 | |
| type UCXLP2PConfig struct {
 | |
| 	EnableAnnouncement bool `yaml:"enable_announcement" json:"enable_announcement"`
 | |
| 	EnableDiscovery    bool `yaml:"enable_discovery" json:"enable_discovery"`
 | |
| 	AnnouncementTopic  string `yaml:"announcement_topic" json:"announcement_topic"`
 | |
| 	DiscoveryTimeout   time.Duration `yaml:"discovery_timeout" json:"discovery_timeout"`
 | |
| }
 | |
| 
 | |
| // HCFSConfig holds HCFS integration configuration
 | |
| type HCFSConfig struct {
 | |
| 	// API settings
 | |
| 	APIURL     string        `yaml:"api_url" json:"api_url"`
 | |
| 	APITimeout time.Duration `yaml:"api_timeout" json:"api_timeout"`
 | |
| 	
 | |
| 	// Workspace settings
 | |
| 	MountPath        string        `yaml:"mount_path" json:"mount_path"`
 | |
| 	WorkspaceTimeout time.Duration `yaml:"workspace_timeout" json:"workspace_timeout"`
 | |
| 	
 | |
| 	// FUSE settings
 | |
| 	FUSEEnabled    bool   `yaml:"fuse_enabled" json:"fuse_enabled"`
 | |
| 	FUSEMountPoint string `yaml:"fuse_mount_point" json:"fuse_mount_point"`
 | |
| 	
 | |
| 	// Cleanup settings
 | |
| 	IdleCleanupInterval time.Duration `yaml:"idle_cleanup_interval" json:"idle_cleanup_interval"`
 | |
| 	MaxIdleTime         time.Duration `yaml:"max_idle_time" json:"max_idle_time"`
 | |
| 	
 | |
| 	// Storage settings
 | |
| 	StoreArtifacts    bool `yaml:"store_artifacts" json:"store_artifacts"`
 | |
| 	CompressArtifacts bool `yaml:"compress_artifacts" json:"compress_artifacts"`
 | |
| 	
 | |
| 	// Enable/disable HCFS integration
 | |
| 	Enabled bool `yaml:"enabled" json:"enabled"`
 | |
| }
 | |
| 
 | |
| // LoadConfig loads configuration from file, environment variables, and defaults
 | |
| func LoadConfig(configPath string) (*Config, error) {
 | |
| 	// Start with defaults
 | |
| 	config := getDefaultConfig()
 | |
| 	
 | |
| 	// Load from file if it exists
 | |
| 	if configPath != "" && fileExists(configPath) {
 | |
| 		if err := loadFromFile(config, configPath); err != nil {
 | |
| 			return nil, fmt.Errorf("failed to load config file: %w", err)
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	// Override with environment variables
 | |
| 	if err := loadFromEnv(config); err != nil {
 | |
| 		return nil, fmt.Errorf("failed to load environment variables: %w", err)
 | |
| 	}
 | |
| 	
 | |
| 	// Validate configuration
 | |
| 	if err := validateConfig(config); err != nil {
 | |
| 		return nil, fmt.Errorf("invalid configuration: %w", err)
 | |
| 	}
 | |
| 	
 | |
| 	return config, nil
 | |
| }
 | |
| 
 | |
| // getDefaultConfig returns the default configuration
 | |
| func getDefaultConfig() *Config {
 | |
| 	return &Config{
 | |
| 		WHOOSHAPI: WHOOSHAPIConfig{
 | |
| 			BaseURL:    "https://hive.home.deepblack.cloud",
 | |
| 			Timeout:    30 * time.Second,
 | |
| 			RetryCount: 3,
 | |
| 		},
 | |
| 		Agent: AgentConfig{
 | |
| 			Capabilities:          []string{"general", "reasoning", "task-coordination"},
 | |
| 			PollInterval:          30 * time.Second,
 | |
| 			MaxTasks:              3,
 | |
| 			Models:                []string{"phi3", "llama3.1"},
 | |
| 			Specialization:        "general_developer",
 | |
| 			ModelSelectionWebhook: "https://n8n.home.deepblack.cloud/webhook/model-selection",
 | |
| 			DefaultReasoningModel: "phi3",
 | |
| 			SandboxImage:          "registry.home.deepblack.cloud/tony/bzzz-sandbox:latest",
 | |
| 		},
 | |
| 		GitHub: GitHubConfig{
 | |
| 			TokenFile: "/home/tony/chorus/business/secrets/gh-token",
 | |
| 			UserAgent: "Bzzz-P2P-Agent/1.0",
 | |
| 			Timeout:   30 * time.Second,
 | |
| 			RateLimit: true,
 | |
| 			Assignee:  "anthonyrawlins",
 | |
| 		},
 | |
| 		P2P: P2PConfig{
 | |
| 			ServiceTag:              "bzzz-peer-discovery",
 | |
| 			BzzzTopic:               "bzzz/coordination/v1",
 | |
| 			HmmmTopic:              "hmmm/meta-discussion/v1",
 | |
| 			DiscoveryTimeout:        10 * time.Second,
 | |
| 			EscalationWebhook:       "https://n8n.home.deepblack.cloud/webhook-test/human-escalation",
 | |
| 			EscalationKeywords:      []string{"stuck", "help", "human", "escalate", "clarification needed", "manual intervention"},
 | |
| 			ConversationLimit:       10,
 | |
| 		},
 | |
| 		Logging: LoggingConfig{
 | |
| 			Level:      "info",
 | |
| 			Format:     "text",
 | |
| 			Output:     "stdout",
 | |
| 			Structured: false,
 | |
| 		},
 | |
| 		HCFS: HCFSConfig{
 | |
| 			APIURL:              "http://localhost:8000",
 | |
| 			APITimeout:          30 * time.Second,
 | |
| 			MountPath:           "/tmp/hcfs-workspaces",
 | |
| 			WorkspaceTimeout:    2 * time.Hour,
 | |
| 			FUSEEnabled:         false,
 | |
| 			FUSEMountPoint:      "/mnt/hcfs",
 | |
| 			IdleCleanupInterval: 15 * time.Minute,
 | |
| 			MaxIdleTime:         1 * time.Hour,
 | |
| 			StoreArtifacts:      true,
 | |
| 			CompressArtifacts:   false,
 | |
| 			Enabled:             true,
 | |
| 		},
 | |
| 		Slurp: GetDefaultSlurpConfig(),
 | |
| 		UCXL: UCXLConfig{
 | |
| 			Enabled: false, // Disabled by default
 | |
| 			Server: UCXIServerConfig{
 | |
| 				Port:     8081,
 | |
| 				BasePath: "/bzzz",
 | |
| 				Enabled:  true,
 | |
| 			},
 | |
| 			Resolution: UCXLResolutionConfig{
 | |
| 				CacheTTL:        5 * time.Minute,
 | |
| 				EnableWildcards: true,
 | |
| 				MaxResults:      50,
 | |
| 			},
 | |
| 			Storage: UCXLStorageConfig{
 | |
| 				Type:      "filesystem",
 | |
| 				Directory: "/tmp/bzzz-ucxl-storage",
 | |
| 				MaxSize:   100 * 1024 * 1024, // 100MB
 | |
| 			},
 | |
| 			P2PIntegration: UCXLP2PConfig{
 | |
| 				EnableAnnouncement: true,
 | |
| 				EnableDiscovery:    true,
 | |
| 				AnnouncementTopic:  "bzzz/ucxl/announcement/v1",
 | |
| 				DiscoveryTimeout:   30 * time.Second,
 | |
| 			},
 | |
| 		},
 | |
| 		Security: SecurityConfig{
 | |
| 			AdminKeyShares: ShamirShare{
 | |
| 				Threshold:   3,
 | |
| 				TotalShares: 5,
 | |
| 			},
 | |
| 			ElectionConfig: ElectionConfig{
 | |
| 				HeartbeatTimeout:     5 * time.Second,
 | |
| 				DiscoveryTimeout:     30 * time.Second,
 | |
| 				ElectionTimeout:      15 * time.Second,
 | |
| 				MaxDiscoveryAttempts: 6,
 | |
| 				DiscoveryBackoff:     5 * time.Second,
 | |
| 				MinimumQuorum:        3,
 | |
| 				ConsensusAlgorithm:   "raft",
 | |
| 				SplitBrainDetection:  true,
 | |
| 				ConflictResolution:   "highest_uptime",
 | |
| 			},
 | |
| 			KeyRotationDays: 90,
 | |
| 			AuditLogging:    true,
 | |
| 			AuditPath:       ".bzzz/security-audit.log",
 | |
| 		},
 | |
| 		V2: V2Config{
 | |
| 			Enabled:         false, // Disabled by default for backward compatibility
 | |
| 			ProtocolVersion: "2.0.0",
 | |
| 			URIResolution: URIResolutionConfig{
 | |
| 				CacheTTL:          5 * time.Minute,
 | |
| 				MaxPeersPerResult: 5,
 | |
| 				DefaultStrategy:   "best_match",
 | |
| 				ResolutionTimeout: 30 * time.Second,
 | |
| 			},
 | |
| 			DHT: DHTConfig{
 | |
| 				Enabled:           false, // Disabled by default
 | |
| 				BootstrapPeers:    []string{},
 | |
| 				Mode:              "auto",
 | |
| 				ProtocolPrefix:    "/bzzz",
 | |
| 				BootstrapTimeout:  30 * time.Second,
 | |
| 				DiscoveryInterval: 60 * time.Second,
 | |
| 				AutoBootstrap:     false,
 | |
| 			},
 | |
| 			SemanticAddressing: SemanticAddressingConfig{
 | |
| 				EnableWildcards:     true,
 | |
| 				DefaultAgent:        "any",
 | |
| 				DefaultRole:         "any",
 | |
| 				DefaultProject:      "any",
 | |
| 				EnableRoleHierarchy: true,
 | |
| 			},
 | |
| 			FeatureFlags: map[string]bool{
 | |
| 				"uri_protocol":        false,
 | |
| 				"semantic_addressing": false,
 | |
| 				"dht_discovery":      false,
 | |
| 				"advanced_resolution": false,
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // loadFromFile loads configuration from a YAML file
 | |
| func loadFromFile(config *Config, filePath string) error {
 | |
| 	data, err := ioutil.ReadFile(filePath)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to read config file: %w", err)
 | |
| 	}
 | |
| 	
 | |
| 	if err := yaml.Unmarshal(data, config); err != nil {
 | |
| 		return fmt.Errorf("failed to parse YAML config: %w", err)
 | |
| 	}
 | |
| 	
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // loadFromEnv loads configuration from environment variables
 | |
| func loadFromEnv(config *Config) error {
 | |
| 	// WHOOSH API configuration
 | |
| 	if url := os.Getenv("BZZZ_HIVE_API_URL"); url != "" {
 | |
| 		config.WHOOSHAPI.BaseURL = url
 | |
| 	}
 | |
| 	if apiKey := os.Getenv("BZZZ_HIVE_API_KEY"); apiKey != "" {
 | |
| 		config.WHOOSHAPI.APIKey = apiKey
 | |
| 	}
 | |
| 	
 | |
| 	// Agent configuration
 | |
| 	if agentID := os.Getenv("BZZZ_AGENT_ID"); agentID != "" {
 | |
| 		config.Agent.ID = agentID
 | |
| 	}
 | |
| 	if capabilities := os.Getenv("BZZZ_AGENT_CAPABILITIES"); capabilities != "" {
 | |
| 		config.Agent.Capabilities = strings.Split(capabilities, ",")
 | |
| 	}
 | |
| 	if specialization := os.Getenv("BZZZ_AGENT_SPECIALIZATION"); specialization != "" {
 | |
| 		config.Agent.Specialization = specialization
 | |
| 	}
 | |
| 	if modelWebhook := os.Getenv("BZZZ_MODEL_SELECTION_WEBHOOK"); modelWebhook != "" {
 | |
| 		config.Agent.ModelSelectionWebhook = modelWebhook
 | |
| 	}
 | |
| 	
 | |
| 	// GitHub configuration
 | |
| 	if tokenFile := os.Getenv("BZZZ_GITHUB_TOKEN_FILE"); tokenFile != "" {
 | |
| 		config.GitHub.TokenFile = tokenFile
 | |
| 	}
 | |
| 	
 | |
| 	// P2P configuration
 | |
| 	if webhook := os.Getenv("BZZZ_ESCALATION_WEBHOOK"); webhook != "" {
 | |
| 		config.P2P.EscalationWebhook = webhook
 | |
| 	}
 | |
| 	
 | |
| 	// Logging configuration
 | |
| 	if level := os.Getenv("BZZZ_LOG_LEVEL"); level != "" {
 | |
| 		config.Logging.Level = level
 | |
| 	}
 | |
| 	
 | |
| 	// SLURP configuration
 | |
| 	if slurpURL := os.Getenv("BZZZ_SLURP_URL"); slurpURL != "" {
 | |
| 		config.Slurp.BaseURL = slurpURL
 | |
| 	}
 | |
| 	if slurpKey := os.Getenv("BZZZ_SLURP_API_KEY"); slurpKey != "" {
 | |
| 		config.Slurp.APIKey = slurpKey
 | |
| 	}
 | |
| 	if slurpEnabled := os.Getenv("BZZZ_SLURP_ENABLED"); slurpEnabled == "true" {
 | |
| 		config.Slurp.Enabled = true
 | |
| 	}
 | |
| 	
 | |
| 	// UCXL protocol configuration
 | |
| 	if ucxlEnabled := os.Getenv("BZZZ_UCXL_ENABLED"); ucxlEnabled == "true" {
 | |
| 		config.UCXL.Enabled = true
 | |
| 	}
 | |
| 	if ucxiPort := os.Getenv("BZZZ_UCXI_PORT"); ucxiPort != "" {
 | |
| 		// Would need strconv.Atoi but keeping simple for now
 | |
| 		// In production, add proper integer parsing
 | |
| 	}
 | |
| 	
 | |
| 	// V2 protocol configuration
 | |
| 	if v2Enabled := os.Getenv("BZZZ_V2_ENABLED"); v2Enabled == "true" {
 | |
| 		config.V2.Enabled = true
 | |
| 	}
 | |
| 	if dhtEnabled := os.Getenv("BZZZ_DHT_ENABLED"); dhtEnabled == "true" {
 | |
| 		config.V2.DHT.Enabled = true
 | |
| 	}
 | |
| 	if dhtMode := os.Getenv("BZZZ_DHT_MODE"); dhtMode != "" {
 | |
| 		config.V2.DHT.Mode = dhtMode
 | |
| 	}
 | |
| 	if bootstrapPeers := os.Getenv("BZZZ_DHT_BOOTSTRAP_PEERS"); bootstrapPeers != "" {
 | |
| 		config.V2.DHT.BootstrapPeers = strings.Split(bootstrapPeers, ",")
 | |
| 	}
 | |
| 	
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // validateConfig validates the configuration values
 | |
| func validateConfig(config *Config) error {
 | |
| 	// Validate required fields
 | |
| 	if config.WHOOSHAPI.BaseURL == "" {
 | |
| 		return fmt.Errorf("hive_api.base_url is required")
 | |
| 	}
 | |
| 	
 | |
| 	// Note: Agent.ID can be empty - it will be auto-generated from node ID in main.go
 | |
| 	
 | |
| 	if len(config.Agent.Capabilities) == 0 {
 | |
| 		return fmt.Errorf("agent.capabilities cannot be empty")
 | |
| 	}
 | |
| 	
 | |
| 	if config.Agent.PollInterval <= 0 {
 | |
| 		return fmt.Errorf("agent.poll_interval must be positive")
 | |
| 	}
 | |
| 	
 | |
| 	if config.Agent.MaxTasks <= 0 {
 | |
| 		return fmt.Errorf("agent.max_tasks must be positive")
 | |
| 	}
 | |
| 	
 | |
| 	// Validate GitHub token file exists if specified
 | |
| 	if config.GitHub.TokenFile != "" && !fileExists(config.GitHub.TokenFile) {
 | |
| 		return fmt.Errorf("github token file does not exist: %s", config.GitHub.TokenFile)
 | |
| 	}
 | |
| 	
 | |
| 	// Validate SLURP configuration
 | |
| 	if err := ValidateSlurpConfig(config.Slurp); err != nil {
 | |
| 		return fmt.Errorf("slurp configuration invalid: %w", err)
 | |
| 	}
 | |
| 	
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // SaveConfig saves the configuration to a YAML file
 | |
| func SaveConfig(config *Config, filePath string) error {
 | |
| 	data, err := yaml.Marshal(config)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to marshal config to YAML: %w", err)
 | |
| 	}
 | |
| 	
 | |
| 	if err := ioutil.WriteFile(filePath, data, 0644); err != nil {
 | |
| 		return fmt.Errorf("failed to write config file: %w", err)
 | |
| 	}
 | |
| 	
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // GetGitHubToken reads the GitHub token from the configured file
 | |
| func (c *Config) GetGitHubToken() (string, error) {
 | |
| 	if c.GitHub.TokenFile == "" {
 | |
| 		return "", fmt.Errorf("no GitHub token file configured")
 | |
| 	}
 | |
| 	
 | |
| 	tokenBytes, err := ioutil.ReadFile(c.GitHub.TokenFile)
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("failed to read GitHub token: %w", err)
 | |
| 	}
 | |
| 	
 | |
| 	return strings.TrimSpace(string(tokenBytes)), nil
 | |
| }
 | |
| 
 | |
| // fileExists checks if a file exists
 | |
| func fileExists(filePath string) bool {
 | |
| 	_, err := os.Stat(filePath)
 | |
| 	return err == nil
 | |
| }
 | |
| 
 | |
| // GenerateDefaultConfigFile creates a default configuration file
 | |
| func GenerateDefaultConfigFile(filePath string) error {
 | |
| 	config := getDefaultConfig()
 | |
| 	return SaveConfig(config, filePath)
 | |
| }
 | |
| 
 | |
| // IsSetupRequired checks if BZZZ needs to be set up (no valid configuration exists)
 | |
| func IsSetupRequired(configPath string) bool {
 | |
| 	// Check if config file exists
 | |
| 	if !fileExists(configPath) {
 | |
| 		return true
 | |
| 	}
 | |
| 	
 | |
| 	// Try to load the configuration
 | |
| 	_, err := LoadConfig(configPath)
 | |
| 	if err != nil {
 | |
| 		return true
 | |
| 	}
 | |
| 	
 | |
| 	// Configuration exists and is valid
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // IsValidConfiguration checks if a configuration is valid for production use
 | |
| func IsValidConfiguration(config *Config) bool {
 | |
| 	// Check essential configuration elements
 | |
| 	if config.Agent.ID == "" {
 | |
| 		return false
 | |
| 	}
 | |
| 	
 | |
| 	if len(config.Agent.Capabilities) == 0 {
 | |
| 		return false
 | |
| 	}
 | |
| 	
 | |
| 	// Configuration appears valid
 | |
| 	return true
 | |
| } |