package config import ( "errors" "os" "strconv" "time" ) type Config struct { ProfilePath string TasksWSURL string TasksAPIURL string TasksAgentToken string CoreEndpoint string CoreToken string CoreInsecure bool Model string MetricsListenAddr string HealthListenAddr string ShutdownTimeout time.Duration ResponseTimeout time.Duration } func Load() (Config, error) { c := Config{ ProfilePath: env("AGENT_PROFILE_PATH", "profiles/kaya.yaml"), TasksWSURL: os.Getenv("TASKS_WS_URL"), TasksAPIURL: os.Getenv("TASKS_API_URL"), TasksAgentToken: os.Getenv("TASKS_AGENT_TOKEN"), CoreEndpoint: env("CORE_ENDPOINT", "core:50051"), CoreToken: os.Getenv("CORE_TOKEN"), CoreInsecure: envBool("CORE_INSECURE", false), Model: env("MODEL", "deepseek-v4-flash"), MetricsListenAddr: env("METRICS_LISTEN_ADDR", ":9097"), HealthListenAddr: env("HEALTH_LISTEN_ADDR", ":8087"), ShutdownTimeout: envDur("SHUTDOWN_TIMEOUT", 15*time.Second), ResponseTimeout: envDur("RESPONSE_TIMEOUT", 120*time.Second), } if c.TasksWSURL == "" { return c, errors.New("TASKS_WS_URL is required") } if c.TasksAPIURL == "" { return c, errors.New("TASKS_API_URL is required") } if c.TasksAgentToken == "" { return c, errors.New("TASKS_AGENT_TOKEN is required") } if c.CoreToken == "" { return c, errors.New("CORE_TOKEN is required") } if c.ResponseTimeout <= 0 { return c, errors.New("RESPONSE_TIMEOUT must be positive") } return c, nil } func env(k, d string) string { if v := os.Getenv(k); v != "" { return v } return d } func envBool(k string, d bool) bool { if v := os.Getenv(k); v != "" { b, _ := strconv.ParseBool(v) return b } return d } func envDur(k string, d time.Duration) time.Duration { if v := os.Getenv(k); v != "" { x, err := time.ParseDuration(v) if err == nil { return x } } return d }