Skip to content

v0.5.5

Choose a tag to compare

@github-actions github-actions released this 03 Sep 04:51
· 33 commits to main since this release

Daemon lifecycle becomes first-class: awerouter serve run <profile> -d runs the daemon detached — it survives the terminal (log: <state>/serve-<profile>.log), awerouter serve status lists every running serve instance (foreground and background, registered under <state>/run/ at bind time), and awerouter serve stop [PROFILE] stops them with a graceful SIGTERM. Serve now also watches routing.json/providers.json and hot-reloads edits — destinations, thresholds, tool routing, settings overrides, and provider entries apply to the next request without a restart. The CLI also reorganizes: serve becomes a command group (run / status / stop) and login / logout / restore move under config — the released top-level spellings keep working as hidden aliases, so nothing breaks.

Added

  • login, logout, and restore moved under the config group — awerouter config login [claude|codex], awerouter config logout [claude|codex], awerouter config restore [providers|routing] — grouping every command that manages config-owned state (files, backups, the claude login store) next to config path/show/edit. The released top-level spellings keep working as hidden aliases (awerouter login etc.), so existing docs, scripts, and muscle memory don't break; awerouter --help lists only the config form. Error hints that name the command (missing claude login 503/warnings, init --merge behavior-shift note) now print the new spelling.
  • serve is now a command group — run (start a daemon), status, stop — instead of a bare command with top-level status/stop. The pre-group spellings keep working: awerouter serve <profile> [--port/--host/-d] and awerouter <profile> are equivalent to awerouter serve run <profile> (an unknown subcommand under serve is a profile name, same as the top level), and bare awerouter serve still auto-selects the single profile. The one removal: awerouter serve -d (background auto-select, no profile) — name the profile or use serve run.
  • awerouter serve run [PROFILE] -d/--background: spawns the daemon detached via python -m awerouter __serve_daemon__ <profile> (new __main__.py), waits for it to bind, then prints pid/port/log path plus a status/stop hint; notes when the profile is already running (starts another anyway, same as concurrent foreground instances). A child that dies before binding fails the command with the log tail. POSIX-only (os.name == "nt" refuses).
  • awerouter serve status / awerouter serve stop [PROFILE] (new awerouter.runtime module): every serve process registers {pid, profile, protocol, port, host, background, started} under <state>/run/<pid>.json at bind time and unregisters on shutdown (SIGTERM/SIGHUP now shut down gracefully via signal handlers on the serve event loop). serve status lists live instances (stale/dead-pid files pruned on sight); serve stop SIGTERMs matching instances after a command-line guard (ps token match: awerouter, -m awerouter, .../bin/awerouter) so a reused pid is never signaled. Windows: pid_alive probes via OpenProcess (os.kill(pid, 0) would TerminateProcess there), and -d/serve stop refuse outright.
  • Hot reload: _serve polls both config files' mtimes (1s) and swaps the live app's profile/settings/providers from a fresh load_for_profile — destinations, thresholds, tool routing, per-profile overrides, provider entries, and "auto" threshold re-resolution all apply to the next request without a restart. A file that fails to load prints one config reload skipped line and the previous config keeps serving until the file parses again; a changed port field prints a restart hint (rebinding is out of scope). The serve banner prints hot reload -> on.
  • Skill refresh nudge: awerouter self-update (after a successful upgrade) and the daily update reminder now add one line when the awerouter agent skill is detected in ~/.agents/skills/ or ~/.claude/skills/ — the skill is updated along with awerouter releases, and refreshing it is best done by the coding agent itself: aweskill update awerouter. awerouter never writes the skill file: its lifecycle (store, projections, local-edit protection) belongs to aweskill, and the skill is not packaged in the wheel, so awerouter only points at the refresh command.