package config import ( "os" "path/filepath" "strconv" "time" ) const ( DefaultMode = "smoke" DefaultPlatformURL = "http://127.0.0.1:8080" DefaultEndpointID = "run-local" DefaultDisplayName = "Local Run" DefaultVersion = "0.1.0" ) type Config struct { Mode string PlatformURL string RunEndpointID string DisplayName string Version string RegistrationToken string WorkspaceRoot string SpoolRoot string MaxJobs int HeartbeatInterval time.Duration PollInterval time.Duration RetryBackoff time.Duration } func Load() Config { mode := os.Getenv("RUN_MODE") if mode == "" { mode = DefaultMode } platformURL := os.Getenv("RUN_PLATFORM_URL") if platformURL == "" { platformURL = DefaultPlatformURL } workspaceRoot := envOrDefault("RUN_WORKSPACE_ROOT", filepath.Join(".", ".run-workspace")) return Config{ Mode: mode, PlatformURL: platformURL, RunEndpointID: envOrDefault("RUN_ENDPOINT_ID", DefaultEndpointID), DisplayName: envOrDefault("RUN_DISPLAY_NAME", DefaultDisplayName), Version: envOrDefault("RUN_VERSION", DefaultVersion), RegistrationToken: envOrDefault("RUN_REGISTRATION_TOKEN", "local-registration"), WorkspaceRoot: workspaceRoot, SpoolRoot: envOrDefault("RUN_SPOOL_ROOT", filepath.Join(workspaceRoot, "spool")), MaxJobs: intEnvOrDefault("RUN_MAX_JOBS", 1), HeartbeatInterval: durationEnvOrDefault("RUN_HEARTBEAT_INTERVAL_MS", 15*time.Second), PollInterval: durationEnvOrDefault("RUN_POLL_INTERVAL_MS", 2*time.Second), RetryBackoff: durationEnvOrDefault("RUN_RETRY_BACKOFF_MS", time.Second), } } func envOrDefault(key string, fallback string) string { value := os.Getenv(key) if value == "" { return fallback } return value } func intEnvOrDefault(key string, fallback int) int { value, err := strconv.Atoi(os.Getenv(key)) if err != nil || value <= 0 { return fallback } return value } func durationEnvOrDefault(key string, fallback time.Duration) time.Duration { value, err := strconv.Atoi(os.Getenv(key)) if err != nil || value <= 0 { return fallback } return time.Duration(value) * time.Millisecond }