Skip to content

Wayfinder Router 2026.7.0 - the "run-it-anywhere" release

Latest

Choose a tag to compare

@tcballard tcballard released this 01 Jul 06:34

Leave the gateway running: install it as a local service, and route offline-first when there's no network. Around those two features is a code audit that closes reliability and correctness gaps across the request path and the surface tools. The routing decision is unchanged — still instant, offline, no model call (WF-ADR-0001).

Run the gateway as a local service

wayfinder-router service install registers Wayfinder with launchd (macOS) or systemd (Linux) so it auto-starts at login on 127.0.0.1:8088 and restarts if it exits. Point every OpenAI-compatible app at it once:

wayfinder-router service install
export OPENAI_BASE_URL=http://127.0.0.1:8088/v1

uninstall, status, and --print (emit the unit without installing) round it out. Packaging only; your keys stay in the config (WF-ADR-0038).

Offline-first delivery

Set [gateway] offline = true (or send X-Wayfinder-Offline: true per request) and Wayfinder serves the local tier and never calls cloud — for flights, air-gapped machines, or privacy. It reuses the existing degrade + breaker, marks the response with x-wayfinder-router-offline: true, and now takes precedence over the response cache (no dearer-tier replay) and a hard budget block (delivered from local, not a 402). Visible at /healthz, in service status, and in the ?debug payload (WF-ADR-0039).

Hardening — a code audit, turned into fixes

Each ships with a regression test; none touches the routing decision.

Request path

  • A bad/expired upstream key (401/403/407) now trips the circuit breaker instead of counting as a success, so failover engages.
  • The gateway-wide rate limit runs before virtual-key auth, so a token flood is shed with 429, not 401'd one at a time.
  • Budget enforcement reads the live config's pricing, so a hot reload takes effect on the next request, not one late.

Claude Code adapter

  • Parallel tool calls survive streaming — interleaved calls are buffered per index instead of being merged into one synthetic block (WF-DESIGN-0011).

Surface tools

  • Configure saves back to the config it loaded (no stray file when editing from a subdirectory).
  • An unknown onboarding arm returns 400, not 500.
  • Thread ids use eight random bytes, so same-second chats can't overwrite each other.
  • service install verifies the unit loaded and exits non-zero on failure instead of printing "installed".

Input guards

  • A malformed / old-schema savings ledger no longer crashes /v1/savings.
  • calibrate --l2 0 (or negative) errors cleanly instead of raising ZeroDivisionError.
  • Non-UTF-8 input files give a usage error, not a traceback.
  • keys new escapes ids/tags, so the emitted TOML always round-trips.
  • The launchd generator resolves ~, so a plist built without a log dir spawns.
  • cross_validated_accuracy rejects k < 2 instead of returning a misleading 0.0.

Routing controls

  • /scope and /sticky now actually route in both backends, not just the status bar.

The suite is up to 604 tests (constant-time key matching, a parsed /metrics exposition, an injectable rate-limiter clock).

Upgrading

pip install -U "wayfinder-router[gateway]"

Additive — existing configs, clients, and the routing decision are unchanged.

Full changelog: https://github.com/itsthelore/wayfinder-router/blob/main/CHANGELOG.md