SMARTRUN_BACKFILL_HORIZON_DAYS was a server-startup-only env var with no UI, defaulting to 3 years -- so editing the unrelated "Rolling window" profile field (for classification, not sync) had no effect on how far back Sync Now reached. Backfill horizon is now Profile.BackfillHorizonDays, read fresh on every Backfill call, with its own field on the Profile page.
80 lines
2.4 KiB
Go
80 lines
2.4 KiB
Go
// Package config loads smartrund's runtime infrastructure configuration
|
|
// from environment variables (paths and process settings that don't belong
|
|
// in the user-editable profile). Garmin credentials and every tunable
|
|
// analysis-engine parameter live in the profile (internal/store.Profile)
|
|
// instead -- see docs/superpowers/specs/2026-07-17-profile-taxonomy-analysis-engine-design.md.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// Config holds smartrund's process-level configuration.
|
|
type Config struct {
|
|
// Addr is the HTTP listen address, e.g. ":8080".
|
|
Addr string
|
|
// DBPath is the SQLite database file path.
|
|
DBPath string
|
|
|
|
// GarminPythonPath is mcp-garmin's venv python executable.
|
|
GarminPythonPath string
|
|
// GarminServerPath is mcp-garmin's server.py.
|
|
GarminServerPath string
|
|
// GarminTokenStore, if set, overrides mcp-garmin's default ~/.garth
|
|
// session cache location.
|
|
GarminTokenStore string
|
|
|
|
MinConfidence float64
|
|
IncrementalSyncEvery time.Duration
|
|
}
|
|
|
|
// Load reads configuration from environment variables, applying defaults
|
|
// for anything optional. Returns an error if a required variable is unset.
|
|
func Load() (Config, error) {
|
|
cfg := Config{
|
|
Addr: getEnvDefault("SMARTRUN_ADDR", ":8080"),
|
|
DBPath: getEnvDefault("SMARTRUN_DB_PATH", "smartrun.db"),
|
|
GarminPythonPath: os.Getenv("MCP_GARMIN_PYTHON"),
|
|
GarminServerPath: os.Getenv("MCP_GARMIN_SERVER"),
|
|
GarminTokenStore: os.Getenv("GARMIN_TOKENSTORE"),
|
|
MinConfidence: getEnvFloat("SMARTRUN_MIN_CONFIDENCE", 0.6),
|
|
IncrementalSyncEvery: getEnvDuration("SMARTRUN_INCREMENTAL_SYNC_EVERY", 6*time.Hour),
|
|
}
|
|
|
|
if cfg.GarminPythonPath == "" {
|
|
return cfg, fmt.Errorf("MCP_GARMIN_PYTHON is required (path to mcp-garmin's venv python)")
|
|
}
|
|
if cfg.GarminServerPath == "" {
|
|
return cfg, fmt.Errorf("MCP_GARMIN_SERVER is required (path to mcp-garmin's server.py)")
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
func getEnvDefault(key, def string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return def
|
|
}
|
|
|
|
func getEnvFloat(key string, def float64) float64 {
|
|
if v := os.Getenv(key); v != "" {
|
|
if f, err := strconv.ParseFloat(v, 64); err == nil {
|
|
return f
|
|
}
|
|
}
|
|
return def
|
|
}
|
|
|
|
func getEnvDuration(key string, def time.Duration) time.Duration {
|
|
if v := os.Getenv(key); v != "" {
|
|
if d, err := time.ParseDuration(v); err == nil {
|
|
return d
|
|
}
|
|
}
|
|
return def
|
|
}
|