Skip to content

v0.4.17

Latest

Choose a tag to compare

@github-actions github-actions released this 13 Oct 14:08
· 4 commits to main since this release

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: 24h hourly, 7d in 6-hour buckets (7 × 4, folded
    from the per-day hourly aggregates instead of 168 hourly buckets), 30d daily,
    and all folded 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. 7d on 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 /models readers 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 at routstrd 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.timeout is 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 to debug.

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