feat(agent): add mirror failover, agent client refactor, status 401 detection

- Mirror pool with health tracking and exponential backoff for failed hosts
- Agent client routes requests through mirror pool with retry semantics
- New `unarr mirrors` command to inspect mirror state and force failover
- `unarr status` now detects 401 from /agent/register and suggests `unarr login`
  instead of the generic "Could not fetch account info" message
- Config supports multiple ScanPaths for upcoming multi-path library scan
- Draft plan for bidirectional library sync (CLI ↔ Web) under Docs/plans/
This commit is contained in:
Deivid Soto 2026-05-15 16:26:43 +02:00
parent bf18812a3d
commit a73e1a7756
12 changed files with 972 additions and 76 deletions

View file

@ -26,6 +26,11 @@ type Config struct {
type AuthConfig struct {
APIKey string `toml:"api_key"`
APIURL string `toml:"api_url"`
// Mirrors lists alternate base URLs the agent will fall back to when the
// primary api_url is unreachable. Ordered by preference. Refreshed at
// runtime by `unarr mirrors update` against /api/v1/mirrors so a long-
// running agent survives a primary takedown without a new release.
Mirrors []string `toml:"mirrors"`
}
type AgentConfig struct {
@ -113,6 +118,12 @@ func Default() Config {
return Config{
Auth: AuthConfig{
APIURL: "https://torrentclaw.com",
// Default mirror list. Kept in sync with src/lib/mirrors-config.ts
// on the server. Users can override with `unarr mirrors update`,
// which pulls the live list from /api/v1/mirrors.
Mirrors: []string{
"https://torrentclaw.to",
},
},
Download: DownloadConfig{
PreferredMethod: "auto",
@ -187,6 +198,9 @@ func applyDefaults(cfg *Config, meta toml.MetaData) {
if !meta.IsDefined("auth", "api_url") {
cfg.Auth.APIURL = "https://torrentclaw.com"
}
if !meta.IsDefined("auth", "mirrors") {
cfg.Auth.Mirrors = []string{"https://torrentclaw.to"}
}
if !meta.IsDefined("downloads", "preferred_method") {
cfg.Download.PreferredMethod = "auto"
}