Repository navigation
routstrd 0.4.17
Overview
The History tab becomes a dual-axis spend/token chart, usage summaries become
timezone-correct and far cheaper to compute, provider enable/disable reports the
policy that actually took effect, onboarding no longer aborts on a slow start,
and startup stops duplicating discovery work.
Depends on @routstr/sdk ^0.4.12 (bounded provider-fetch deadlines, see below).
TUI
- Dual-axis History chart: every bucket draws two flush bars side by side —
orange spend (left axis, sats) and red tokens (right axis, tokens) — with a gap
between buckets. The chart grows to fill the terminal viewport (minimum 4 rows)
and the footer stays pinned to the bottom. The separate token sparkline is gone. - Bucketing by window:
24hhourly,7din 6-hour buckets (7 × 4, folded
from the per-day hourly aggregates instead of 168 hourly buckets),30ddaily,
andallfolded into ISO weeks (Monday). - Axis ceilings round up (e.g.
10.0k/10.0M) instead of using the exact
peaks, and merged buckets are scaled against their summed peaks at narrow
widths, so a full bar can no longer look like it overshoots the y-axis. - Reserved headroom row for the peak ticks; legend swatches reset before their
colour so a preceding dim segment no longer washes them out. - Legacy daemon support: when the daemon has no window support the TUI shows
"All-time usage only: upgrade the daemon to enable time windows." and pins to
all-time, instead of rendering empty windows. The timezone argument is still
sent, so an upgrade restores windowing without a restart.
Daemon
- Timezone-correct usage windows:
timezone=accepts an IANA zone (400 on an
invalid one) and calendar arithmetic — day/week boundaries, DST transitions,
skipped and repeated wall times — is evaluated in that zone. An owner filter
that matches nothing is an empty selection, not an unfiltered query. - Perf — IANA windows aggregate in SQL: the requested range is split at each
UTC-offset transition and grouped in the driver per segment with that segment's
offset, so memory scales with buckets instead of rows.7don a 20k-row
database drops from ~570 ms to ~120 ms; summaries were verified byte-identical
to the previous implementation for Asia/Singapore, America/New_York and
Europe/Berlin across today/7d/30d/all. - Perf — startup stops re-doing bootstrap: the immediate forced relay refresh
is dropped (scheduled and explicit refreshes still force discovery), and
concurrent/modelsreaders plus startup now share a single cold population
pass instead of each fetching every provider. A failed pass clears so the next
request retries, and a genuinely cold pass stays authoritative until it settles
so onboarding cannot mistake a partial cache for a complete model list. - Provider policy reports what actually happened:
providers enable/disable
output distinguishes providers that are actually disabled from those that
remain enabled under the effective policy, and prints the effective review
labels. Manual overrides and default labels are preserved, label matching is
resolved before manual overrides are read so concurrent index edits are not
overwritten, and overrides are only written when the request supplied indices. - Onboarding waits for models: the OpenCode, OpenClaw and Pi installers wait
up to 5 minutes for a non-empty/models(progress line every 10 s), and an
installer failure during onboarding now warns and points atroutstrd refresh
instead of failing onboarding after the daemon and API key already exist. - Integrations fail loudly: the integration installers now throw on failure
instead of silently returning, so scheduled and bulk refreshes count real
failures while onboarding stays tolerant.
Dependencies
@routstr/sdk ^0.4.11 → ^0.4.12
SDK changes since routstrd 0.4.16:
- Caller-side provider-fetch deadlines:
AbortSignal.timeoutis not honoured
during connect on the deployed runtime (Bun 1.2.22), so a single unreachable
provider held an entire model-refresh or mint-discovery pass open — measured at
up to ~136 s against the straggler hosts. Fetches are now bounded by an
independent deadline that settles in ~3 s regardless of the socket. - Model-path lookups are bounded the same way, since the per-model path
lookup runs inside routing. - The four relay filters refresh concurrently (previously awaited one at a
time, so a slow relay cost its timeout up to four times — ~20 s of serialised
waiting on a cold start), and unchanged model shards are skipped during
incremental discovery instead of being rewritten. - Mint-discovery failures are summarised like model refreshes: one warning
per newly-failed or changed provider plus a single per-pass summary line,
instead of a raw warning and a full stack trace per provider every ~21-minute
pass. Unchanged outages age down todebug.
Compatibility
No breaking changes. routstrd 0.4.17 builds against @routstr/sdk ^0.4.12; the
provider review-label commands require the SDK API that first shipped in 0.4.11.
Full Changelog: v0.4.16...v0.4.17