Added
- ๐งช Smart Model Router v2 engine (built in): the regular router daemon (
--daemon-bg, historical port) now runs the hardened v2 engine - same command, same port, same endpoints, existing setups upgrade transparently. A hardened parallel beta ran on port 19380 during development; it is retired by this release. Open the TUI overlay withShift+V, or use the "Router v2" page in the Web Dashboard (BETA badge on both surfaces). - ๐ก๏ธ Content-validated failover: a 200 only counts as a success when the answer holds real content. Empty
choices, embeddederrorobjects or content-less replies now fail over to the next model, in both streaming and non-streaming. This closes the biggest v1 blind spot where free providers serving empty 200s were reported as successes. - โฑ๏ธ Body-read timeout: a provider that sends headers but trickles (or never sends) the body can no longer hang your coding tool; the read is raced against
router.failover.bodyReadTimeoutMs(default 30s) and fails over. - ๐ฅ Quota-aware routing: models answering 429 are paused for their
Retry-Afterwindow and skipped; when every model is paused the client gets a proper429+Retry-Afterinstead of a generic 503. - โ๏ธ Blame attribution: client-caused 4xx (bad payload, unsupported fields) fail over but never damage healthy models' circuit breakers, and client disconnects never mark failures.
- ๐พ Persisted circuit breakers: breaker state survives daemon restarts, with a new amber
DEGRADEDwarning state (60% of the failure threshold) and escalating cooldowns for repeatedly-tripping models. - ๐ Decision traces: every response carries
x-fcm-v2-model,x-fcm-v2-attemptsandx-fcm-v2-decisionheaders, and every request chain (attempts, statuses, skip reasons) is persisted locally and rendered in the TUI overlay and the web page. Routing metadata only: no prompts, no keys. - ๐ค Anthropic
/v1/messagessupport on the v2 port: request, response and SSE stream translation (includingtool_use/input_json_delta), so Anthropic-protocol agents can use the router directly. - ๐ Pinned-model requests:
model: "fcm:@provider/modelId"routes to one exact model through the full chain with failover disabled. NewCtrl+T(test selected model) andCtrl+Shift+T(test all visible models) TUI hotkeys use it to test the real routing path, unlike the direct-to-providerCtrl+A/Ctrl+Ubenchmarks. - ๐ Last-resort model: optional
router.failover.lastResortModelconfig gives a designated model one final shot when the whole set fails. - โก Fast first boot: v2 listens before its first probe pass, removing the old first-boot stall where the router port stayed dark for up to ~36 seconds.
Security
- ๐ Client
x-api-keyheaders are now stripped before proxying to upstream providers on v2, so the local router token can never leak to a provider.
Fixed
- ๐ Ghost "active requests" no longer accumulate in v2 stats when a request is rejected before routing (v1 leaks one entry per rejected request until restart).