package config import ( "errors" "fmt" "os" "path/filepath" "time" ) // Config holds runtime configuration for the AI gRPC gateway. type Config struct { GRPCPort string OllamaURL string OllamaModel string OllamaTimeout time.Duration HAGatewayAddr string HAGatewayServerName string TLSDir string OTELEndpoint string LogLevel string LogFormat string LightCacheTTL time.Duration } // Load reads configuration from environment variables and applies defaults. func Load() (*Config, error) { ollamaTimeout, err := parseDurationEnv("OLLAMA_TIMEOUT", 120*time.Second) if err != nil { return nil, err } cacheTTL, err := parseDurationEnv("LIGHT_CACHE_TTL", 60*time.Second) if err != nil { return nil, err } cfg := &Config{ GRPCPort: getenvDefault("GRPC_PORT", "50052"), OllamaURL: getenvDefault("OLLAMA_URL", "http://192.168.7.96:11434"), OllamaModel: getenvDefault("OLLAMA_MODEL", "llama3"), OllamaTimeout: ollamaTimeout, HAGatewayAddr: getenvDefault("HA_GATEWAY_ADDR", "ha-gateway.home-services.svc.cluster.local:50051"), HAGatewayServerName: getenvDefault("HA_GATEWAY_SERVER_NAME", "ha-gateway.home-services.svc.cluster.local"), TLSDir: os.Getenv("TLS_DIR"), OTELEndpoint: os.Getenv("OTEL_ENDPOINT"), LogLevel: getenvDefault("LOG_LEVEL", "info"), LogFormat: getenvDefault("LOG_FORMAT", "json"), LightCacheTTL: cacheTTL, } if cfg.TLSDir != "" { if err := validateTLSDir(cfg.TLSDir); err != nil { return nil, err } } return cfg, nil } func getenvDefault(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback } func parseDurationEnv(key string, fallback time.Duration) (time.Duration, error) { if v := os.Getenv(key); v != "" { d, err := time.ParseDuration(v) if err != nil { return 0, fmt.Errorf("parse %s: %w", key, err) } return d, nil } return fallback, nil } func validateTLSDir(dir string) error { required := []string{"tls.crt", "tls.key", "ca.crt"} for _, name := range required { path := filepath.Join(dir, name) info, err := os.Stat(path) if err != nil { return fmt.Errorf("tls dir validation failed for %s: %w", path, err) } if info.IsDir() { return fmt.Errorf("tls dir validation failed for %s: %w", path, errors.New("expected file")) } } return nil }