🎭 CHORUS - Container-First P2P Task Coordination System - Docker-first architecture designed from ground up - Environment variable-based configuration (no config files) - Structured logging to stdout/stderr for container runtimes - License validation required for operation - Clean separation from BZZZ legacy systemd approach Core features implemented: - Container-optimized logging system - Environment-based configuration management - License validation with KACHING integration - Basic HTTP API and health endpoints - Docker build and deployment configuration Ready for P2P protocol development and AI integration. 🤖 Generated with Claude Code
140 lines
4.0 KiB
Go
140 lines
4.0 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Config represents the complete CHORUS configuration loaded from environment variables
|
|
type Config struct {
|
|
Agent AgentConfig `yaml:"agent"`
|
|
Network NetworkConfig `yaml:"network"`
|
|
License LicenseConfig `yaml:"license"`
|
|
AI AIConfig `yaml:"ai"`
|
|
Logging LoggingConfig `yaml:"logging"`
|
|
}
|
|
|
|
// AgentConfig defines agent-specific settings
|
|
type AgentConfig struct {
|
|
ID string `yaml:"id"`
|
|
Specialization string `yaml:"specialization"`
|
|
MaxTasks int `yaml:"max_tasks"`
|
|
Capabilities []string `yaml:"capabilities"`
|
|
}
|
|
|
|
// NetworkConfig defines network and API settings
|
|
type NetworkConfig struct {
|
|
P2PPort int `yaml:"p2p_port"`
|
|
APIPort int `yaml:"api_port"`
|
|
HealthPort int `yaml:"health_port"`
|
|
BindAddr string `yaml:"bind_address"`
|
|
}
|
|
|
|
// LicenseConfig defines licensing settings
|
|
type LicenseConfig struct {
|
|
Email string `yaml:"email"`
|
|
LicenseKey string `yaml:"license_key"`
|
|
ClusterID string `yaml:"cluster_id"`
|
|
}
|
|
|
|
// AIConfig defines AI service settings
|
|
type AIConfig struct {
|
|
OllamaEndpoint string `yaml:"ollama_endpoint"`
|
|
DefaultModel string `yaml:"default_model"`
|
|
}
|
|
|
|
// LoggingConfig defines logging settings
|
|
type LoggingConfig struct {
|
|
Level string `yaml:"level"`
|
|
Format string `yaml:"format"`
|
|
}
|
|
|
|
// LoadFromEnvironment loads configuration from environment variables
|
|
// This is the primary configuration method for CHORUS (no config files)
|
|
func LoadFromEnvironment() (*Config, error) {
|
|
cfg := &Config{
|
|
Agent: AgentConfig{
|
|
ID: getEnvOrDefault("CHORUS_AGENT_ID", ""),
|
|
Specialization: getEnvOrDefault("CHORUS_SPECIALIZATION", "general_developer"),
|
|
MaxTasks: getEnvIntOrDefault("CHORUS_MAX_TASKS", 3),
|
|
Capabilities: getEnvArrayOrDefault("CHORUS_CAPABILITIES", []string{"general_development", "task_coordination"}),
|
|
},
|
|
Network: NetworkConfig{
|
|
P2PPort: getEnvIntOrDefault("CHORUS_P2P_PORT", 9000),
|
|
APIPort: getEnvIntOrDefault("CHORUS_API_PORT", 8080),
|
|
HealthPort: getEnvIntOrDefault("CHORUS_HEALTH_PORT", 8081),
|
|
BindAddr: getEnvOrDefault("CHORUS_BIND_ADDRESS", "0.0.0.0"),
|
|
},
|
|
License: LicenseConfig{
|
|
Email: os.Getenv("CHORUS_LICENSE_EMAIL"),
|
|
LicenseKey: os.Getenv("CHORUS_LICENSE_KEY"),
|
|
ClusterID: getEnvOrDefault("CHORUS_CLUSTER_ID", "default-cluster"),
|
|
},
|
|
AI: AIConfig{
|
|
OllamaEndpoint: getEnvOrDefault("OLLAMA_ENDPOINT", "http://localhost:11434"),
|
|
DefaultModel: getEnvOrDefault("CHORUS_DEFAULT_MODEL", "llama3.1:8b"),
|
|
},
|
|
Logging: LoggingConfig{
|
|
Level: getEnvOrDefault("LOG_LEVEL", "info"),
|
|
Format: getEnvOrDefault("LOG_FORMAT", "structured"),
|
|
},
|
|
}
|
|
|
|
// Validate required configuration
|
|
if err := cfg.Validate(); err != nil {
|
|
return nil, fmt.Errorf("configuration validation failed: %w", err)
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
// Validate ensures all required configuration is present
|
|
func (c *Config) Validate() error {
|
|
if c.License.Email == "" {
|
|
return fmt.Errorf("CHORUS_LICENSE_EMAIL is required")
|
|
}
|
|
|
|
if c.License.LicenseKey == "" {
|
|
return fmt.Errorf("CHORUS_LICENSE_KEY is required")
|
|
}
|
|
|
|
if c.Agent.ID == "" {
|
|
// Auto-generate agent ID if not provided
|
|
hostname, _ := os.Hostname()
|
|
containerID := os.Getenv("HOSTNAME") // Docker sets this to container ID
|
|
if containerID != "" && containerID != hostname {
|
|
c.Agent.ID = fmt.Sprintf("chorus-%s", containerID[:12])
|
|
} else {
|
|
c.Agent.ID = fmt.Sprintf("chorus-%s", hostname)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Helper functions for environment variable parsing
|
|
|
|
func getEnvOrDefault(key, defaultValue string) string {
|
|
if value := os.Getenv(key); value != "" {
|
|
return value
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvIntOrDefault(key string, defaultValue int) int {
|
|
if value := os.Getenv(key); value != "" {
|
|
if parsed, err := strconv.Atoi(value); err == nil {
|
|
return parsed
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvArrayOrDefault(key string, defaultValue []string) []string {
|
|
if value := os.Getenv(key); value != "" {
|
|
return strings.Split(value, ",")
|
|
}
|
|
return defaultValue
|
|
} |